OpenCog Framework  Branch: master, revision 6f0b7fc776b08468cf1b74aa9db028f387b4f0c0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
AtomUtils.cc
Go to the documentation of this file.
1 /*
2  * AtomUtils.cc
3  *
4  * Copyright (C) 2014 OpenCog Foundation
5  *
6  * Author: William Ma <https://github.com/williampma>
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 
24 #include <iostream>
25 
26 #include <opencog/atomspace/Link.h>
27 #include <opencog/atomspace/Node.h>
29 #include "AtomUtils.h"
30 
31 namespace opencog
32 {
33 
41 {
42  HandleSeq results;
43 
44  LinkPtr lll(LinkCast(h));
45  if (lll)
46  for (const Handle& o : lll->getOutgoingSet())
47  {
48  HandleSeq sub = get_all_nodes(o);
49  results.insert(results.end(), sub.begin(), sub.end());
50  }
51  else
52  results.push_back(h);
53 
54  // Handle is copy safe, but in this case C++11 would move it
55  return results;
56 }
57 
67 {
68  UnorderedHandleSet results;
69 
70  LinkPtr lll(LinkCast(h));
71  if (lll)
72  for (const Handle& o : lll->getOutgoingSet())
73  {
75  results.insert(sub.begin(), sub.end());
76  }
77  else
78  results.insert(h);
79 
80  return results;
81 }
82 
90 {
91  HandleSeq results;
92  results.push_back(h);
93 
94  LinkPtr lll(LinkCast(h));
95  if (lll)
96  for (const Handle& o : lll->getOutgoingSet())
97  {
98  HandleSeq sub = get_all_atoms(o);
99  results.insert(results.end(), sub.begin(), sub.end());
100  }
101 
102  return results;
103 }
104 
114 {
115  UnorderedHandleSet results;
116  results.insert(h);
117 
118  LinkPtr lll(LinkCast(h));
119  if (lll)
120  for (const Handle& o : lll->getOutgoingSet())
121  {
123  results.insert(sub.begin(), sub.end());
124  }
125 
126  return results;
127 }
128 
129 
130 HandleSeq get_neighbors(const Handle& h, bool fanin,
131  bool fanout, Type desiredLinkType,
132  bool subClasses)
133 {
134  if (h == NULL) {
135  throw InvalidParamException(TRACE_INFO,
136  "Handle %d doesn't refer to a Atom", h.value());
137  }
138  HandleSeq answer;
139 
140  for (const LinkPtr& link : h->getIncomingSet())
141  {
142  Type linkType = link->getType();
143  if ((linkType == desiredLinkType)
144  or (subClasses && classserver().isA(linkType, desiredLinkType))) {
145  for (const Handle& handle : link->getOutgoingSet()) {
146  if (handle == h) continue;
147  if (!fanout && link->isSource(h)) continue;
148  if (!fanin && link->isTarget(h)) continue;
149  answer.push_back(handle);
150  }
151  }
152  }
153  return answer;
154 }
155 
157  const std::vector<Type>& types)
158 {
159  LinkPtr link(LinkCast(hinput));
160 
161  // Recursive case
162  if (link) {
163  UnorderedHandleSet found_nodes;
164  for (const Handle& h : link->getOutgoingSet()) {
165  UnorderedHandleSet tmp = get_outgoing_nodes(h, types);
166  found_nodes.insert(tmp.begin(), tmp.end());
167  }
168  return found_nodes;
169  }
170  // Base case
171  else {
172  OC_ASSERT(NodeCast(hinput) != nullptr);
173 
174  if (types.empty()) { // Empty means all kinds of nodes
175  return {hinput};
176  } else {
177  // Check if this node is in our wish list
178  Type t = NodeCast(hinput)->getType();
179  auto it = find(types.begin(), types.end(), t);
180  if (it != types.end())
181  return {hinput};
182  else
183  return UnorderedHandleSet();
184  }
185  }
186 }
187 
188 /* Tail-recursive helper function. We mark it static, so that
189  * gcc can optimize this, i.e. call it without buying the stack
190  * frame. */
191 static void get_distant_neighbors_rec(const Handle& h,
192  UnorderedHandleSet& res,
193  int dist)
194 {
195  res.insert(h);
196 
197  // Recursive calls
198  if (dist != 0) {
199  // 1. Fetch incomings
200  for (const LinkPtr& in_l : h->getIncomingSet()) {
201  Handle in_h = in_l->getHandle();
202  if (res.find(in_h) == res.cend()) // Do not re-explore
203  get_distant_neighbors_rec(in_h, res, dist - 1);
204  }
205  // 2. Fetch outgoings
206  LinkPtr link = LinkCast(h);
207  if (link) {
208  for (const Handle& out_h : link->getOutgoingSet()) {
209  if (res.find(out_h) == res.cend()) // Do not re-explore
210  get_distant_neighbors_rec(out_h, res, dist - 1);
211  }
212  }
213  }
214 }
215 
217 {
218  UnorderedHandleSet results;
219  get_distant_neighbors_rec(h, results, dist);
220  results.erase(h);
221  return results;
222 }
223 
224 
226  Type predicateType,
227  bool subClasses)
228 {
229  if (target == NULL) {
230  throw InvalidParamException(TRACE_INFO,
231  "get_predicates: Target handle %d doesn't refer to an Atom", target.value());
232  }
233  ClassServer& classServer = classserver();
234  HandleSeq answer;
235 
236  // First find any ListLinks that point to the target
237  for (const LinkPtr& link : target->getIncomingSet())
238  {
239  // Skip any links that aren't subclasses of ListLink.
240  Type linkType = link->getType();
241  if (!classServer.isA(linkType, LIST_LINK))
242  continue;
243 
244  // Look for EvaluationLink's that contain this ListLink.
245  for (const LinkPtr& evaluationLink : link->getIncomingSet())
246  {
247  // Skip any links that aren't subclasses of EvaluationLink.
248  linkType = evaluationLink->getType();
249  if (!classServer.isA(linkType, EVALUATION_LINK))
250  continue;
251 
252  // Check the first outgoing atom for this EvaluationLink against
253  // the desired predicate type.
254  Handle candidatePredicate = evaluationLink->getOutgoingAtom(0);
255  Type candidateType = candidatePredicate->getType();
256  if ((candidateType == predicateType)
257  or (subClasses &&
258  classServer.isA(candidateType, predicateType)))
259  {
260  answer.push_back(evaluationLink->getHandle());
261  }
262  }
263  }
264 
265  return answer;
266 }
267 
269  const Handle& predicate)
270 {
271  if (target == NULL) {
272  throw InvalidParamException(TRACE_INFO,
273  "get_predicates_for: Target handle %d doesn't refer to an Atom", target.value());
274  }
275  if (predicate == NULL) {
276  throw InvalidParamException(TRACE_INFO,
277  "get_predicates_for: Predicate handle %d doesn't refer to an Atom", predicate.value());
278  }
279  ClassServer& classServer = classserver();
280  HandleSeq answer;
281 
282  // First find any ListLinks that point to the target
283  for (const LinkPtr& link : target->getIncomingSet())
284  {
285  // Skip any links that aren't subclasses of ListLink.
286  Type linkType = link->getType();
287  if (!classServer.isA(linkType, LIST_LINK))
288  continue;
289 
290  // Look for EvaluationLink's that contain this ListLink.
291  for (const LinkPtr& evaluationLink : link->getIncomingSet())
292  {
293  // Skip any links that aren't subclasses of EvaluationLink.
294  linkType = evaluationLink->getType();
295  if (!classServer.isA(linkType, EVALUATION_LINK))
296  continue;
297 
298  // Check if the first outgoing atom for this EvaluationLink is
299  // the desired predicate.
300  if (predicate == evaluationLink->getOutgoingAtom(0))
301  answer.push_back(evaluationLink->getHandle());
302  }
303  }
304 
305  return answer;
306 }
307 
308 } // namespace OpenCog
static void get_distant_neighbors_rec(const Handle &h, UnorderedHandleSet &res, int dist)
Definition: AtomUtils.cc:191
IncomingSet getIncomingSet()
Definition: Atom.cc:321
std::vector< Handle > HandleSeq
a list of handles
Definition: Handle.h:246
HandleSeq get_neighbors(const Handle &h, bool fanin, bool fanout, Type desiredLinkType, bool subClasses)
Definition: AtomUtils.cc:130
Handle getHandle()
Definition: Atom.h:211
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
UnorderedHandleSet get_distant_neighbors(const Handle &h, int dist)
Definition: AtomUtils.cc:216
static NodePtr NodeCast(const Handle &h)
Definition: Node.h:113
HandleSeq get_predicates(const Handle &target, Type predicateType, bool subClasses)
Definition: AtomUtils.cc:225
HandleSeq get_all_atoms(Handle h)
Definition: AtomUtils.cc:89
HandleSeq get_all_nodes(Handle h)
Definition: AtomUtils.cc:40
HandleSeq get_predicates_for(const Handle &target, const Handle &predicate)
Definition: AtomUtils.cc:268
bool isA(Type sub, Type super)
Definition: ClassServer.h:144
UnorderedHandleSet get_outgoing_nodes(const Handle &hinput, const std::vector< Type > &types)
Definition: AtomUtils.cc:156
static LinkPtr LinkCast(const Handle &h)
Definition: Link.h:263
UnorderedHandleSet get_all_unique_nodes(Handle h)
Definition: AtomUtils.cc:66
UUID value(void) const
Definition: Handle.h:85
UnorderedHandleSet get_all_unique_atoms(Handle h)
Definition: AtomUtils.cc:113
unsigned short Type
type of Atoms, represented as short integer (16 bits)
Definition: types.h:40
std::unordered_set< Handle, handle_hash > UnorderedHandleSet
a hash that associates the handle to its unique identificator
Definition: Handle.h:250