Manipulating Atoms in C++

From OpenCog
Jump to: navigation, search

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.

#include <iostream>

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/truthvalue/AttentionValue.h>
#include <opencog/truthvalue/SimpleTruthValue.h>
#include <opencog/truthvalue/TruthValue.h>

using namespace opencog;
using namespace std;

int main(int argc, char **argv){
        //Instantiate the atomspace
	AtomSpace as;

	//Create some atoms
	Handle h = as.add_node(CONCEPT_NODE, "Cat");
	Handle h1 = as.add_node(CONCEPT_NODE, "Human");
	Handle h2 = as.add_node(CONCEPT_NODE, "Animal");

	//Create an InheritanceLink
	/*InheritanceLink
	      ConceptNode "Human"
	      ConceptNode "Animal"
	 */
	HandleSeq hseq = {h1, h2};
	Handle inheritancelink = as.add_link(INHERITANCE_LINK, hseq);

	//Print out the contents of the atomspace
	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:

	//Create hierarchical atomspace
	//The child_as is more like a subclass in that it encompasses the
	//parent atomspace.
	AtomSpace child_as(&as);
	child_as.add_node(CONCEPT_NODE, "Puma");

	cout << "Parent AtomSpace: " << endl << as
		 << "Child AtomSpace: " << endl << child_as;

	return 0;
}

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.

#include <iostream>

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/truthvalue/AttentionValue.h>
#include <opencog/truthvalue/SimpleTruthValue.h>
#include <opencog/truthvalue/TruthValue.h>
#include <opencog/query/BindLinkAPI.h>

using namespace opencog;
using namespace std;

int main(int argc, char **argv){
	//Instantiate the atomspace
	AtomSpace as;

	//Create some atoms
	Handle color = as.add_node(CONCEPT_NODE, "Color");
	Handle primarycolor = as.add_node(CONCEPT_NODE, "PrimaryColor");
	Handle c1 = as.add_node(CONCEPT_NODE, "100");
	Handle c2 = as.add_node(CONCEPT_NODE, "010");
	Handle c3 = as.add_node(CONCEPT_NODE, "001");

	HandleSeq hseq = {c1, color};
	as.add_link(INHERITANCE_LINK, hseq);

	hseq[0] = c2;
	as.add_link(INHERITANCE_LINK, hseq);

	hseq[0] = c3;
	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:

	Handle h1, h2;
	h1 = as.add_node(VARIABLE_NODE, "$x");
	h2 = as.add_node(TYPE_NODE, "ConceptNode");
	hseq[0] = h1;
	hseq[1] = h2;
	Handle TypedVariableLink = as.add_link(TYPED_VARIABLE_LINK, hseq);
	
	h2 = as.add_node(CONCEPT_NODE, "Color");
	hseq[1] = h2;
	Handle findpattern = as.add_link(INHERITANCE_LINK, hseq);

	hseq[0] = TypedVariableLink;
	hseq[1] = findpattern;
	Handle SatisfactionLink = as.add_link(GET_LINK, hseq);

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

	//Run the PM to get the set of atoms that satisfy the pattern
	Handle colornodes = satisfying_set(&as, SatisfactionLink);

	//Print out the query result
	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:

	h2 = as.add_node(CONCEPT_NODE, "PrimaryColor");
	hseq[0] = h1;
	hseq[1] = h2;
	Handle writepattern = as.add_link(INHERITANCE_LINK, hseq);

	HandleSeq BLinkHseq = {TypedVariableLink, findpattern, writepattern};
	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:

	//Execute rewrite query
	colornodes = bindlink(&as, BindLink);

	//Print the returned atoms
	cout << "PrimaryColors: " << endl << colornodes->toString() << endl;
	return 0;
}

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)