OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Composition.cc
Go to the documentation of this file.
1 /*
2  * Composition.cc
3  *
4  * Copyright (C) 2015 Linas Vepstas
5  *
6  * Author: Linas Vepstas <linasvepstas@gmail.com> aPRIL 2015
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Affero General Public License v3 as
10  * published by the Free Software Foundation and including the exceptions
11  * at http://opencog.org/wiki/Licenses
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public License
19  * along with this program; if not, write to:
20  * Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
25 
26 #include "PatternMatchEngine.h"
27 #include "PatternMatchCallback.h"
28 
29 using namespace opencog;
30 
31 // Uncomment below to enable debug print
32 // #define DEBUG
33 #ifdef DEBUG
34  #define dbgprt(f, varargs...) printf(f, ##varargs)
35 #else
36  #define dbgprt(f, varargs...)
37 #endif
38 
39 static inline void prtmsg(const char * msg, const Handle& h)
40 {
41 #ifdef DEBUG
42  if (h == Handle::UNDEFINED) {
43  printf("%s (invalid handle)\n", msg);
44  return;
45  }
46  std::string str = h->toShortString();
47  printf("%s %s\n", msg, str.c_str());
48 #endif
49 }
50 
51 /* ================================================================= */
52 /*
53 TODO:
54 -- for non-connected satisfaction links, the ctor should take each
55  connected comp, and compute the mandatories, the optionals, the
56  evaluatables and the connectivity map for each comp, and store
57  thse in a meta-pseudo satisfactonLink. Should invent a new link
58  type for this...
59 
60 -- where the heck is type enforcement done, again??? Need type
61  enforcement during the redex...
62 */
63 /* ================================================================= */
64 
65 /* Reset the current variable grounding to the last grounding pushed
66  * onto the stack. */
67 #define POPGND(soln,stack) { \
68  OC_ASSERT(not stack.empty(), "Unbalanced grounding stack"); \
69  soln = stack.top(); \
70  stack.pop(); \
71 }
72 
73 /* ================================================================= */
74 
76 {
78  _stack_pattern.push(_pat);
79 }
80 
82 {
83  _varlist = _stack_variables.top();
84  _stack_variables.pop();
85 
86  _pat = _stack_pattern.top();
87  _stack_pattern.pop();
88 }
89 
91  const LinkPtr& lg)
92 {
93  // If we are here, the pattern is defined in a DefineLink. We
94  // must match to that. There seem to be two strategies for doing
95  // that: Method A: rename all of the variables in the defined
96  // pattern to be the variables we are actually using in the
97  // top-level search. This seems easy, but it is wrong, for two
98  // reasons. One reason is that, after renaming, we will have
99  // created a pattern that is probably not in the atomspace.
100  // That means that the pattern will have atoms with invalid UUID's
101  // in them, causing trouble down the line. The other problem is
102  // that the variables in the defined target now look like perfectly
103  // good grounding candidates, and so get found and reported as valid
104  // grounds. So, for these two reasons, the simple, "obvious" method
105  // A is out. Instead, we implement method B: we rename the variables
106  // that the match engine is carrying, to correspond with the variable
107  // names that are native to the definition. This way, inside the body
108  // of the definition, everything looks "normal", and should thus
109  // proceed as formal. Of course, on exit, we have to unmasquerade.
110  //
111  // By "everything looks normal", we really mean "treat this as if it
112  // was a brand-new pattern matching problem". To do this, it is very
113  // empting to just create a new PME, and let it run. The problem with
114  // that is that we have no particularly good way of integrating the
115  // new pme state, with the existing pme state. So we don't. Instead,
116  // we push all pme state, clear the decks, (almost as if starting from
117  // scratch) and then pop all pme state when we are done.
118 
119 #if LATER
120  BetaRedexPtr cpl(BetaRedexCast(lp));
121 
122  // Get the variales and clauses that make up the redex.
123  // We expect the redex body to be a PatternLink.
124  // XXX TODO perhaps we should create a special sat-redex-only
125  // link type?
126  Handle hsat(cpl->get_definition());
127  PatternLinkPtr sat_link(PatternLinkCast(hsat));
128  if (NULL == sat_link)
129  throw InvalidParamException(TRACE_INFO,
130  "Expecting PatternLink, got %s",
131  hsat->toString().c_str());
132 
133  push_redex();
134  _varlist = &sat_link->get_variables();
135  _pat = &sat_link->get_pattern();
136 
137  // To explore this redex, we've got to translate the current
138  // traversal state into the "local frame". Do this by tranlsating
139  // (masquerading) any grounded variables we may have so far.
140  const Variables& local_args(cpl->get_local_args());
141  const HandleSeq& redex_args(cpl->get_args());
142 
145 // XXX TODO handle clause_grounding as well ?? why
146 
147  SolnMap local_grounding;
148  size_t sz = redex_args.size();
149  for (size_t i=0; i< sz; i++)
150  {
151  // Relabel (masquerade) the grounded vars.
152  auto iter = var_grounding.find(redex_args[i]);
153  if (iter == var_grounding.end()) continue;
154  local_grounding.insert({local_args.varseq[i], iter->second});
155  }
156  var_grounding = local_grounding;
157 
158  if (1 != _pat->cnf_clauses.size())
159  throw InvalidParamException(TRACE_INFO,
160  "Redex can currently handle only one clause!");
161 
162  // Since there is just a single clause, just compare it as a tree
163  clause_accepted = false;
164 
165  Handle hp(_pat->cnf_clauses[0]);
166  throw RuntimeException(TRACE_INFO, "Unimplemented yet");
167  // TODO: wrap by PatternTermPtr
168  // bool found = tree_compare(hp, Handle(lg), CALL_COMP);
169  bool found = false;
170 #endif
171 
172 #if 0
173  Handle join;
174  Handle root;
175  // Follow the connectivity graph, to find a joint to
176  // somethig we know about...
177  for (const ConnectPair& vk : _connectivity_map)
178  {
179  join = vk.first;
180  if (var_grounding[join])
181  {
182  root = vk.second[0];
183  break;
184  }
185  }
186  if (Handle::UNDEFINED == root)
187  throw InvalidParamException(TRACE_INFO,
188  "Badly structured redex!");
189 
190  prtmsg("redex starting with clause: ", root);
191  curr_root = root;
192  curr_term_handle = join;
193  clause_accepted = false;
194 
195  bool found = soln_up(curr_soln_handle);
196 #endif
197 
198 #if LATER
199  dbgprt("redex finishing; found match=%d\n", found);
200 
201  // No match; restore original grounding and quit
202  if (not found)
203  {
205  pop_redex();
206  return false;
207  }
208 
209  // If there is a match, then maybe we grounded some variables.
210  // If so, we need to unmasquerade them.
211  local_grounding = var_grounding;
213  for (size_t i=0; i< sz; i++)
214  {
215  auto iter = local_grounding.find(local_args.varseq[i]);
216  if (iter != local_grounding.end())
217  var_grounding.insert({redex_args[i], iter->second});
218  }
219 
220  pop_redex();
221 #endif
222  return true;
223 }
224 
225 /* ===================== END OF FILE ===================== */
#define dbgprt(f, varargs...)
Definition: Composition.cc:36
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
std::stack< const Pattern * > _stack_pattern
std::map< Handle, Handle > var_grounding
virtual std::string toShortString(std::string indent="")=0
HandleSeq cnf_clauses
Definition: Pattern.h:102
std::shared_ptr< Link > LinkPtr
Definition: Atom.h:53
static const Handle UNDEFINED
Definition: Handle.h:77
std::stack< const Variables * > _stack_variables
static PatternLinkPtr PatternLinkCast(const Handle &h)
Definition: PatternLink.h:182
std::shared_ptr< PatternLink > PatternLinkPtr
Definition: PatternLink.h:181
bool redex_compare(const LinkPtr &, const LinkPtr &)
Definition: Composition.cc:90
std::map< Handle, Handle > SolnMap
static void prtmsg(const char *msg, const Handle &h)
Definition: Composition.cc:39