Manipulating Atoms in C++

From OpenCog

Lesson: Manipulating Atoms in C++

Outline

We will use basic examples taken from here, but giving actual working code embodying these snippets

Then give an example of invoking the Pattern Matcher using C++


The link above provide detailed descriptions of all topics in this chapter.

This tutorial is a severely restricted selection from these pages. One should go back and explore those links to gain a deeper understanding of the topics introduced here.

In this lesson we will create some Atoms in Atomspace and execute the equivalent of cog-bind and cog-satisfying-set queries on the Atomspace using c++. c++ should not be used as the primary way to interact with Atomspace. These examples are given just to let a developer get started.

Making some Atoms(c++)

Choose a working directory of your choice and create a file createatoms.cc. We will use two functions atomspace::add_node and atomspace::add_link to add atoms in the atomspace. The contents of atomspace can be printed by passing it to the output stream.

 1#include <iostream>
 2
 3#include <opencog/atomspace/AtomSpace.h>
 4#include <opencog/truthvalue/AttentionValue.h>
 5#include <opencog/truthvalue/SimpleTruthValue.h>
 6#include <opencog/truthvalue/TruthValue.h>
 7
 8using namespace opencog;
 9using namespace std;
10
11int main(int argc, char **argv){
12        //Instantiate the atomspace
13	AtomSpace as;
14
15	//Create some atoms
16	Handle h = as.add_node(CONCEPT_NODE, "Cat");
17	Handle h1 = as.add_node(CONCEPT_NODE, "Human");
18	Handle h2 = as.add_node(CONCEPT_NODE, "Animal");
19
20	//Create an InheritanceLink
21	/*InheritanceLink
22	      ConceptNode "Human"
23	      ConceptNode "Animal"
24	 */
25	HandleSeq hseq = {h1, h2};
26	Handle inheritancelink = as.add_link(INHERITANCE_LINK, hseq);
27
28	//Print out the contents of the atomspace
29	cout << "Atomspace: " << endl << as << endl;

It is trivial to create more than one Atomspace instances. It is also possible to create nested Atomspaces as follows:

31	//Create hierarchical atomspace
32	//The child_as is more like a subclass in that it encompasses the
33	//parent atomspace.
34	AtomSpace child_as(&as);
35	child_as.add_node(CONCEPT_NODE, "Puma");
36
37	cout << "Parent AtomSpace: " << endl << as
38		 << "Child AtomSpace: " << endl << child_as;
39
40	return 0;
41}

To compile and run this file issue the following command:

$ g++ createatoms.cc -std=c++11 -o createatoms -latomspace -latombase
$ ./createatoms

Note you may need to directly link to the path there the libraries (atomspace, atombase) exist by adding '-L/usr/local/lib/opencog'

$ g++ createatoms.cc -std=c++11 -o createatoms -L/usr/local/lib/opencog  -latomspace -latombase
$ ./createatoms

See the error handling section for more detail

Pattern Matcher

Make another file named patternmatcher.cc. In this example we will show how to perform the equivalent of cog-satisfying-set and cog-bind queries through c++.

First create some atoms: We add some color nodes to the atomspace just like we did in the scheme examples.

 1#include <iostream>
 2
 3#include <opencog/atomspace/AtomSpace.h>
 4#include <opencog/truthvalue/AttentionValue.h>
 5#include <opencog/truthvalue/SimpleTruthValue.h>
 6#include <opencog/truthvalue/TruthValue.h>
 7#include <opencog/query/BindLinkAPI.h>
 8
 9using namespace opencog;
