OpenCog

Cookbook

From OpenCog

This guide indicates how to do specific tasks that one often comes across while programming with OpenCog. Of course there are usually multiple ways of doing the same thing, and the examples should display the best practice to use unless the situation specifically requires an alternative approach.

The tasks here are things that don't impact on the framework itself, instead they manipulate the data with an OpenCog instance, or describe how to use OpenCog as part of another system. To extend OpenCog (such as adding MindAgents, adding types of atoms, etc.) please look at the Framework Cookbook.

Contents

The OpenCog Shell

The OpenCog server can be controlled from the OpenCog shell interface. It is presented as a TCP/IP socket interface at port 17001 on the localhost. One may connect to it using telnet, like so:

 ./cogserver & # start the opencog server
 telnet localhost 17001 # to get to the opencog shell
 opencog> help          # to list the currently supported commands

Many commands are implemented in modules; if a module is not loaded, then the commands that it exports will not be visible from the 'help' listing. The set of modules that are loaded by default can be specified in the "opencog.conf" file. Please note that a module cannot be loaded if it hasn't been first compiled, and that it cannot be compiled until it's compile-time pre-reqs are installed.

Notable modules include:

 libpln.o           -- probabilist backwards chainer
 libpersist.so      -- SQL-based persitence
 libscheme-shell.so -- Guile-based scheme interpreter
 libquery.so        -- simple forward chainer

The an example config file is located at "./lib/opencog.conf". It can be specified during server startup with the "-c" flag:

 ./cogserver -c lib/opencog.conf & # start the opencog server

The Scheme Interpreter

Opencog comes with an interpreter for the programming language Scheme, implemented using Guile. The goal of providing a scheme shell for OpenCog is manifold:

  • Provide a relatively simple, yet flexible way of examining the contents of of the OpenCog AtomSpace
  • Provide a means for rapidly creating and testing algorithms, without having to code in C++.
  • Provide a means for stopping, starting and controlling MindAgents.

The scheme shell itself is reachable through the OpenCog shell.

Thus:

 ./cogserver & # start the opencog server
 telnet localhost 17001 # to get to the opencog shell
 opencog> scm           # to enter the scheme shell

At this point, generic scheme expressions can be entered. The list of OpenCog-specific extensions are description the OpenCog Scheme Extensions page.

Importing Data

Taken from opencog/src/guile/Example

Below follow some examples for using scheme to input data into OpenCog.

Consider the following OpenCog XML:

 <InheritanceLink strength=".98" confidence=".99">
     <Element class="ConceptNode" name="famous"/>
     <Element class="ConceptNode" name="artist"/>
 </InheritanceLink>
 <ExtensionalImplicationLink strength=".99" confidence=".99">
     <Element class="ConceptNode" name="Muhammad"/>
     <Element class="ConceptNode" name="artist"/>
 </ExtensionalImplicationLink>
 <ExtensionalImplicationLink strength=".99" confidence=".99">
    <Element class="ConceptNode" name="Britney"/>
    <Element class="ConceptNode" name="artist"/>
 </ExtensionalImplicationLink>

This is more easily represented in scheme in the following way:

 (InheritanceLink (stv 0.98 0.99)
      (ConceptNode "famous")
      (ConceptNode "artist")
 )
 (ExtensionalImplicationLink (stv 0.99 0.99)
      (ConceptNode "Muhammad")
      (ConceptNode "artist")
 )
 (ExtensionalImplicationLink (stv 0.99 0.99)
      (ConceptNode "Britney")
      (ConceptNode "artist")
 )

The simple truth values can appear either before, or after the nodes, thus:

 (ExtensionalImplicationLink
      (ConceptNode "Britney")
      (ConceptNode "artist")
      (stv 0.99 0.99)
 )

will also work.

