OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
VariableList.cc
Go to the documentation of this file.
1 /*
2  * VariableList.cc
3  *
4  * Copyright (C) 2009, 2014, 2015 Linas Vepstas
5  *
6  * Author: Linas Vepstas <linasvepstas@gmail.com> January 2009
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
11  * exceptions
12  * at http://opencog.org/wiki/Licenses
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public
20  * License
21  * along with this program; if not, write to:
22  * Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
27 #include <opencog/atoms/TypeNode.h>
28 
29 #include "VariableList.h"
30 
31 using namespace opencog;
32 
34 {
35  for (const Handle& h: oset)
36  {
37  Type t = h->getType();
38  if (VARIABLE_NODE == t)
39  {
40  _varlist.varset.insert(h); // tree (unordered)
41  _varlist.varseq.push_back(h); // vector (ordered)
42  }
43  else if (TYPED_VARIABLE_LINK == t)
44  {
45  get_vartype(h);
46  }
47  else
48  throw InvalidParamException(TRACE_INFO,
49  "Expected a VariableNode or a TypedVariableLink, got: %s",
50  classserver().getTypeName(t).c_str());
51  }
52  build_index();
53 }
54 
57  : Link(VARIABLE_LIST, oset, tv, av)
58 {
59  validate_vardecl(oset);
60 }
61 
64  : Link(t, oset, tv, av)
65 {
66  // derived classes have a different initialization order
67  if (VARIABLE_LIST != t) return;
68  validate_vardecl(oset);
69 }
70 
72  : Link(l)
73 {
74  // Type must be as expected
75  Type tscope = l.getType();
76  if (not classserver().isA(tscope, VARIABLE_LIST))
77  {
78  const std::string& tname = classserver().getTypeName(tscope);
79  throw InvalidParamException(TRACE_INFO,
80  "Expecting a VariableList, got %s", tname.c_str());
81  }
82 
83  // Dervided types have a different initialization sequence
84  if (VARIABLE_LIST != tscope) return;
86 }
87 
88 /* ================================================================= */
89 typedef std::pair<Handle, const std::set<Type> > ATPair;
90 
114 void VariableList::get_vartype(const Handle& htypelink)
115 {
116  const std::vector<Handle>& oset = LinkCast(htypelink)->getOutgoingSet();
117  if (2 != oset.size())
118  {
119  throw InvalidParamException(TRACE_INFO,
120  "TypedVariableLink has wrong size, got %lu", oset.size());
121  }
122 
123  Handle varname = oset[0];
124  Handle vartype = oset[1];
125 
126  // The vartype is either a single type name, or a list of typenames.
127  Type t = vartype->getType();
128  if (TYPE_NODE == t)
129  {
130  Type vt = TypeNodeCast(vartype)->get_value();
131  std::set<Type> ts = {vt};
132  _varlist.typemap.insert(ATPair(varname, ts));
133  _varlist.varset.insert(varname);
134  _varlist.varseq.push_back(varname);
135  }
136  else if (TYPE_CHOICE == t)
137  {
138  std::set<Type> ts;
139 
140  const std::vector<Handle>& tset = LinkCast(vartype)->getOutgoingSet();
141  size_t tss = tset.size();
142  for (size_t i=0; i<tss; i++)
143  {
144  Handle h(tset[i]);
145  Type var_type = h->getType();
146  if (TYPE_NODE != var_type)
147  {
148  throw InvalidParamException(TRACE_INFO,
149  "VariableChoice has unexpected content:\n"
150  "Expected TypeNode, got %s",
151  classserver().getTypeName(h->getType()).c_str());
152  }
153  Type vt = TypeNodeCast(h)->get_value();
154  ts.insert(vt);
155  }
156 
157  _varlist.typemap.insert(ATPair(varname,ts));
158  _varlist.varset.insert(varname);
159  _varlist.varseq.push_back(varname);
160  }
161  else
162  {
163  throw InvalidParamException(TRACE_INFO,
164  "Unexpected contents in TypedVariableLink\n"
165  "Expected TypeNode or TypeChoice, got %s",
166  classserver().getTypeName(t).c_str());
167  }
168 }
169 
170 /* ================================================================= */
193 {
194  // Expecting the declaration list to be either a single
195  // variable, or a list of variable declarations
196  Type tdecls = hdecls->getType();
197  if ((VARIABLE_NODE == tdecls) or
198  NodeCast(hdecls)) // allow *any* node as a variable
199  {
200  _varlist.varset.insert(hdecls);
201  _varlist.varseq.push_back(hdecls);
202  }
203  else if (TYPED_VARIABLE_LINK == tdecls)
204  {
205  get_vartype(hdecls);
206  }
207  else if (VARIABLE_LIST == tdecls or LIST_LINK == tdecls)
208  {
209  // The list of variable declarations should be .. a list of
210  // variables! Make sure its as expected.
211  const std::vector<Handle>& dset = LinkCast(hdecls)->getOutgoingSet();
212  validate_vardecl(dset);
213  }
214  else
215  {
216  throw InvalidParamException(TRACE_INFO,
217  "Expected a VariableList holding variable declarations");
218  }
219  build_index();
220 }
221 
222 /* ================================================================= */
233 bool VariableList::is_type(const Handle& h) const
234 {
235  // The arity must be one for there to be a match.
236  if (1 != _varlist.varset.size()) return false;
237 
238  // No type restrictions.
239  if (0 == _varlist.typemap.size()) return true;
240 
241  // Check the type restrictions.
242  VariableTypeMap::const_iterator it =
243  _varlist.typemap.find(_varlist.varseq[0]);
244  const std::set<Type> &tchoice = it->second;
245 
246  Type htype = h->getType();
247  std::set<Type>::const_iterator allow = tchoice.find(htype);
248  return allow != tchoice.end();
249 }
250 
251 /* ================================================================= */
262 bool VariableList::is_type(const HandleSeq& hseq) const
263 {
264  // The arity must be one for there to be a match.
265  size_t len = hseq.size();
266  if (_varlist.varset.size() != len) return false;
267  // No type restrictions.
268  if (0 == _varlist.typemap.size()) return true;
269 
270  // Check the type restrictions.
271  for (size_t i=0; i<len; i++)
272  {
273  VariableTypeMap::const_iterator it =
274  _varlist.typemap.find(_varlist.varseq[i]);
275  if (it == _varlist.typemap.end()) continue; // no restriction
276 
277  const std::set<Type> &tchoice = it->second;
278  Type htype = hseq[i]->getType();
279  std::set<Type>::const_iterator allow = tchoice.find(htype);
280  if (allow == tchoice.end()) return false;
281  }
282  return true;
283 }
284 
285 /* ================================================================= */
293 {
294  if (0 < _varlist.index.size()) return;
295  size_t sz = _varlist.varseq.size();
296  for (size_t i=0; i<sz; i++)
297  {
298  _varlist.index.insert(std::pair<Handle, unsigned int>(_varlist.varseq[i], i));
299  }
300 }
301 
302 /* ================================================================= */
352  const HandleSeq& args) const
353 {
354  if (args.size() != _varlist.varseq.size())
355  throw InvalidParamException(TRACE_INFO,
356  "Incorrect numer of arguments specified, expecting %lu got %lu",
357  _varlist.varseq.size(), args.size());
358 
359  if (not is_type(args))
360  throw InvalidParamException(TRACE_INFO,
361  "Arguments fail to match variable declarations");
362 
363  return substitute_nocheck(fun, args);
364 }
365 
367  const HandleSeq& args) const
368 {
369  // If it is a singleton, just return that singleton.
370  std::map<Handle, unsigned int>::const_iterator idx;
371  idx = _varlist.index.find(term);
372  if (idx != _varlist.index.end())
373  return args.at(idx->second);
374 
375  // If its a node, and its not a variable, then it is a constant,
376  // and just return that.
377  LinkPtr lterm(LinkCast(term));
378  if (NULL == lterm) return term;
379 
380  // QuoteLinks halt the reursion
381  if (QUOTE_LINK == term->getType()) return term;
382 
383  // Recursively fill out the subtrees.
384  HandleSeq oset;
385  for (const Handle& h : lterm->getOutgoingSet())
386  {
387  oset.push_back(substitute_nocheck(h, args));
388  }
389  return Handle(createLink(term->getType(), oset));
390 }
391 
392 /* ===================== END OF FILE ===================== */
static TypeNodePtr TypeNodeCast(const Handle &h)
Definition: TypeNode.h:88
#define createLink
Definition: Link.h:269
Variables _varlist
Unbundled variables and types for them.
Definition: VariableList.h:52
void validate_vardecl(const Handle &)
HandleSeq varseq
Definition: Pattern.h:64
friend class Handle
Definition: Atom.h:79
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
std::set< Handle > varset
Definition: Pattern.h:65
bool is_type(const Handle &) const
std::shared_ptr< TruthValue > TruthValuePtr
Definition: TruthValue.h:85
std::shared_ptr< AttentionValue > AttentionValuePtr
Type getType() const
Definition: Atom.h:197
std::shared_ptr< Link > LinkPtr
Definition: Atom.h:53
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
Definition: ClassServer.cc:159
void get_vartype(const Handle &)
static NodePtr NodeCast(const Handle &h)
Definition: Node.h:113
std::map< Handle, unsigned int > index
Definition: Pattern.h:67
Handle substitute_nocheck(const Handle &, const HandleSeq &) const
tuple args
Definition: benchmark.py:79
const std::string & getTypeName(Type type)
Definition: ClassServer.cc:148
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
Handle substitute(const Handle &tree, const HandleSeq &vals) const
VariableList(Type, const HandleSeq &, TruthValuePtr tv=TruthValue::DEFAULT_TV(), AttentionValuePtr av=AttentionValue::DEFAULT_AV())
Definition: VariableList.cc:62
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
std::pair< Handle, const std::set< Type > > ATPair
Definition: VariableList.cc:89
VariableTypeMap typemap
Definition: Pattern.h:66