OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
FoldLink.cc
Go to the documentation of this file.
1 /*
2  * opencog/atoms/reduct/FoldLink.cc
3  *
4  * Copyright (C) 2015 Linas Vepstas
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License v3 as
9  * published by the Fold Software Foundation and including the exceptions
10  * at http://opencog.org/wiki/Licenses
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program; if not, write to:
19  * Fold Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #include <limits>
24 
25 #include <opencog/atomspace/atom_types.h>
28 #include "FoldLink.h"
29 
30 using namespace opencog;
31 
35  : FunctionLink(FOLD_LINK, oset, tv, av)
36 {
37  init();
38 }
39 
43  : FunctionLink(t, oset, tv, av)
44 {
45  if (not classserver().isA(t, FOLD_LINK))
46  throw InvalidParamException(TRACE_INFO, "Expecting a FoldLink");
47  init();
48 }
49 
50 FoldLink::FoldLink(Type t, const Handle& a, const Handle& b,
53  : FunctionLink(t, a, b, tv, av)
54 {
55  if (not classserver().isA(t, FOLD_LINK))
56  throw InvalidParamException(TRACE_INFO, "Expecting a FoldLink");
57  init();
58 }
59 
61  : FunctionLink(l)
62 {
63  Type tscope = l.getType();
64  if (not classserver().isA(tscope, FOLD_LINK))
65  throw InvalidParamException(TRACE_INFO, "Expecting a FoldLink");
66  init();
67 }
68 
69 void FoldLink::init(void) {}
70 
71 // ===============================================================
72 
73 // Place the result into the same atomspace we are in.
74 // XXX this is bad, buggy, uncomfortable, icky: it pollutes
75 // the atomspace with intermediate results. This needs to
76 // be fixed somehow. Right now, I don't know how.
77 #define DO_RETURN(result) { \
78  if (not _atomTable) return (result); \
79  AtomSpace* as = _atomTable->getAtomSpace(); \
80  return as->add_atom(result); \
81 }
82 
126 {
127  // The atom table is typically not set when the ctor runs.
128  // So fix it up now.
129  if (_atomTable)
131 
132  HandleSeq reduct;
133  bool did_reduce = false;
134 
135  // First, reduce the outgoing set. Loop over the outgoing set,
136  // and call reduce on everything reducible. Remove all occurances
137  // of knil, while we are at it.
138  for (const Handle& h: _outgoing)
139  {
140  Type t = h->getType();
141 
142  if (classserver().isA(t, FUNCTION_LINK))
143  {
145  // Arghh. The cast should have been enough, but we currently
146  // can't store these in the atomsapce, due to circular shared
147  // lib dependencies.
148  if (NULL == fff)
150 
151  Handle redh = fff->reduce();
152  if (h != redh)
153  {
154  did_reduce = true;
155  if (redh != knil)
156  reduct.push_back(redh);
157  }
158  else if (h != knil)
159  reduct.push_back(h);
160  else
161  did_reduce = true;
162  }
163  else if (h != knil)
164  reduct.push_back(h);
165  else
166  did_reduce = true;
167  }
168 
169  // If it reduced down to one element, we are done.
170  size_t osz = reduct.size();
171  if (1 == osz)
172  {
173  if (not did_reduce)
174  return getHandle();
175  DO_RETURN(reduct[0]);
176  }
177 
178  // Next, search for two neighboring atoms of the same type.
179  // If two atoms of the same type are found, apply kons to them.
180  // Also handle the distributive case.
181  for (size_t i = 0; i < osz-1; i++)
182  {
183  const Handle& hi = reduct[i];
184  Type it = hi->getType();
185 
186  size_t j = i+1;
187  const Handle& hj = reduct[j];
188  Type jt = hj->getType();
189 
190  // Explore two cases.
191  // i and j are the same type. Apply kons, and then recurse.
192  bool do_kons = (it == jt);
193 
194  // If j is (DistType x a) and i is identical to x,
195  // then call kons, because kons is distributive.
196  do_kons |= (jt == distributive_type and
197  LinkCast(hj)->getOutgoingAtom(0) == hi);
198 
199  if (do_kons)
200  {
201  Handle cons = kons(hi, hj);
202 
203  // If there were only two things in total we are done.
204  if (2 == osz)
205  DO_RETURN(cons);
206 
207  HandleSeq rere;
208  for (size_t k=0; k < osz; k++)
209  {
210  if (k < i)
211  rere.push_back(reduct[k]);
212  else if (k == i)
213  rere.push_back(cons);
214  else if (j < k)
215  rere.push_back(reduct[k]);
216  }
217 
218  // Create the reduced atom, and recurse.
219  // We need to insert it into the atomspace,
220  // so that knil gets placed into the atomspace
221  // when reduce is called; else the knil
222  // compares up above fail.
223  Handle foo(createLink(getType(), rere));
224  if (_atomTable)
225  foo = _atomTable->getAtomSpace()->add_atom(foo);
226 
228 
229  // Arghh. The cast should have been enough, but we currently
230  // can't store these in the atomsapce, due to circular shared
231  // lib dependencies.
232  if (NULL == flp)
234  DO_RETURN(Handle(flp->reduce()));
235  }
236  }
237 
238  // If nothing reduced, nothing to do.
239  if (not did_reduce)
240  return getHandle();
241 
242  DO_RETURN(Handle(createLink(getType(), reduct)));
243 }
244 
245 // ===========================================================
#define createLink
Definition: Link.h:269
AtomSpace * getAtomSpace(void)
Definition: AtomTable.h:166
friend class Handle
Definition: Atom.h:79
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
std::shared_ptr< TruthValue > TruthValuePtr
Definition: TruthValue.h:85
std::shared_ptr< AttentionValue > AttentionValuePtr
Handle getHandle()
Definition: Atom.h:211
Type getType() const
Definition: Atom.h:197
std::shared_ptr< FunctionLink > FunctionLinkPtr
Definition: FunctionLink.h:78
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
Definition: ClassServer.cc:159
static FunctionLinkPtr FunctionLinkCast(const Handle &h)
Definition: FunctionLink.h:79
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
AtomTable * _atomTable
Definition: Atom.h:94
Handle add_atom(AtomPtr atom, bool async=false)
Definition: AtomSpace.cc:100