10using namespace std;
11
12int main(int argc, char **argv){
13	//Instantiate the atomspace
14	AtomSpace as;
15
16	//Create some atoms
17	Handle color = as.add_node(CONCEPT_NODE, "Color");
18	Handle primarycolor = as.add_node(CONCEPT_NODE, "PrimaryColor");
19	Handle c1 = as.add_node(CONCEPT_NODE, "100");
20	Handle c2 = as.add_node(CONCEPT_NODE, "010");
21	Handle c3 = as.add_node(CONCEPT_NODE, "001");
22
23	HandleSeq hseq = {c1, color};
24	as.add_link(INHERITANCE_LINK, hseq);
25
26	hseq[0] = c2;
27	as.add_link(INHERITANCE_LINK, hseq);
28
29	hseq[0] = c3;
30	as.add_link(INHERITANCE_LINK, hseq);

Define pattern: Now we define the pattern to be grounded using a SatisfactionLink. The pattern written in a scheme-ish style is:

GetLink
 	TypedVariableLink 
 		VariableNode "$x"
 		TypeNode "ConceptNode
 	InheritanceLink
		VariableNode "$x"
		ConceptNode "Color"	

To define this pattern issue the following commands:

31	Handle h1, h2;
32	h1 = as.add_node(VARIABLE_NODE, "$x");
33	h2 = as.add_node(TYPE_NODE, "ConceptNode");
34	hseq[0] = h1;
35	hseq[1] = h2;
36	Handle TypedVariableLink = as.add_link(TYPED_VARIABLE_LINK, hseq);
37	
38	h2 = as.add_node(CONCEPT_NODE, "Color");
39	hseq[1] = h2;
40	Handle findpattern = as.add_link(INHERITANCE_LINK, hseq);
41
42	hseq[0] = TypedVariableLink;
43	hseq[1] = findpattern;
44	Handle SatisfactionLink = as.add_link(GET_LINK, hseq);

Ground the pattern: Now we ground the pattern using the satisfying_set function.

45	//Run the PM to get the set of atoms that satisfy the pattern
46	Handle colornodes = satisfying_set(&as, SatisfactionLink);
47
48	//Print out the query result
49	cout << "Colors: " << endl << colornodes->toString() << endl;

Define pattern for rewrite query: Now we define a BindLink to perform a graph rewriting. The BindLink being defined is:

BindLink
 	TypedVariableLink 
 		VariableNode "$x"
 		TypeNode "ConceptNode"
 	InheritanceLink
		VariableNode "$x"
		ConceptNode "Color"
	InheritanceLink
		VariableNode "$x"
		ConceptNode "PrimaryColor"

This query will label all the colors in Atomspace as PrimaryColors. Define the BindLink as follows:

50	h2 = as.add_node(CONCEPT_NODE, "PrimaryColor");
51	hseq[0] = h1;
52	hseq[1] = h2;
53	Handle writepattern = as.add_link(INHERITANCE_LINK, hseq);
54
55	HandleSeq BLinkHseq = {TypedVariableLink, findpattern, writepattern};
56	Handle BindLink = as.add_link(BIND_LINK, BLinkHseq);

Execute the rewrite query: The query defined through the BindLink can be executed using the bindlink function as follows:

57	//Execute rewrite query
58	colornodes = bindlink(&as, BindLink);
59
60	//Print the returned atoms
61	cout << "PrimaryColors: " << endl << colornodes->toString() << endl;
62	return 0;
63}

The file can be compiled and run using the following commands:

$ g++ patternmatcher.cc -std=c++11 -o patternmatcher -latombase -latomspace -lquery -lexecution	
$ ./patternmatcher

Similarly to above, if it fails, then compile with a direct link to the libraries

g++ patternmatcher.cc -std=c++11 -o patternmatcher -L/usr/local/lib/opencog -latombase -latomspace -lquery -lexecution

Contact: (Misgana)

Notes

Error Handling

G++ Compile issues

Note if getting a problem compiling the code like so:

$ g++ createatoms.cc -std=c++11 -o createatoms -latomspace -latombase
/usr/bin/ld: cannot find -latomspace
/usr/bin/ld: cannot find -latombase
collect2: error: ld returned 1 exit status
  • Make sure you have installed atom space
  • Either :
  - make sure to add the library paths to gcc
  - link directly to the directory containing the libraries -L/usr/local/lib/opencog , making sure to do this before linking to the libraries like this:
$ g++ createatoms.cc -std=c++11 -o createatoms -L/usr/local/lib/opencog  -latomspace -latombase

(Thanks to Misgana)

More Path Issues

If the ./createatoms didn't work.. i.e. if it produces this error

 ./createatoms: error while loading shared libraries: libatomspace.so: cannot open shared object file: No such file or directory

Then try these commands:

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/opencog
$ sudo ldconfig

Note there is likely to be a better way to solve the path issues... will look into this later (Misgana, Adam)