Scheme

From OpenCog
Jump to: navigation, search

This page describes the Scheme extensions for OpenCog. Scheme is a dialect of Lisp; the scheme shell allows scheme code to manipulate the contents of an OpenCog AtomSpace.

This binding is intended to be used for day-to-day maintenance activities, experimentation and MindAgent development. The shell is implemented in Guile; the guile reference manual is here. The best book on the Scheme programming language (never-mind the language, it's one of the best books written on programming, no matter what language you like to use) is "Structure and Interpretation of Computer Programs" by Abelson and Sussman. It is now available online for free from MIT Press.

Documented below are the core interface functions implemented by the guile binding. These provide for the creation and deletion of OpenCog Nodes, Links and TruthValues, as well as ways to get properties (such as the names of Nodes, or the outgoing sets of Links).

A number of utilities and handy functions can be found in the directory /opencog/scm; additional NLP-related utilities are located in /opencog/nlp. In addition, there are scheme bindings to various important atomspace subsystems, these include the unified rule engine and the pattern matcher.

Contents

Running

There are three scheme shells available for opencog. One is the native guile REPL prompt; the other two are provided by the cogserver. The cogserver provides a low-level, built-in shell at port 17001, and a guile REPL at port 18001.

The shells are available only if the cogserver was compiled with guile support, and the guile module was loaded. The guile module should be loaded automatically; it is specified in lib/opencog.conf.

The guile REPL shell

Simply start guile, and then load the opencog module:

scheme@(guile-user)> (use-modules (ice-9 readline)) (activate-readline)
scheme@(guile-user)> (add-to-load-path "/usr/local/share/opencog/scm")
scheme@(guile-user)> (add-to-load-path ".")
scheme@(guile-user)> (use-modules (opencog))
scheme@(guile-user)> (use-modules (opencog query))
scheme@(guile-user)> (use-modules (opencog exec))
scheme@(guile-user)> (load-from-path "opencog.scm")
scheme@(guile-user)>
scheme@(guile-user)> (ConceptNode "asdf")

The above assumes that you have installed atomspace. The extensive boilerplate at the start is best handled by copying the following into your ~/.guile file, which is executed automatically every time guile is started:

(use-modules (ice-9 readline)) (activate-readline)
(add-to-load-path "/usr/local/share/opencog/scm")
(add-to-load-path ".")
(use-modules (opencog))
(use-modules (opencog query))
(use-modules (opencog exec))
(load-from-path "opencog.scm")

The guile REPL cogserver shell

The high-level shell may be accessed via telnet, at port 18001, (not port 17001).

telnet localhost 18001

or

rlwrap telnet localhost 18001

This second form will provide an editable command-line history.

To leave the shell, type ,q on a line all by itself.

Scheme scripts can be loaded by using netcat or socat; it is recommended that the low-level shell be used for this. The high-level shell is implemented in opencog/scm/repl-shell.scm.

The low-level cogserver shell

The low-level shell may be invoked by typing "scm" at the OpenCog shell prompt. To get to the opencog shell, say

telnet localhost 17001

or

rlwrap telnet localhost 17001

This second form will provide an editable command-line history.

To leave the shell, place a single . on the line, and hit enter. Alternately, hit ^D.

On-line documentation

Documentation for some (a small number, but growing) routines and utilities can be pulled up at the scheme shell prompt, by saying (display (procedure-documentation name-of-proc)), after importing the module that has defined the given routine. Otherwise, you'll have to consult the individual scm files for more info.

Modules

Currently OpenCog's scheme functions are broken into the following different modules:

(opencog)
(opencog exec)
(opencog logger)
(opencog persist)
(opencog persist-sql)
(opencog query)
(opencog rule-engine)
(opencog atom-types)
(opencog cogserver)
(opencog nlp chatbot)
(opencog nlp chatbot-eva)
(opencog nlp fuzzy)
(opencog nlp lg-dict)
(opencog nlp relex2logic)
(opencog nlp sureal)

The contents of the query module (for example) can be listed with the following code:

(module-for-each 
   (lambda (symbol value) (display symbol) (newline))
      (resolve-interface '(opencog query)))

You will have to always import (opencog) module for the core atom types. If you want to work on a specific opencog-module, like NLP or embodiment, then in addition, you will have to import (opencog atom-types) module.

Atom Functions

The following are functions for creating and manipulating atoms.

cog-new-node node-type node-name

Create a new node of the given type and name

Optionally, a truth value can follow the node name. Throws errors if node-type is not a valid atom type for a node, and if node-name is not a string.

Example:

; Create a new node; the created node is echoed to output:
guile> (cog-new-node 'ConceptNode "some node name")
(ConceptNode "some node name")

; Creates a new node, with a truth value:
guile> (cog-new-node 'ConceptNode "another node"
         (cog-new-stv 0.8 0.9))
(ConceptNode "another node" (stv 0.8 0.9))

An even simple syntax can be used:

; Create a new node; the created node is echoed to output:
guile> (ConceptNode "some node name")
(ConceptNode "some node name")

; Creates a new node, with a truth value:
guile> (ConceptNode "another node" (cog-new-stv 0.8 0.9))
(ConceptNode "another node" (stv 0.8 0.9))

cog-node node-type node-name

Returns the node of the given type and name, if it exists, else returns null.

Optionally, a truth value can follow the node name. If the node exists, then the truth value is modified. Throws errors if node-type is not a valid atom type for a node, and if node-name is not a string.

Example:

; Check to see if a node exists: 
guile> (cog-node 'ConceptNode "asdf")
()

; Verify that the return value is actually a true null:
guile> (null? (cog-node 'ConceptNode "asdf"))
#t 

; Now, create the node, and see if it exists:
guile> (cog-new-node 'ConceptNode "asdf")
(ConceptNode "asdf")
guile> (null? (cog-node 'ConceptNode "asdf"))
#f

; Change the truth value of an existing node:
guile> (cog-node 'ConceptNode "asdf" (cog-new-stv 0.8 0.9))
(ConceptNode "asdf" (stv 0.8 0.9))

cog-new-link link-type atom ... atom

Create a new link, with the given atoms in the link.

Optionally, a truth value can follow the list of atoms. Throws errors if the link type is not a valid opencog link type, or if any of the arguments after the link type are not atoms.

Example:

; Creates two nodes, and a new link: 
guile> (define x (ConceptNode "abc")) 
guile> (define y (ConceptNode "def")) 
guile> (cog-new-link 'Link x y) 
(Link
    (ConceptNode "abc")
    (ConceptNode "def")
)

; Create a new link with a truth value: 
guile> (cog-new-link 'Link x y (cog-new-stv 0.7 0.8)) 
(Link (stv 0.7 0.8)
   (ConceptNode "abc")
   (ConceptNode "def")
)

An even simple syntax can be used:

; Create a new link
guile> (Link x y)
(Link
   (ConceptNode "abc")
   (ConceptNode "def")
)

; Creates a new link, with a truth value:
guile> (Link  (cog-new-stv 0.7 0.8) x y)
(Link (stv 0.69999999 0.80000001)
   (ConceptNode "abc")
   (ConceptNode "def")
)

cog-link link-type atom ... atom

Returns the link of the given type and list of atoms, if it exists, else returns null.

Optionally, a truth value can follow the list of atoms. If the link exists, then the truth value is modified.

Throws errors if the link type is not a valid opencog link type, or if any of the arguments after the link type are not atoms.

Example:

; Create two nodes: 
guile> (define x (ConceptNode "abc")) 
guile> (define y (ConceptNode "def")) 

; Does a link with these two nodes exist? 
guile> (cog-link 'Link x y) 
() 

; Now, create such a link 
guile> (cog-new-link 'Link x y) 
(Link
   (ConceptNode "abc")
   (ConceptNode "def")
)
  
; Check again for existence: 
guile> (cog-link 'Link x y) 
(Link
   (ConceptNode "abc")
   (ConceptNode "def")
)

; Change the truth value of an existing node: 
guile> (cog-link 'Link x y (cog-new-stv 0.7 0.8)) 
(Link (stv 0.7 0.8)
   (ConceptNode "abc")
   (ConceptNode "def")
)

cog-delete atom

Delete the indicated atom, but only if it has no incoming links.

Returns #t on success, else it returns #f.

Example:

; Creates a link between two nodes
guile> (define x (ConceptNode "abc"))
guile> (define y (ConceptNode "def"))
guile> (define l (Link x y))

; Try to delete x. This should fail, since there's a link 
; containing x.  
guile> (cog-delete x)
#f

; Delete the link
guile> (cog-delete l)
#t

; Verify that the link l is gone: 
guile> l
#<Invalid handle>

; Verify that the node x and y still exists: 
guile> x
(ConceptNode "abc")

guile> y
(ConceptNode "def")

cog-delete-recursive atom

Delete the incoming atom, and all atoms that point at it.

Returns #t on success, else it returns #f.

Example:

; Define two nodes and a link between them: 
guile> (define x (ConceptNode "abc")) 
guile> (define y (ConceptNode "def")) 
guile> (define l (Link x y)) 

; Delete x, and everything pointing to it. This should delete 
; both x, and the link l. 
guile> (cog-delete-recursive x) 
#t 

; Verify that the link l is gone: 
guile> l 
#<Invalid handle>

; Verify that the node x is gone: 
guile> x 
#<Invalid handle>

; Verify that the node y still exists: 
guile> y 
(ConceptNode "def")

cog-atom? exp

Return #t if exp is an atom, else return #f

Example:

; Define a node 
guile> (define x (ConceptNode "abc")) 
guile> (define y (+ 2 2)) 
guile> (cog-atom? x) 
#t 
guile> (cog-atom? y) 
#f

cog-node? exp

Return #t if exp is an node, else return #f

See also cog-node, which will check to see if a specific node already exists.

Example:

; Define a node and a link
guile> (define x (ConceptNode "abc"))
guile> (define y (ListLink x))
guile> (cog-node? x)
#t    
guile> (cog-node? y)
#f

cog-link? exp

Return #t if exp is an link, else return #f

See also cog-link, which will check to see if a specific link already exists.

Example:

; Define a node and a link
guile> (define x (ConceptNode "abc"))
guile> (define y (ListLink x))
guile> (cog-link? x)
#f    
guile> (cog-link? y)
#t

cog-name atom

Return the name of the node. If the atom is not a node, returns empty string.

Example:

; Define a node 
guile> (define x (ConceptNode "abc"))
guile> (define l (Link x))       
guile> (cog-name x) 
"abc" 

guile> (cog-name l)
""

cog-type atom

Return the type of the atom.

Example:

; Define a node 
guile> (define x (ConceptNode "abc")) 
guile> (cog-type x) 
ConceptNode 
guile> (eq? 'ConceptNode (cog-type x)) 
#t

cog-arity atom

Return the arity of the atom.

Example:

guile> (define x (ConceptNode "abc")) 
guile> (cog-arity x) 
0 
guile> (define l (Link x x x)) 
guile> (cog-arity l) 
3

cog-incoming-set atom

Return the incoming set of the atom. The set is returned as ordinary scheme list.

Example:

; Define two nodes and a link between them:
guile> (define x (ConceptNode "abc"))
guile> (define y (ConceptNode "def"))
guile> (define l (Link x y))

; Get the incoming sets of nodes x and y (which is the link l):
guile> (cog-incoming-set x)
((Link
    (ConceptNode "abc")
    (ConceptNode "def")
)
)
guile> (cog-incoming-set y)
((Link
    (ConceptNode "abc")
    (ConceptNode "def")
)
)
; Verify that the both incoming sets are really one and the
; same link:
guile> (equal? (cog-incoming-set x) (cog-incoming-set y))
#t

; The returned values are lists, and not singleton atoms.
; Thus, the incoming set of x is a list containing l:
guile> (equal? (cog-incoming-set x) (list l))
#t

; Verify that the returned value is a true list:
guile> (list? (cog-incoming-set x))
#t

cog-outgoing-set atom

Return the outgoing set of the atom. The set is returned as ordinary scheme list.

Example:

; Define two nodes and a link between them: 
guile> (define x (ConceptNode "abc")) 
guile> (define y (ConceptNode "def")) 
guile> (define l (Link x y)) 

; Get the outgoing set of nodes x and y:
; It is an empty list because nodes don't have outgoing set.
guile> (cog-outgoing-set x) 
()
guile> (cog-outgoing-set y)
()

; Get the outgoing set of link l:
guile> (cog-outgoing-set l)
((ConceptNode "abc")
 (ConceptNode "def")
)

cog-handle atom

Return the handle (which is an integer) of the atom.

It may be useful to remember that scheme indicates hexadecimal numbers by preceding them with #x, and so, for example, (cog-atom #x2c949b) gets the handle associated with hex 2c949b.

Example:

; Create two atoms, and get their handles: 
guile> (define x (ConceptNode "abc")) 
guile> (define y (ConceptNode "def")) 
guile> (cog-handle x) 
113 
guile> (cog-handle y) 
114

; Verify that handles are truly integers 
guile> (integer? x) 
#f 
guile> (integer? (cog-handle x)) 
#t

cog-undefined-handle

Return the value of Handle::UNDEFINED. Example (in 32bit architecture):

; return the value of Handle::UNDEFINED
guile> (cog-undefined-handle)
18446744073709551615

cog-atom handle

Reference the atom identified by the integer-valued handle

Example:

guile> (define x (ConceptNode "abc")) 
guile> (cog-handle x)
113 

; Get the atom corresponding to handle number 113
guile> (cog-atom 113) 
(ConceptNode "def")

; Only existing handles are allowed:
guile> (cog-atom 654321)
#<Invalid handle>

cog-execute!

See here.

cog-evaluate!

See here.

cog-free-variables

Return the list of free variables.

Example:

guile> (cog-free-variables (ConceptNode "A"))
$1 = ()
guile> (cog-free-variables (VariableNode "$X"))
$2 = ((VariableNode "$X"))
guile> (cog-free-variables (LambdaLink (VariableNode "$X") (VariableNode "$X")))
$3 = ()
guile> (cog-free-variables (AndLink (VariableNode "$X") (LambdaLink (VariableNode "X") (VariableNode "$X"))))
$4 = ((VariableNode "$X"))

cog-closed? atom

Return #t is the atom is closed, that is has no free variable, #f otherwise.

Example:

guile> (cog-closed? (ConceptNode "A"))
$1 = #t
guile> (cog-closed? (VariableNode "$X"))
$2 = #f
guile> (cog-closed? (LambdaLink (VariableNode "$X") (VariableNode "$X")))
$3 = #t
guile> (cog-closed? (AndLink (VariableNode "$X") (LambdaLink (VariableNode "X") (VariableNode "$X"))))
$4 = #f

TruthValue Functions

The following are functions for creating and manipulating truth values.

cog-new-stv mean confidence

Create a SimpleTruthValue with the given mean and confidence. Unlike atoms, truth values are ephemeral: they are automatically garbage-collected when no longer needed.

Throws errors if mean and confidence are not floating-point values. Example:

; Create a new simple truth value: 
guile> (cog-new-stv 0.7 0.9)

cog-new-ctv mean confidence count

Create a CountTruthValue with the given mean, confidence and count. Unlike atoms, truth values are ephemeral: they are automatically garbage-collected when no longer needed.

Throws errors if mean, confidence and count are not floating-point values. Example:

; Create a new count truth value: 
guile> (cog-new-ctv 0.7 0.9 44.0)

cog-new-itv lower upper confidence

Create an IndefiniteTruthValue with the given lower, upper and confidence. Unlike atoms, truth values are ephemeral: they are automatically garbage-collected when no longer needed.

Throws errors if lower, upper and confidence are not floating-point values. Example:

; Create a new indefinite truth value: 
guile> (cog-new-itv 0.7 0.9 0.6)

cog-new-etv positive-count total-count

Create a EvidenceCountTruthValue with the given positive and total counts. Unlike atoms, truth values are ephemeral: they are automatically garbage-collected when no longer needed.

The total count is optional in the sense that any value below the positive count will be considered undefined.

Throws errors if positive and total counts are not floating-point values. Example:

; Create a new simple truth value: 
guile> (cog-new-etv 10 100)

cog-tv? exp

Return #t if exp is a truth value, else return #f

Example:

; Define a node 
guile> (define x (cog-new-stv 0.7 0.9)) 
guile> (define y (+ 2 2)) 
guile> (cog-tv? x) 
#t 
guile> (cog-tv? y) 
#f

cog-stv? exp

Return #t if exp is a SimpleTruthValue, else return #f

cog-ctv? exp

Return #t if exp is a CountTruthValue, else return #f

cog-itv? exp

Return #t if exp is a IndefiniteTruthValue, else return #f


cog-etv? exp

Return #t if exp is a EvidenceCountTruthValue, else return #f

cog-tv atom

Return the truth-value of the atom.

Example:

; Define a node 
guile> (define x  
          (cog-new-node 'ConceptNode "abc"  
             (cog-new-stv 0.2 0.5))) 
guile> (cog-tv x) 
(stv 0.2 0.5) 
guile> (cog-tv? (cog-tv x)) 
#t

cog-set-tv! atom tv

Set the truth-value of the atom.

Example:

; Define a node
guile> (define x (cog-new-node 'ConceptNode "def"))
guile> (cog-tv x)
(stv 0 0)
guile> (cog-set-tv! x (cog-new-stv 0.9 0.8))
(ConceptNode "def" (stv 0.9 0.8))
guile> (cog-tv x)
(stv 0.9 0.8)

cog-tv->alist tv

Convert a truth value to an association list (alist).

Example:

guile> (define x (cog-new-stv 0.7 0.9)) 
guile> (cog-tv->alist x) 
((count . 7199.998046875) (mean . 0.699999988079071) (confidence . 0.899999976158142))

cog-merge-tv! atom tv

Like cog-set-tv! but merge the TV value to the existing one instead of overwriting it.

Example:

; Define a node
guile> (define x (cog-new-node 'ConceptNode "def"))
guile> (cog-set-tv! x (cog-new-stv 0.9 0.8))
(ConceptNode "def" (stv 0.9 0.8))
guile> (cog-merge-tv! x (cog-new-stv 0.1 0.6))
(ConceptNode "def" (stv 0.682 0.839))

cog-merge-hi-conf-tv! atom tv

Like cog-merge-tv! but uses the keep-tv-with-higher-confidence policy instead of the default one (PLN book revision rule).

Example:

; Define a node
guile> (define x (cog-new-node 'ConceptNode "def"))
guile> (cog-set-tv! x (cog-new-stv 0.9 0.8))
(ConceptNode "def" (stv 0.9 0.8))
guile> (cog-merge-hi-conf-tv! x (cog-new-stv 0.1 0.6))
(ConceptNode "def" (stv 0.9 0.8))

AttentionValue Functions

The following are functions for creating and manipulating attention values.

cog-new-av sti lti vlti

Create an AttentionValue with the given STI, LTI and VLTI. Unlike atoms, attention values are ephemeral: they are automatically garbage-collected when no longer needed.

Example:

; Create a new attention value:
guile> (cog-new-av 10 20 0)

cog-av? exp

Return #t if exp is an attention value, else return #f

Example:

; Define a simple attention value
guile> (define x (cog-new-av 15 25 0))
guile> (define y (+ 2 2))
guile> (cog-av? x)
#t
guile> (cog-av? y)
#f

cog-av atom

Return the attention value of the atom.

Example:

; Define a node
guile> (define x 
          (cog-new-node 'ConceptNode "abc" 
             (cog-new-av 11 21 0)))
guile> (cog-av x)
(av 11 21 0)
guile> (cog-av? (cog-av x))
#t

cog-set-av! atom av

Set the attention value of the atom.

Example:

; Define a node
guile> (define x (cog-new-node 'ConceptNode "def"))
guile> (cog-av x)
(av 0 0 0)
guile> (cog-set-av! x (cog-new-av 44 55 1))
(ConceptNode "def" (av 44 55 1))
guile> (cog-av x)
(av 44 55 1)

cog-inc-vlti! atom av

Increase the vlti of the atom by 1.

Example:

; Define a node
guile> (define x 
          (cog-new-node 'ConceptNode "abc" 
             (cog-new-av 11 21 0)))
guile> (cog-inc-vlti! x)
(ConceptNode "abc" (av 11 21 1))
guile> (cog-av x)
(av 11 21 1)
guile> (cog-inc-vlti! x)
(ConceptNode "abc" (av 11 21 2))
guile> (cog-av x)
(av 11 21 2)

cog-dec-vlti! atom av

Decrease the vlti of the atom by 1.

Example:

; Define a node
guile> (define x 
          (cog-new-node 'ConceptNode "abc" 
             (cog-new-av 11 21 1)))
guile> (cog-dec-vlti! x)
(ConceptNode "abc" (av 11 21 0))
guile> (cog-av x)
(av 11 21 0)

cog-av->alist av

Convert an attention value to an association list (alist).

Example:

guile> (define x (cog-new-av 99 88 #f))
guile> (cog-av->alist x)
((sti . 99) (lti . 88) (vlti . #f))

cog-stimulate atom stim

stimulate an atom with stimulus amount stim.

Example:

guile> (define atom (ConceptNode "x"))
guile> (cog-stimulate atom 40)

Note: This function is supposed to be used with the ECAN system running.

cog-af-boundary

Return the AttentionalFocus Boundary of the AtomSpace (which is a short integer STI value).

Example:

guile> (cog-af-boundary)
100

cog-set-af-boundary! sti

Set the AttentionalFocus Boundary of the AtomSpace (which is a short integer STI value). Returns the new AttentionalFocus Boundary (which is a short integer STI value).

Example:

guile> (cog-set-af-boundary! 200)
200

cog-af

Return the list of atoms in the AttentionalFocus.

Example:

guile> (cog-af)
(ConceptNode "ArtificialIntelligence" (av 15752 0 0))
(ConceptNode "Databases" (av 15752 0 0))

Atom Type Functions

The following are functions for creating and manipulating types.

cog-get-types

Return a list of all of the atom types in the system.

Example:

guile> (cog-get-types)

cog-type? symb

Return #t if the symbol names an atom type, else return #f

Example:

guile> (cog-type? 'ConceptNode)
#t
guile> (cog-type? 'FlorgleBarf)
#f

cog-node-type? symb

Return #t if the symbol names a node type, else return #f

Example:

guile> (cog-node-type? 'ConceptNode)
#t
guile> (cog-node-type? 'ListLink)
#f
guile> (cog-node-type? 'FlorgleBarf)
#f

cog-link-type? symb

Return #t if the symbol names a link type, else return #f

Example:

guile> (cog-link-type? 'ConceptNode)
#f
guile> (cog-link-type? 'ListLink)
#t
guile> (cog-link-type? 'FlorgleBarf)
#f

cog-type->int symb

Return the integer value corresponding to an atom type.

Example:

guile> (cog-type->int 'ListLink)
8

cog-get-subtypes type

Return a list of the subtypes of the given type. Only the immediate subtypes are returned; to obtain all subtypes, this function should be called recursively.

Example:

guile> (cog-get-subtypes 'Atom)
(Link Node)

cog-subtype? type subtype

Return #t if 'subtype' is a subtype of 'type', else return #f. The check is performed recursively.

Example:

guile> (cog-subtype? 'Node 'Link)
#f
guile> (cog-subtype? 'Atom 'Link)
#t
guile> (cog-subtype? 'Atom 'ConceptNode)
#t

cog-map-type proc type

Call procedure proc for each atom in the atomspace that is of type type. If proc returns any value other than #f, then the iteration is terminated. Note that this iterates only over the given type, and not its sub-types. Thus (cog-map-type proc 'Atom) will never call proc, because no atoms in the atomspace can have the type Atom: they are all subtypes of Atom.

Example:

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

AtomSpace Functions

The following are functions for creating and manipulating atomspaces. See the page Multiple AtomSpaces for a discussion of what these are and how they can be used. The cog-node, cog-new-node, cog-link, cog-new-link, cog-delete, cog-purge, cog-delete-recursive and cog-purge-recursive calls can all take an atomspace as one of their arguments, in which case, the operation will be performed on the indicated atomspace, instead of the default one.

cog-atomspace

Return the current atomspace for this evaluator and thread.

Example:

guile> (cog-atomspace)
#<atomspace 0x1e9cad0>

cog-atomspace?

Return #t if the symbol names an atomspace, else return #f

Example:

guile> (cog-atomspace? 'ConceptNode)
#f
guile> (cog-atomspace? (cog-atomspace))
#t

cog-new-atomspace

Create a new atomspace, either stand-alone, or as a child of an existing space.

For example, this creates a new, independent atomspace:

guile> (cog-new-atomspace)
#<atomspace 0x7fb8380009d0>

While this creates a child space of the current atomspace:

guile> (cog-new-atomspace (cog-atomspace))
#<atomspace 0x7fc938000620>

cog-set-atomspace!

Set the current atomspace for this evaluator and thread. Return the previously current atomspace.

Example:

guile> (define alt-as (cog-new-atomspace))

guile> (cog-set-atomspace! alt-as)
#<atomspace 0x1e9cad0>

Logger

The OpenCog logger has also scheme bindings.

Usage

In order to use the logger you need to load its module first.

Load the logger module

guile> (use-modules (opencog logger))

Log a message

guile> (cog-logger-info "My info message")

The logger support scheme string format you can easily log other object than strings:

guile> (cog-logger-info "My concept ~a" (ConceptNode "A"))

Change the log level

You can change the logging level with the `cog-logger-set-level!` function, such as:

(cog-logger-set-level! "debug")

Supported levels are: "error", "warn", "info", "debug" and "fine", case doesn't matter.

Change the filname

The default filename is `opencog.cog` in the current directory. You can change this filename as follows:

(cog-logger-set-filename! "my/new/log/filename.log")

Redirect the log to stdout

Alternatively you may redirect the log output directly to stdout:

(cog-logger-set-stdout! #t)

When you wish to disable it, call it again with `#f`.

See [1] for more information about scheme string format.

More Info

Other useful functions to change the log filepath, level and more are also available. See [2] for a complete listing, and [3] for examples of most available functions.

Ad-Hoc Commands

The scheme module provides a generic mechanism to declare new scheme "primitive functions" i.e. functions which call methods on a C++ object. New primitives may be defined by using the "define_scheme_primitive" function in opencog/guile/SchemePrimitive.h.

A number of these have been implemented; the below is an incomplete list

Available when the pattern matcher module is loaded:

Persistant storage commands, available when the PersistModule is loaded, and connected to a database:

  • fetch-atom handle -- fetch indicated atom from SQL/persistent storage.
  • fetch-incoming-set handle -- fetch the incoming set from SQL/persistent storage.
  • store-atom handle -- store indicated atom to SQL/persistent storage.
  • load-atoms-of-type type -- fetch atoms of the given type from SQL/persistent storage.
  • barrier -- block until the SQL Atom write queues are empty.

Word-sense disambiguation. This command requires a considerable amount of infrastructure to be set up:

  • do-wsd -- run word-sense disambiguation

Notes, examples, utilities

Various related notes.

Load scheme data from a file

There are two ways to load scheme from a file: automatically, at server startup, or manually.

To load automatically, edit opencog.conf, and append the filename to the line SCM_PRELOAD, for example:

SCM_PRELOAD = scm/type_constructors.scm, scm/utilities.scm

The cogserver is then started with the -c flag:

cogserver -c ../lib/opencog.conf

To manually load scheme code, simply make sure the first 3 characters of the file are "scm" followed by a carriage return. Then, at the shell prompt, simply execute the command:

 
cat filename | telnet localhost 17001

This assumes the scheme code is in "filename", that the cogserver is running on "localhost", and is listening on port 17001 (which is the default port for the cogserver).

Alternately, if the first three letters of the file are not scm, then they can be inserted with an echo:

echo "scm" | cat - filename | telnet localhost 17001

Netcat can be used instead of telnet.

Utilities

A number of handy utilities can be found in opencog/scm/utilities.scm as well as NLP-specific utilities in opencog/nlp/scm/nlp-utils.scm. These include small, simple routines for following a link from one atom type to another, finding all EvaluationLinks having some given form, filtering lists based on atom types, and so on.

Count the total number of atoms in the atomspace

Here is a simple example showing how to count the total number of atoms in the atomspace.

(define (cnt-all)
   (define cnt 0)
   (define (incrm a) (set! cnt (+ cnt 1)) #f)
   (define (cnt-type x) (cog-map-type incrm x)) 
   (map cnt-type (cog-get-types))
   cnt
)

Show atom counts by type

A more complex example, which shows the count of atoms of each type:

(define (show-cnts)
  (define (cnt-type ty)
    (let ((cnt 0))
      (define (incrm a) (set! cnt (+ cnt 1)) #f)
      (cog-map-type incrm ty)

      ; print only the non-zero counts
      (if (< 0 cnt)
        (begin
          (display ty)
          (display "  ")
          (display cnt)
          (newline)
        )
      )
    )
  )
  (for-each cnt-type (cog-get-types))
)

Print all atoms in the AtomSpace

This will print all of the atoms in the atomspace: specifically, only those atoms that have no incoming set, and thus are at the top of a hierarchy. All other atoms (those which do have an incoming set) then appear somewhere underneath these top-most atoms. Note that cog-map-type does not automatically recurse over sub-types; this is done explicitly, below.

(define (prt-atomspace) 
  (define (prt-atom h) 
    ; print only the top-level atoms.
    (if (null? (cog-incoming-set h)) 
        (display h))   
  #f)
  (define (prt-type type)
    (cog-map-type prt-atom type)
    ; We have to recurse over sub-types
    (for-each prt-type (cog-get-subtypes type))
  )
  (prt-type 'Atom)                          
)

Delete a list of atoms

Below is a simple example of scheme code for deleting all of the atoms in a list.

(define (killall lst) 
   (if (null? lst) 
       '() 
       (cons (cog-delete (car lst)) 
             (killall (cdr lst)))))

Working with Truth Values

Here are some handy utilities for working with truth values:

; Return the strength of a simple truth value
(define (get-tv-strength tv) (cdr (assoc 'mean (cog-tv->alist tv))))
 
; Return the confidence of a simple truth value
(define (get-tv-confidence tv) (cdr (assoc 'confidence (cog-tv->alist tv))))
 
; Return the strength of the truth value on atom h
(define (cog-stv-strength h) (get-tv-strength (cog-tv h)))
 
; Return a truth value where the strength was multiplied by 'val'
(define (scale-tv-strength val tv)
  (cog-new-stv
    (* val (get-tv-strength tv))
    (get-tv-confidence tv)
  )
)
 
; On atom h, multiply the truth-value strength by 'val'
(define (scale-strength h val)
  (cog-set-tv! h (scale-tv-strength val (cog-tv h)))
)
 
; Return the truth value strength of an atom
(define (cog-tv-strength x) (cdr (assoc 'mean (cog-tv->alist (cog-tv x)))))
 
; Given a threshold 'y' and a list of atoms 'z', returns a 
; list of atoms with truth value strength above the threshold
(define (cog-tv-strength-above y z) (filter (lambda (x) (> (cog-tv-strength x) y)) z))

Working with Attention Values

Here are some handy utilities for working with atom attention values:

; Return the STI of an atom
(define (cog-av-sti x) (cdr (assoc 'sti (cog-av->alist (cog-av x)))))

; Given a threshold 'y' and a list of atoms 'z', 
; returns a list of atoms with STI above the threshold
(define (cog-sti-above y z) (filter (lambda (x) (> (cog-av-sti x) y)) z))

; Given a threshold 'y' and a list of atoms 'z', 
; returns a list of atoms with STI below the threshold
(define (cog-sti-below y z) (filter (lambda (x) (< (cog-av-sti x) y)) z))

Calling scheme from C++

Scheme code can be called from C++. The most common case is shown below: calling a scheme function which expects 0,1,2 or more Handle arguments, and returns a Handle. So, for example, assume you have a scheme function called do-stuff as follows:

(define (do-stuff handle1 handle2) (... return some-hand ...))

Then you can call it from C++ as follows:

// Create a LIST_LINK on stack, holding the input arguments.
Handle arg1 = ...;
Handle arg2 = ...;
Link lnk(LIST_LINK, arg1, arg2;...);    // constructor runs on stack
Handle hlnk = TLB::getHandle(&lnk);     // handle of the list link

// Create a new evaluator, using the cogserver atomspace by default.
SchemeEval evaluator(&cogserver().getAtomSpace());

// Call the "do-stuff" function
Handle answer = evaluator.apply("do-stuff", hlnk);

If do-stuff doesn't take any arguments, then set hlink to Handle::UNDEFINED, or pass an empty ListLink.

The above form is used by the ExecutionLink to embed scheme callouts into hypergraphs.

Calling C++ from scheme

The C++ programmer may define new scheme primitive functions by using the define_scheme_primitive function in opencog/guile/SchemePrimitive.h. This function expects a string that will be the scheme name, a C++ method, and a pointer to a C++ object instance. Unusual C++ signatures may require extending opencog/guile/SchemePrimitive.h, but this should not be hard.

The example program examples/c%2B%2B-guile/PrimitiveExample.cc shows how.

Calling scheme from Hypergraphs

The ExecutionOutputLink, when used with the GroundedSchemaNode, allows scheme code to be invoked when the given ExecutionOutputLink is evaluated with cog-execute!, and by the pattern matcher. See those pages for details.

Likewise, EvaluationLinks containing GroundedPredicateNodes can have embedded scheme code that evaluates into a truth value. In this case, either cog-evaluate! or the pattern matcher can be used.

Multi-threading

At this time, the scheme infrastructure should be both thread-safe and thread-enabled. That is, multiple threads should be able to safely evaluate scheme expressions in parallel. However, there are some locks in the code that still serialize access. Those locks can probably be removed, but no one has really experimented, there's no unit test case, and things may or may not break as a result. Lack of demand and interest has halted forward progress. This should be fixed.

The guile parallel-foreach and parallel-map do seem to work just fine, and mostly do seem to speed things up, if your code isn't horrible to begin with.

See Also

Pattern Miner Functions

Please see Pattern Miner Scheme Functions.