The above can be entered at the scheme shell prompt. There are several ways to view what was created. One crude way is to exit the shell (with a single '.' followed by newline) and type 'ls', which will display the entire contents of the atomspace. A more refined way to view graphs is by the cog-map-type, cog-incoming-set and cog-outgoing-set procedures. So, for example:

        ; Define a function that prints the atoms:
        guile> (define (prt-atom h) (display h) #f)
        ; Print all atoms of type ConceptNode:
        guile> (cog-map-type prt-atom 'ConceptNode)

The following will return all of the atoms that reference the ConceptNode "artist":

       guile> (cog-incoming-set (ConceptNode "artist"))

The scheme "define" command is handy for naming atoms. So:

       guile> (define a (ConceptNode "artist"))
       guile> (cog-incoming-set a)


Note: OpenCog shell uses generic TCP/IP sockets for its I/O, and so you can issues commands from a file, or from a process. So, for example, if you create a file, say, "some-atoms.scm", which contains something like this:

 scm
 (ConceptNode "blah-blah-blah")

and then, you go:

 cat some-atoms.scm | telnet localhost 17001

then the atom will be created. Of course, anything that spits out scheme to stdout will work -- so for example, if you have a file stuff.c which contains:

 #include <stdio.h>
 main () {
  printf ("scm\n");
  printf ("(ConceptNode \"blah-blah-blah\")\n");
  printf(".\n");
 }

and then

 cc stuff.c -o stuff
 ./stuff | telnet localhost 17001

will also create the atom(s).

If you're picky, use netcat or socat instead of telnet.

OpenCog XML (formerly NM-XML)

Alternately, data can imported/exported using OpenCog XML. At the time of this writing, the scheme-based data importer is 2x-3x faster; the scheme format is 2x more compact, and its more human-readable. However, legacy data can be imported via XML.

  • Importing

You can send opencog xml to the opencog shell. Just issue 'data' first, and you'll get a shell that accepts only nmxml. Use ^D to leave the shell.

  • Exporting

Using PLN

PLN refers to Probabilistic Logic Networks, and is basically a backwards chainer that can make use of uncertain probabilities. The PLN usage page illustrates a simple example of using PLN.

Programming in C++

Writing new code in C++ is possible, but not generally recommended. This is because the whole point of OpenCog is to represent knowledge in terms of hypergraphs in the atomspace, and to manipulate and grow that knowledge using deduction, PLN, learning and various evolutionary algorithms. Of course, writing new evolutionary algorithms can mean writing in C++; and certainly fixing existing low-level, core code requires working with C++. However, newcomers to OpenCog are strongly encouraged to think in terms of hypergraphs, and representing their ideas in terms of hypergraphs, and in terms of the first-order logic that the PLN and pattern-matching engines can process.

Although most new code should really be "new hypgraphs", and new patterns (such as the ImplicationLink and the VariableScopeLink), sometimes its just plain hard to avoid writing new algorithms. For this, scheme is recommended. In other cases, one might need to implement a new control process, aka a new "MindAgent" that controls inferencing, or possibly interfaces to external systems and sensors. For this, using python is recommended.

That said, here are some basic C++ examples:

Adding a node

Add a Node to the AtomSpace as follows. The addNode method returns a handle to the added node.

AtomSpace* atomSpace = CogServer::getAtomSpace();
  SimpleTruthValue tv1(0.5f, 0.99f);
  Handle h1 = atomSpace->addNode(CONCEPT_NODE, "ConceptNode1", tv1);

Adding a link

Similarly, you can add a Link as follows:

AtomSpace* atomSpace = CogServer::getAtomSpace();
  SimpleTruthValue tv1(0.5f, 0.99f);
  Handle h1 = atomSpace->addNode(CONCEPT_NODE, "ConceptNode1", tv1);
  Handle h2 = atomSpace->addNode(CONCEPT_NODE, "ConceptNode2", tv1);  
  Handle link = atomSpace->addLink(INHERITANCE_LINK, h1, h2, tv1);