24 #include <opencog/util/oc_assert.h>
25 #include <opencog/util/Logger.h>
34 using namespace opencog;
62 #define dbgprt(f, varargs...) printf(f, ##varargs)
64 #define dbgprt(f, varargs...)
71 printf (
"%s\n", str.c_str());
79 printf (
"%s (invalid handle)\n", msg);
83 printf (
"%s %s\n", msg, str.c_str());
93 #define NO_SELF_GROUNDING 1
98 #define POPSTK(stack,soln) { \
99 OC_ASSERT(not stack.empty(), \
100 "Unbalanced stack " #stack); \
101 soln = stack.top(); \
105 #define POPSTK(stack,soln) { \
106 soln = stack.top(); \
122 if (1 != lp->getArity())
123 throw InvalidParamException(TRACE_INFO,
124 "QuoteLink has unexpected arity!");
138 #ifdef NO_SELF_GROUNDING
158 OC_ASSERT (NULL != np,
159 "ERROR: expected variable to be a node, got this: %s\n",
162 #ifdef NO_SELF_GROUNDING
167 if (VARIABLE_NODE == hg->
getType() and
181 dbgprt(
"Found grounding of variable:\n");
182 prtmsg(
"$$ variable: ", hp);
183 prtmsg(
"$$ ground term: ", hg);
203 #ifdef NO_SELF_GROUNDING
204 #if THIS_CANT_BE_RIGHT
209 (VARIABLE_NODE != tp or
214 #endif // THIS_CANT_BE_RIGHT
229 dbgprt(
"Found matching nodes\n");
230 prtmsg(
"# pattern: ", hp);
247 const HandleSeq &osg = lg->getOutgoingSet();
252 size_t osg_size = osg.size();
253 size_t osp_size = osp.size();
254 size_t max_size = std::max(osg.size(), osp.size());
271 for (
size_t i=0; i<max_size; i++)
274 if (i < osp_size and i < osg_size)
277 else if (i < osp_size)
290 dbgprt(
"tree_comp down link match=%d\n", match);
292 if (not match)
return false;
297 if (not match)
return false;
324 size_t iend = osp.size();
329 dbgprt(
"tree_comp resume choice search at %zu of %zu of term=%s, "
331 icurr, iend, ptm->toString().c_str(),
choose_next);
347 dbgprt(
"tree_comp or_link choice %zu of %zu\n", icurr, iend);
385 catch(...) { istart = 0; fresh =
true; }
395 catch(...) { have =
false;}
404 static int facto (
int n) {
return (n==1)? 1 : n * facto(n-1); };
555 const HandleSeq& osg = lg->getOutgoingSet();
558 size_t osg_size = osg.size();
559 size_t osp_size = osp.size();
560 size_t max_size = std::max(osg.size(), osp.size());
567 "Impossible situation! BUG!");
577 int num_perms = facto(mutation.size());
578 dbgprt(
"tree_comp resume unordered search at %d of %d of term=%s "
579 "take_step=%d have_more=%d\n",
580 perm_count[
Unorder(ptm, hg)], num_perms, ptm->toString().c_str(),
585 dbgprt(
"tree_comp explore unordered perm %d of %d of term=%s\n",
586 perm_count[
Unorder(ptm, hg)], num_perms,
587 ptm->toString().c_str());
591 for (
size_t i=0; i<max_size; i++)
594 if (i < osp_size and i < osg_size)
597 else if (i < osp_size)
613 "This shouldn't happen. Impossible situation! BUG!");
620 "Impossible: should have matched!");
646 dbgprt(
"Good permutation %d for term=%s have_more=%d\n",
647 perm_count[
Unorder(ptm, hg)], ptm->toString().c_str(),
654 dbgprt(
"Above permuation %d failed term=%s\n",
655 perm_count[
Unorder(ptm, hg)], ptm->toString().c_str());
662 perm_count[
Unorder(ptm, hg)] ++;
664 }
while (std::next_permutation(mutation.begin(), mutation.end()));
667 dbgprt(
"Exhausted all permuations of term=%s\n", ptm->toString().c_str());
686 dbgprt(
"tree_comp fresh start unordered link term=%s\n",
687 ptm->toString().c_str());
688 perm_count[
Unorder(ptm, hg)] = 0;
690 perm = ptm->getOutgoingSet();
691 sort(perm.begin(), perm.end());
703 catch(...) {
return false; }
711 perm_count_stack.push(perm_count);
719 POPSTK(perm_count_stack, perm_count);
777 if (not
in_quote and QUOTE_LINK == tp)
808 #ifdef NO_SELF_GROUNDING
827 prtmsg(
"found bound variable in grounding tree:", vh);
828 prtmsg(
"matching pattern is:", hp);
829 prtmsg(
"proposed grounding is:", hg);
832 dbgprt(
"miscompare; var is not in pattern, or its not quoted\n");
841 if (not match)
return false;
844 prtmsg(
"> tree_compare", hp);
851 if (CHOICE_LINK == tp)
904 const Handle& clause_root)
916 }
catch (
const std::out_of_range&) {
917 dbgprt(
"Pattern term not found for %s, clause=%s\n",
918 hp->toShortString().c_str(),
919 clause_root->toShortString().c_str());
950 const Handle& clause_root)
954 size_t sz = iset.size();
955 dbgprt(
"Looking upward for term=%s have %zu branches\n",
956 ptm->toString().c_str(), sz);
958 for (
size_t i = 0; i < sz; i++) {
959 dbgprt(
"Try upward branch %zu of %zu for term=%s propose=%lu\n",
960 i, sz, ptm->toString().c_str(),
Handle(iset[i]).
value());
965 dbgprt(
"Found upward soln = %d\n", found);
1003 const Handle& clause_root)
1009 if ((hg == clause_root)
1023 dbgprt(
"Step to next permuation\n");
1030 dbgprt(
"No more unordered permutations\n");
1040 const Handle& clause_root)
1044 if (CHOICE_LINK != hp->
getType())
1047 dbgprt(
"Begin choice branchpoint iteration loop\n");
1062 dbgprt(
"Step to next choice\n");
1068 dbgprt(
"Exhausted all choice possibilities\n");
1091 const Handle& clause_root)
1095 dbgprt(
"Checking pattern term=%s for soln by %lu\n",
1096 ptm->toString().c_str(), hg.
value());
1102 dbgprt(
"Pattern term=%s NOT solved by %lu\n",
1103 ptm->toString().c_str(), hg.
value());
1108 dbgprt(
"Pattern term=%s solved by %lu move up\n",
1109 ptm->toString().c_str(), hg.
value());
1114 bool found =
do_term_up(ptm, hg, clause_root);
1162 const Handle& clause_root)
1171 if (hp == clause_root)
1179 dbgprt(
"Term = %s of clause UUID = %lu has ground, move upwards.\n",
1180 ptm->toString().c_str(), clause_root.
value());
1219 for (
auto evit = evra.first; evit != evra.second; evit++)
1224 prtmsg(
"Term inside evaluatable, move up to it's top:\n",
1239 dbgprt(
"After evaluating clause, found = %d\n", found);
1254 if (CHOICE_LINK != hi->
getType())
1257 dbgprt(
"After moving up the clause, found = %d\n", found);
1260 if (hi == clause_root)
1262 dbgprt(
"Exploring ChoiceLink at root\n");
1274 dbgprt(
"Exploring ChoiceLink below root\n");
1277 "Something is wrong with the ChoiceLink code");
1280 if (
do_term_up(parent, hg, clause_root)) found =
true;
1302 dbgprt(
"optional clause match callback match=%d\n", match);
1307 dbgprt(
"clause match callback match=%d\n", match);
1309 if (not match)
return false;
1312 prtmsg(
"---------------------\nclause:", clause_root);
1334 dbgprt (
"==================== FINITO!\n");
1341 prtmsg(
"Next clause is\n", curr_root);
1342 dbgprt(
"This clause is %s\n",
1344 dbgprt(
"This clause is %s\n",
1346 "dynamically evaluatable" :
"non-dynamic");
1347 prtmsg(
"Joining variable is", joiner);
1362 "Error: joining handle has not been grounded yet!");
1376 while ((
false == found) and
1382 dbgprt (
"Exhausted search for optional clause, cb=%d\n", match);
1394 prtmsg(
"Next optional clause is", curr_root);
1397 dbgprt (
"==================== FINITO BANDITO!\n");
1517 const std::set<Handle>& live)
1521 if (live.size() < 2)
return 1;
1523 unsigned int count = 0;
1524 for (
const Handle& v : live)
1538 bool search_optionals)
1547 unsigned int thinnest_joint = UINT_MAX;
1548 unsigned int thinnest_clause = UINT_MAX;
1549 bool unsolved =
false;
1552 std::set<Handle> ungrounded_vars;
1555 std::multimap<std::size_t, Handle> thick_vars;
1564 thick_vars.insert(std::make_pair(incoming_set_size, v));
1566 else ungrounded_vars.insert(v);
1568 catch(...) { ungrounded_vars.insert(v); }
1578 for (
auto tckvar : thick_vars)
1580 std::size_t pursue_thickness = tckvar.first;
1581 const Handle& pursue = tckvar.second;
1583 if (pursue_thickness > thinnest_joint)
break;
1586 catch(...) {
continue; }
1589 for (
const Handle& root : rl)
1593 and (search_black or not
is_black(root))
1596 unsigned int root_thickness =
thickness(root, ungrounded_vars);
1597 if (root_thickness < thinnest_clause)
1599 thinnest_clause = root_thickness;
1600 thinnest_joint = pursue_thickness;
1601 unsolved_clause = root;
1620 issued.insert(unsolved_clause);
1648 OC_ASSERT(not
in_quote,
"Can't posssibly happen!");
1769 const Handle& first_clause)
1778 issued.insert(first_clause);
1802 dbgprt(
"Clause is matchable; start matching it.\n");
1811 dbgprt(
"Clause is evaluatable; start evaluating it\n");
1813 dbgprt(
"Post evaluating clause, found = %d\n", found);
1873 const std::map<Handle, Handle> &vars,
1874 const std::map<Handle, Handle> &clauses)
1876 printf(
"\nVariable groundings:\n");
1879 std::map<Handle, Handle>::const_iterator j = vars.begin();
1880 std::map<Handle, Handle>::const_iterator jend = vars.end();
1881 for (; j != jend; ++j)
1887 if (VARIABLE_NODE != var->
getType())
continue;
1891 printf(
"ERROR: ungrounded variable %s\n",
1896 printf(
"\t%s maps to %s\n",
1902 printf(
"\nGrounded clauses:\n");
1903 std::map<Handle, Handle>::const_iterator
m;
1905 for (m = clauses.begin(); m != clauses.end(); ++
m, ++i)
1910 prtmsg(
"ERROR: ungrounded clause: ", mf);
1913 std::string str = m->second->toShortString();
1914 printf (
"%d. %s\n", i, str.c_str());
1923 const std::set<Handle> &vars,
1924 const std::vector<Handle> &clauses)
1926 printf(
"\nClauses:\n");
1929 printf(
"\nVars:\n");
virtual bool optional_clause_match(const Handle &pattrn, const Handle &grnd)=0
virtual bool evaluate_sentence(const Handle &eval, const std::map< Handle, Handle > &gnds)=0
static bool prt(const Handle &h)
bool explore_neighborhood(const Handle &, const Handle &, const Handle &)
PatternTermSeq Permutation
std::stack< SolnMap > var_solutn_stack
PatternMatchEngine(PatternMatchCallback &, const Variables &, const Pattern &)
std::shared_ptr< PatternTerm > PatternTermPtr
unsigned int _clause_stack_depth
std::vector< Handle > HandleSeq
a list of handles
std::set< Handle > evaluatable_holders
std::set< Handle > varset
static void print_solution(const std::map< Handle, Handle > &vars, const std::map< Handle, Handle > &clauses)
bool do_term_up(const PatternTermPtr &, const Handle &, const Handle &)
std::map< Handle, Handle > var_grounding
#define POPSTK(stack, soln)
virtual std::string toShortString(std::string indent="")=0
static bool is_quoted_in_tree(const Handle &tree, const Handle &atom)
ClassServer & _classserver
std::map< Handle, Handle > clause_grounding
virtual bool post_link_match(const LinkPtr &patt_link, const LinkPtr &grnd_link)
bool have_choice(const PatternTermPtr &, const Handle &)
static bool any_unquoted_in_tree(const Handle &tree, const std::set< Handle > &atoms)
std::shared_ptr< Link > LinkPtr
std::pair< PatternTermPtr, Handle > Choice
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
virtual IncomingSet get_incoming_set(const Handle &h)
static NodePtr NodeCast(const Handle &h)
std::vector< PatternTermPtr > PatternTermSeq
const Variables * _varlist
bool get_next_thinnest_clause(bool, bool, bool)
void clause_stacks_clear(void)
bool self_compare(const Handle &)
void clause_stacks_push(void)
bool explore_link_branches(const PatternTermPtr &, const Handle &, const Handle &)
static const Handle UNDEFINED
#define dbgprt(f, varargs...)
std::stack< SolnMap > term_solutn_stack
bool explore_choice_branches(const PatternTermPtr &, const Handle &, const Handle &)
bool quote_compare(const PatternTermPtr &, const Handle &)
unsigned int thickness(const Handle &, const std::set< Handle > &)
bool is_black(const Handle &h)
virtual bool clause_match(const Handle &pattrn_link_h, const Handle &grnd_link_h)
virtual bool variable_match(const Handle &patt_node, const Handle &grnd_node)=0
std::pair< PatternTermPtr, Handle > Unorder
void clear_current_state(void)
PatternMatchCallback & _pmc
bool isA(Type sub, Type super)
virtual bool link_match(const LinkPtr &patt_link, const LinkPtr &grnd_link)=0
bool explore_single_branch(const PatternTermPtr &, const Handle &, const Handle &)
bool variable_compare(const Handle &, const Handle &)
bool explore_redex(const Handle &, const Handle &, const Handle &)
virtual bool node_match(const Handle &patt_node, const Handle &grnd_node)=0
std::unordered_multimap< Handle, Handle > in_evaluatable
static LinkPtr LinkCast(const Handle &h)
ChoiceState _choice_state
std::stack< IssuedSet > issued_stack
bool unorder_compare(const PatternTermPtr &, const Handle &, const LinkPtr &, const LinkPtr &)
std::vector< LinkPtr > IncomingSet
static const PatternTermPtr UNDEFINED
virtual bool grounding(const std::map< Handle, Handle > &var_soln, const std::map< Handle, Handle > &term_soln)=0
std::shared_ptr< Node > NodePtr
ConnectMap connectivity_map
bool is_optional(const Handle &h)
std::stack< ChoiceState > choice_stack
bool do_next_clause(void)
unsigned short Type
type of Atoms, represented as short integer (16 bits)
static void print_term(const std::set< Handle > &vars, const std::vector< Handle > &clauses)
std::set< Handle > optionals
size_t getIncomingSetSize()
Get the size of the incoming set.
bool explore_clause(const Handle &, const Handle &, const Handle &)
bool ordered_compare(const PatternTermPtr &, const Handle &, const LinkPtr &, const LinkPtr &)
size_t curr_choice(const PatternTermPtr &, const Handle &, bool &)
bool explore_term_branches(const Handle &, const Handle &, const Handle &)
bool clause_accept(const Handle &, const Handle &)
Permutation curr_perm(const PatternTermPtr &, const Handle &, bool &)
bool explore_up_branches(const PatternTermPtr &, const Handle &, const Handle &)
bool is_evaluatable(const Handle &h)
void get_next_untried_clause(void)
void clause_stacks_pop(void)
bool tree_compare(const PatternTermPtr &, const Handle &, Caller)
static void prtmsg(const char *msg, const Handle &h)
bool choice_compare(const PatternTermPtr &, const Handle &, const LinkPtr &, const LinkPtr &)
bool have_perm(const PatternTermPtr &, const Handle &)
ConnectTermMap connected_terms_map
bool node_compare(const Handle &, const Handle &)
Compare two nodes, one in the pattern, one proposed grounding.
virtual bool fuzzy_match(const Handle &ph, const Handle &gh)
std::vector< Handle > RootList
std::stack< PermState > perm_stack
static bool is_unquoted_in_tree(const Handle &tree, const Handle &atom)