30 #include <opencog/util/random.h>
38 using namespace opencog;
41 : _as(as), _configReader(as, rbs),
45 _garbage_superspace(&_as) {}
97 logger().debug(
"[BackwardChainer] ==========================================");
98 logger().debug(
"[BackwardChainer] Start of a single BC step");
99 logger().debug(
"[BackwardChainer] %d potential targets",
_targets_set.
size());
109 logger().debug(
"[BackwardChainer] Target is 'Truth Value Query'");
111 logger().debug(
"[BackwardChainer] Target is 'Variable Fullfillment Query'");
120 logger().debug(
"[BackwardChainer] End of a single BC step");
145 logger().debug(
"[BackwardChainer] Boring virtual link goal, "
154 std::vector<VarMap> kb_vmap;
161 if (not kb_match.empty())
163 logger().debug(
"[BackwardChainer] Matched something in knowledge base, "
164 "storing the grounding");
166 for (
size_t i = 0; i < kb_match.size(); ++i)
168 Handle& soln = kb_match[i];
171 logger().debug(
"[BackwardChainer] Looking at grounding "
187 logger().debug(
"[BackwardChainer] Breaking into sub-targets");
191 for (
Handle& h : sub_premises)
202 std::vector<Rule> acceptable_rules =
filter_rules(target);
204 logger().debug(
"[BackwardChainer] %d rules unifiable", acceptable_rules.size());
207 if (acceptable_rules.empty())
211 Rule standardized_rule =
214 logger().debug(
"[BackwardChainer] Selected rule "
221 std::vector<VarMap> all_implicand_to_target_mappings;
225 for (
Handle h : qrule_outputs)
236 all_implicand_to_target_mappings.push_back(temp_mapping);
240 if (all_implicand_to_target_mappings.empty())
242 logger().debug(
"[BackwardChainer] Trying sub-atom unification");
245 for (
Handle h : qrule_outputs)
248 output_expanded.insert(hs.begin(), hs.end());
249 output_expanded.erase(h);
252 for (
Handle h : output_expanded)
263 all_implicand_to_target_mappings.push_back(temp_mapping);
267 logger().debug(
"[BackwardChainer] Found %d implicand's output unifiable",
268 all_implicand_to_target_mappings.size());
278 VarMap implicand_normal_mapping = rand_element(all_implicand_to_target_mappings);
279 for (
auto& p : implicand_normal_mapping)
280 logger().debug(
"[BackwardChainer] Chosen mapping is "
281 + p.first->toShortString()
282 +
" to " + p.second->toShortString());
287 std::vector<VarMap> premises_vmap_list, premises_vmap_list_alt;
288 Handle hrule_implicant_normal_grounded = subt.
substitute(hrule_implicant, implicand_normal_mapping);
290 logger().debug(
"[BackwardChainer] Reverse grounded as "
305 VarMap implicand_quoted_mapping;
306 for (
auto& p : implicand_normal_mapping)
318 implicand_quoted_mapping[p.first] = subt.
substitute(p.second, quote_mapping);
322 Handle hrule_implicant_quoted_grounded = subt.
substitute(hrule_implicant, implicand_quoted_mapping);
324 logger().debug(
"[BackwardChainer] Alternative reverse grounded as "
330 premises_vmap_list_alt);
333 possible_premises.insert(possible_premises.end(),
334 possible_premises_alt.begin(),
335 possible_premises_alt.end());
336 premises_vmap_list.insert(premises_vmap_list.end(), premises_vmap_list_alt.begin(),
337 premises_vmap_list_alt.end());
340 logger().debug(
"[BackwardChainer] %d possible permises", possible_premises.size());
350 if (possible_premises.size() == 0)
352 logger().debug(
"[BackwardChainer] Adding rule's grounded input as Target");
354 target.
store_step(selected_rule, { hrule_implicant_normal_grounded });
363 for (
size_t i = 0; i < possible_premises.size(); i++)
365 Handle hp = possible_premises[i];
366 VarMap vm = premises_vmap_list[i];
368 logger().debug(
"[BackwardChainer] Checking permises " + hp->
toShortString());
375 logger().debug(
"[BackwardChainer] Output reverse grounded step 1 as " + output_grounded->
toShortString());
376 output_grounded = subt.
substitute(output_grounded, vm);
378 logger().debug(
"[BackwardChainer] Output reverse grounded step 2 as " + output_grounded->
toShortString());
380 std::vector<VarMap> vm_list;
383 vm.insert(implicand_normal_mapping.begin(), implicand_normal_mapping.end());
391 for (
size_t i = 0; i < grounded_premises.size(); ++i)
394 Handle& g = grounded_premises[i];
397 logger().debug(
"[BackwardChainer] Checking possible permises grounding "
404 if (not fv.
varset.empty())
417 logger().debug(
"[BackwardChainer] Added " + added->
toShortString() +
" to _as");
421 results[h].emplace(m.at(h));
439 logger().debug(
"[BackwardChainer] Before breaking apart into sub-premises");
443 target.
store_step(selected_rule, sub_premises);
445 for (
Handle& s : sub_premises)
463 std::vector<Rule> rules;
476 bool unifiable =
false;
501 output_expanded.insert(hs.begin(), hs.end());
502 output_expanded.erase(h);
505 for (
Handle h : output_expanded)
541 vector<VarMap>& vmap)
556 logger().debug(
"[BackwardChainer] Matching knowledge base with "
557 " %s and variables %s",
572 vector<map<Handle, Handle>> var_solns = pmcb.
get_var_list();
573 vector<map<Handle, Handle>> pred_solns = pmcb.
get_pred_list();
577 logger().debug(
"[BackwardChainer] Pattern matcher found %d matches",
580 for (
size_t i = 0; i < var_solns.size(); i++)
585 for (
auto& p : pred_solns[i])
589 if (std::any_of(rules.begin(), rules.end(), [&](
Rule& r) {
592 logger().debug(
"[BackwardChainer] matched clause in rule");
597 if (std::any_of(rules.begin(), rules.end(), [&](
Rule& r) {
600 logger().debug(
"[BackwardChainer] matched clause wrapping rule");
607 logger().debug(
"[BackwardChainer] matched clause not in _as");
611 i_pred_soln.push_back(p.second);
614 if (i_pred_soln.size() != pred_solns[i].size())
625 this_result = i_pred_soln[0];
627 results.push_back(this_result);
628 vmap.push_back(var_solns[i]);
643 const VarMap& premise_vmap,
644 std::vector<VarMap>& vmap_list)
655 VarMap old_map = premise_vmap;
659 for (
const auto& p : premise_vmap)
661 if (old_map.count(p.second) == 1)
663 new_map[p.first] = old_map[p.second];
664 new_map[p.second] = old_map[p.second];
665 old_map.erase(p.second);
668 new_map[p.first] = p.second;
672 new_map.insert(old_map.begin(), old_map.end());
674 vmap_list.push_back(new_map);
675 results.push_back(hpremise);
680 Handle premises = hpremise;
687 for (
const Handle& h : oset)
693 sub_premises.push_back(h);
696 if (sub_premises.size() == 1)
697 premises = sub_premises[0];
703 logger().debug(
"[BackwardChainer] Grounding " + premises->
toShortString());
705 std::vector<VarMap> temp_vmap_list;
712 for (
unsigned int i = 0; i < temp_results.size(); ++i)
714 VarMap& tvm = temp_vmap_list[i];
717 for (
const auto& p : premise_vmap)
719 if (tvm.count(p.second) == 1)
721 this_map[p.first] = tvm[p.second];
722 this_map[p.second] = tvm[p.second];
726 this_map[p.first] = p.second;
730 this_map.insert(tvm.begin(), tvm.end());
732 vmap_list.push_back(this_map);
733 results.push_back(temp_results[i]);
768 Handle temp_hsource_vardecl = temp_space.
add_atom(hsource_vardecl);
792 std::vector<std::map<Handle, Handle>> pred_list = pmcb.
get_pred_list();
793 std::vector<std::map<Handle, Handle>> var_list = pmcb.
get_var_list();
801 for (
size_t i = 0; i < pred_list.size(); ++i)
803 for (
const auto& p : pred_list[i])
807 good_map = var_list[i];
808 i = pred_list.size();
816 if (good_map.size() == 0)
820 for (
auto& p : good_map)
845 std::vector<double> weights;
846 std::for_each(rules.begin(), rules.end(),
851 return rules[randGen().randDiscrete(weights)];
870 const Handle& parent_varlist,
871 std::set<Handle> additional_free_varset)
880 for (
const Handle& h : oset)
882 Type t = h->getType();
883 if (VARIABLE_NODE == t && fv.
varset.count(h) == 1)
885 final_oset.push_back(h);
886 additional_free_varset.erase(h);
888 else if (TYPED_VARIABLE_LINK == t
891 final_oset.push_back(h);
892 additional_free_varset.erase(
LinkCast(h)->getOutgoingSet()[0]);
898 for (
const Handle& h : additional_free_varset)
900 if (fv.
varset.count(h) == 1)
901 final_oset.push_back(h);
std::set< Handle > varset
std::vector< Rule > filter_rules(const Target &target)
Rule gen_standardize_apart(AtomSpace *as)
static bool is_atom_in_tree(const Handle &tree, const Handle &atom)
void set_target(Handle init_target)
std::vector< Handle > HandleSeq
a list of handles
HandleSeq get_varseq() const
virtual std::string toShortString(std::string indent="")=0
#define createPatternLink
Handle get_vardecl() const
Rule select_rule(Target &target, const std::vector< Rule > &rules)
void store_varmap(VarMultimap &vm)
void emplace(Handle h, Handle hvardecl)
int get_maximum_iterations() const
std::vector< std::map< Handle, Handle > > get_pred_list()
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
const VarMultimap & get_chaining_result()
Handle get_handle() const
static const Handle UNDEFINED
UREConfigReader _configReader
AtomSpace _garbage_superspace
#define createVariableList
HandleSeq get_implicand_seq()
HandleSeq match_knowledge_base(const Handle &htarget, Handle htarget_vardecl, std::vector< VarMap > &vmap)
Handle instantiate(const Handle &expr, const std::map< Handle, Handle > &vars)
HandleSeq ground_premises(const Handle &htarget, const VarMap &vmap, std::vector< VarMap > &vmap_list)
HandleSeq get_free_vars_in_tree(const Handle &tree)
std::map< Handle, UnorderedHandleSet > VarMultimap
bool unify(const Handle &hsource, const Handle &hmatch, Handle hsource_vardecl, Handle hmatch_vardecl, VarMap &result)
static VariableListPtr VariableListCast(const Handle &h)
const std::vector< Rule > & get_rules() const
Handle substitute(const Handle &expr, const std::map< Handle, Handle > &vars)
static LinkPtr LinkCast(const Handle &h)
unsigned int rule_count(const Rule &r)
std::set< Handle > get_varset() const
UREConfigReader & get_config()
unordered_set< Type > _logical_link_types
std::map< Handle, Handle > VarMap
UnorderedHandleSet get_all_unique_atoms(Handle h)
std::shared_ptr< PatternLink > PatternLinkPtr
void store_step(const Rule &r, const HandleSeq &premises)
unsigned int get_selection_count() const
unsigned short Type
type of Atoms, represented as short integer (16 bits)
std::unordered_set< Handle, handle_hash > UnorderedHandleSet
a hash that associates the handle to its unique identificator
Handle add_link(Type t, const HandleSeq &outgoing, bool async=false)
Handle gen_sub_varlist(const Handle &parent, const Handle &parent_varlist, std::set< Handle > additional_free_varset)
void process_target(Target &target)
const VarMultimap & get_varmap() const
void search_set(const Handle &h)
BackwardChainer(AtomSpace &as, Handle rbs)
std::vector< std::map< Handle, Handle > > get_var_list()
Handle add_atom(AtomPtr atom, bool async=false)