OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PlusLink.cc
Go to the documentation of this file.
1 /*
2  * opencog/atoms/reduct/PlusLink.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 Plus 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  * Plus Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #include <opencog/atomspace/atom_types.h>
26 #include "PlusLink.h"
27 #include "TimesLink.h"
28 
29 using namespace opencog;
30 
34  : ArithmeticLink(PLUS_LINK, oset, tv, av)
35 {
36  init();
37 }
38 
42  : ArithmeticLink(t, oset, tv, av)
43 {
44  if (not classserver().isA(t, PLUS_LINK))
45  throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
46  init();
47 }
48 
49 PlusLink::PlusLink(const Handle& a, const Handle& b,
52  : ArithmeticLink(PLUS_LINK, a, b, tv, av)
53 {
54  init();
55 }
56 
57 PlusLink::PlusLink(Type t, const Handle& a, const Handle& b,
60  : ArithmeticLink(t, a, b, tv, av)
61 {
62  if (not classserver().isA(t, PLUS_LINK))
63  throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
64  init();
65 }
66 
68  : ArithmeticLink(l)
69 {
70  Type tscope = l.getType();
71  if (not classserver().isA(tscope, PLUS_LINK))
72  throw InvalidParamException(TRACE_INFO, "Expecting a PlusLink");
73  init();
74 }
75 
76 void PlusLink::init(void)
77 {
78  knild = 0.0;
80 
81  distributive_type = TIMES_LINK;
82 }
83 
84 // ============================================================
85 
86 double PlusLink::konsd(double a, double b) const { return a+b; }
87 
88 static inline double get_double(const Handle& h)
89 {
91  if (NULL == nnn)
92  nnn = createNumberNode(*NodeCast(h));
93 
94  return nnn->get_value();
95 }
96 
97 // ============================================================
98 
99 Handle PlusLink::kons(const Handle& fi, const Handle& fj)
100 {
101  // Are they numbers?
102  if (NUMBER_NODE == fi->getType() and
103  NUMBER_NODE == fj->getType())
104  {
105  double sum = get_double(fi) + get_double(fj);
106  return Handle(createNumberNode(sum));
107  }
108 
109  // Is fi identical to fj? If so, then replace by 2*fi
110  if (fi == fj)
111  {
112  Handle two(createNumberNode("2"));
113  return Handle(createTimesLink(fi, two));
114  }
115 
116  // If j is (TimesLink x a) and i is identical to x,
117  // then create (TimesLink x (a+1))
118  //
119  // If j is (TimesLink x a) and i is (TimesLink x b)
120  // then create (TimesLink x (a+b))
121  //
122  if (fj->getType() == TIMES_LINK)
123  {
124  bool do_add = false;
125  HandleSeq rest;
126 
127  LinkPtr ilp = LinkCast(fi);
128  LinkPtr jlp = LinkCast(fj);
129  Handle exx = jlp->getOutgoingAtom(0);
130 
131  // Handle the (a+1) case described above.
132  if (fi == exx)
133  {
134  Handle one(createNumberNode("1"));
135  rest.push_back(one);
136  do_add = true;
137  }
138 
139  // Handle the (a+b) case described above.
140  else if (fi->getType() == TIMES_LINK and
141  ilp->getOutgoingAtom(0) == exx)
142  {
143  const HandleSeq& ilpo = ilp->getOutgoingSet();
144  size_t ilpsz = ilpo.size();
145  for (size_t k=1; k<ilpsz; k++)
146  rest.push_back(ilpo[k]);
147  do_add = true;
148  }
149 
150  if (do_add)
151  {
152  const HandleSeq& jlpo = jlp->getOutgoingSet();
153  size_t jlpsz = jlpo.size();
154  for (size_t k=1; k<jlpsz; k++)
155  rest.push_back(jlpo[k]);
156 
157  // a_plus is now (a+1) or (a+b) as described above.
158  // We need to insert into the atomspace, else reduce() horks
159  // up the knil compares during reduction.
160  Handle foo(createLink(PLUS_LINK, rest));
161  if (_atomTable)
162  foo = _atomTable->getAtomSpace()->add_atom(foo);
163 
164  PlusLinkPtr ap = PlusLinkCast(foo);
165  Handle a_plus(ap->reduce());
166 
167  return Handle(createTimesLink(exx, a_plus));
168  }
169  }
170 
171  // If we are here, we've been asked to add two things of the same
172  // type, but they are not of a type that we know how to add.
173  // For example, fi and fj might be two different VariableNodes.
174  return Handle(createPlusLink(fi, fj)->reorder());
175 }
176 
177 // ============================================================
#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
Type getType() const
Definition: Atom.h:197
#define createTimesLink
Definition: TimesLink.h:71
std::shared_ptr< Link > LinkPtr
Definition: Atom.h:53
ClassServer & classserver(ClassServerFactory *=ClassServer::createInstance)
Definition: ClassServer.cc:159
static NodePtr NodeCast(const Handle &h)
Definition: Node.h:113
std::shared_ptr< NumberNode > NumberNodePtr
Definition: NumberNode.h:76
static PlusLinkPtr PlusLinkCast(const Handle &h)
Definition: PlusLink.h:65
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
static NumberNodePtr NumberNodeCast(const Handle &h)
Definition: NumberNode.h:77
std::shared_ptr< PlusLink > PlusLinkPtr
Definition: PlusLink.h:64
#define createPlusLink
Definition: PlusLink.h:71
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
#define createNumberNode
Definition: NumberNode.h:83
AtomTable * _atomTable
Definition: Atom.h:94
Handle add_atom(AtomPtr atom, bool async=false)
Definition: AtomSpace.cc:100