OpenCogPrime:AbstractSchemaManipulation
Advanced Schema Manipulation
On this page we describe some special schema for manipulating schema, which seem to be very useful in certain contexts.
Listification
First, there are two ways to represent n-ary relations in OCP's Atom level knowledge representation language: using lists as in
f_list (x1, …, xn )
or using currying as in
f_curry x1, …, xn
To make conversion between list and curried forms easier, we have chosen to introduce special schema (combinators) just for this purpose:
Listify f = f_list so that f_list (x1, …, xn ) = f x1 … xn Unlistify Listify f = f
For instance
kick_curry Ben Ken
denotes
(kick_curry Ben) Ken
which means that kick is applied to the argument Ben to yield a predicate schema applied to Ken. This is the curried style. The list style is
kick_List (Ben, Ken)
where kick is viewed as taking as an argument the List (Ben, Ken). The conversion between the two is done by
listify kick_curry = kick_list unlistify kick_list = kick_curry
As a more detailed example of unlistification, let us utilize a simple mathematical example, the function
(X- 1 )^2
As noted there, if we use the notations -, *, Square and Power to denote SchemaNodes embodying the corresponding operations, then then this formula may be written in variable-free node-and-link form as
ExOutLink pow ListLink ExOutLink - ListLink X 1 2
But to get rid of the nasty variable X, we need to first unlistify the functions pow and -, and then apply the C combinator a couple times to move the variable X to the front. This is accomplished as follows:
pow [ - [x,1], 2 ] unlistify pow (-[x,1]) 2 C (unlistify pow) 2 (-[x,1]) C (unlistify pow) 2 ((unlistify -) x 1) C (unlistify pow) 2 (C (unlistify -) 1 x) B ( C (unlistify pow) 2) ( C (unlistify — ) 1) x
yielding the final schema
B ( C (unlistify pow) 2) ( C (unlistify — ) 1)
By the way, a variable-free representation of this schema in OCP would look like
ExOutLink B ExOutLink ExOutLink ExOutLink C ExOutLink unlistify pow 2 ExOutLink C ExOutLink unlistify - 1
This representation may be difficult for the reader who lacks experience with functional programming. It involves the C combinator (discussed above), and the unlistify operator, defined so that e.g.
((unlistify f) x) (y) = f (x, y)
These concepts will be discussed in detail later, and used to do this example (and others) with more thorough explanation.
The main thing to be observed, however, is that the introduction of these extra schema lets us remove the variable X. The size of the schema is increased slightly in this case, but only slightly — an increase that is well-justified by the elimination of the many difficulties that explicit variables would bring to the system. Furthermore, there is a shorter rendition which looks like
ExOutLink B ExOutLink ExOutLink ExOutLink C pow_curried 2 ExOutLink C -_curried 1
This rendition uses alternate variants of - and pow schema, labeled -_curried and pow_curried, which do not act on lists but are curried in the manner of combinatory logic and Haskell. It is 11 lines whereas the variable-bearing version is 8 lines, a trivial increase in length that brings a lot of operational simplification.
Finally, in case the indent notation is confusing, we give a similar example in a more standard predicate logic notation. We will translate the variable-laden predicate
likes(y,x) AND likes(x,y)
into the equivalent combinatory logic tree. Assume that the two inputs are going to be given to us as a list. Now, the combinatory logic representation of this is
S (B AND (B likes (listify C)) likes
using the standard convention of left-associativity for @.
We now show how this would be evaluated to produce the correct expression:
S (B AND (B likes (listify C)) likes (x,y)
S gets evaluated first, to produce
B AND (B likes (listify C)) (x,y) (likes (x,y))
now the first B
AND (B likes (listify C) (x,y)) (likes (x,y))
now the second one
AND (likes ((listify C) (x,y)) (likes (x,y)))
now the listified C
AND (likes (y,x)) (likes (x,y)) )
which is what we wanted.
Argument Permutation
In dealing with List relationships, there will sometimes be use for an argument-permutation operator
ListOfAtom PermuteArgumentList(Permutation p, ListOfAtom A)
The semantics are that
(P f) (v1,…, vn ) = f ( P (v1,…, vn ) )
where P is a permutation on n letters. This deals with the case where we want to say, for instance that
Equivalence parent(x,y) child(y,x)
Instead of positing variable names x and y that span the two relations parent(x,y) and child(y,x), what we can instead say in this example is
Equivalence parent ( PermuteArgumentList {2,1} child )
For the case of two-argument functions, argument permutation is basically doing on the list level what the C combinator does in the curried function domain. On the other hand, in the case of n-argument functions with n>2, argument permutation doesn't correspond to any of the standard combinators.