Manipulating Atoms in C++
Contents
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
8 using namespace opencog;
9 using namespace std;
10
11 int 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
9 using namespace opencog;
10 using namespace std;
11
12 int 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)