Manipulating Atoms in Python
Contents
Lesson: Manipulating Atoms in Python3
- See the wiki entry on Python3
- Repeat a bunch of the Scheme shell examples in python
- See the opencog atomspace examples on Python
The links above provide detailed descriptions of all topics in this chapter. What follows 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 see the same stuff, this time repeated in python. The last two sections will show how to execute custom functions involving atoms in python. This can be done in scheme or c++ as well. But before we do any of that, you must make sure that python can import the opencog modules.
Export the location of the opencog modules to PYTHONPATH environment variable. This has to be done everytime you open a new shell. You may want to put it in your ~/.bashrc file, like so:
export PYTHONPATH=/usr/local/lib/python3.5/dist-packages/:$PYTHONPATH
You may need to adjust the above to match your actual python version.
Making some Atoms (python3)
Here I will mostly use the ipython shell to give examples. But you can of course put all the commands in a script if you like. Import AtomSpace and types to start making atoms.
In [1]: from opencog.atomspace import AtomSpace, types
There are two ways to create Atoms in python. You can use the c++ like syntax or you can use the scheme like syntax.
c++ like syntax
#Create the atomspace
In [2]: atsp = AtomSpace()
#Create some atoms with add_node function
In [3]: cat = atsp.add_node(types.ConceptNode, "Cat")
In [4]: man = atsp.add_node(types.ConceptNode, "Man")
In [5]: animal = atsp.add_node(types.ConceptNode, "Animal")
#Try to print the atomspace
In [6]: atsp
Out[6]: <opencog.atomspace.AtomSpace at 0x7f3beeaf4810>
#Try to print a Node
In [7]: man
Out[7]: (ConceptNode "Man") ; [3][1]
So printing the AtomSpace didn't quite work out as we might have expected from c++. We can print its contents as follows:
In [10]: for atom in atsp:
....: print (atom)
....:
(ConceptNode "Animal") ; [4][1]
(ConceptNode "Man") ; [3][1]
(ConceptNode "Cat") ; [2][1]
Now lets add some links into the AtomSpace. This is again, just like c++.
In [11]: atsp.add_link(types.InheritanceLink, [man, animal])
Out[11]:
(InheritanceLink
(ConceptNode "Man") ; [3][1]
(ConceptNode "Animal") ; [4][1]
) ; [5][1]
scheme like syntax
To use scheme like concise syntax you have to do a few extra steps. Import the type_constructors that enable you to add atoms to the AtomSpace by calling functions named after their types. Import initialize_opencog a function that binds a AtomSpace instance to the type_constructors.
In [13]: from opencog.utilities import initialize_opencog
In [14]: from opencog.type_constructors import *
#Setup that ensures that any atoms you create are added to the AtomSpace atsp.
In [15]: initialize_opencog(atsp)
Now you can add atoms just like in scheme. This becomes very useful when you start building complex patterns for the pattern matcher.
In [15]: initialize_opencog(atsp)
In [16]: color = ConceptNode("Color")
In [17]: c1 = ConceptNode("Blue")
In [18]: link = InheritanceLink(c1, color)
In [19]: for atom in atsp:
....: print (atom)
....:
(ConceptNode "Color") ; [6][1]
(ConceptNode "Blue") ; [7][1]
(ConceptNode "Animal") ; [4][1]
(ConceptNode "Man") ; [3][1]
(ConceptNode "Cat") ; [2][1]
(InheritanceLink
(ConceptNode "Blue") ; [7][1]
(ConceptNode "Color") ; [6][1]
) ; [8][1]
(InheritanceLink
(ConceptNode "Man") ; [3][1]
(ConceptNode "Animal") ; [4][1]
) ; [5][1]
One last thing before we wrap this up. The Atoms are classes with a lot of useful methods. If you are in the ipython shell you can look at a list by writing <variable_pointing_to_an_atom>.<Tab>. For example we have a variable color that points to the ConceptNode object of name "Color". Then I can see a list of all the method I can call on it by:
In [21]: color.<Press_Tab>
color.arity color.incoming color.long_string color.truth_value color.vlti
color.atomspace color.incoming_by_type color.lti color.tv color.xincoming
color.av color.increment_vlti color.name color.type color.xincoming_by_type
color.decrement_vlti color.is_a color.out color.type_name
color.get_out color.is_link color.sti color.uuid
color.handle_uuid color.is_node color.t color.value
Pattern Matching
Now lets look at how we can run the PM through python. The PM functions are defined in c++ and made available in python through wrappers that are defined in atomspace/opencog/cython/opencog/bindlink.pyx and you can see the imports in atomspace/opencog/cython/opencog/bindlink.pxd
Here we will again run the equivalent of bindlink and cog-staisfying-set functions in scheme.
#Import the staisfying_set function
In [21]: from opencog.bindlink import satisfying_set
#Delete existing atoms
In [22]: atsp.clear()
#Create some atoms
In [27]: InheritanceLink(ConceptNode("Red"), color)
In [28]: InheritanceLink(ConceptNode("Green"), color)
In [29]: InheritanceLink(ConceptNode("Blue"), color)
#Create a pattern to look for color nodes
In [30]: varlink = TypedVariableLink(VariableNode("$xcol"), TypeNode("ConceptNode"))
In [31]: pattern = InheritanceLink(VariableNode("$xcol"), color)
In [32]: colornodes = GetLink(varlink, pattern)
#Now run the function to find all color nodes
In [33]: satisfying_set(atsp, colornodes)
Out[33]:
(SetLink
(ConceptNode "Red") ; [10][1]
(ConceptNode "Blue") ; [12][1]
(ConceptNode "Green") ; [14][1]
) ; [22][1]
In a similar manner you can import bindlink from opencog.bindlink and use it to execute rewrite queries (with the help of BindLink in place of SatisfactionLink).