Extending ExecutionLink...

29 views
Skip to first unread message

Ben Goertzel

unread,
Apr 29, 2013, 4:01:02 AM4/29/13
to opencog, hk-a...@opencog.org, Linas Vepstas, Ramin Barati
Hi Linas, Ramin, etc. ,

In the course of the recent dialogue w/ Linas about the pattern
matcher, it has occurred to me that it would be very useful to have
some extensions to the current Execution Link...

As currently defined at

http://wiki.opencog.org/w/ExecutionLink

the practical definition of ExecutionLink seems to be

ExecutionLink
SchemaNode schema-name
ListLink
SomeAtom arg_1
OtherAtom arg_2
...

However, in the prior OpenCog conceptual documentation, there is an
optional additional argument, so that we would have


BindLink
VariableNode $v1
ExecutionLink
SchemaNode schema-name
ListLink
SomeAtom arg_1
OtherAtom arg_2
...
$v1


The semantics of this would be: once the schema is run on the given
arguments, the resultant output is put into the variable $v1

For convenience, we could also define a SequentialExecutionLink.
This would take as its argument a list of GroundedSchemaNodes, i.e.


BindLink
VariableNode $v1
VariableNode $v2
...
VariableNode $vn
SequentialExecutionLink
(GroundedSchemaNode gs_1, args_1)
(GroundedSchemaNode gs_2, args_2)
...
(GroundedSchemaNode gs_n, args_n)

The basic idea is that, when the Sequential ExecutionLink is executed, then

-- The output of running GroundedSchemaNode gs_k, is placed into the
variable $v_k

-- The argument of GroundedSchemaNode gs_k, args_k, may use the
variables $v_1 ... $v_(k-1)....

-- Also, the GroundedSchemaNode gs_k, itself, may be defined as one of
the variables $v1 ... $v_{k-1}


...

Using this construct, a PLN ForwardInferenceStep might be written like

BindLink
VariableNode $var, $R, $var1
SequentialExecutionLink
GroundedSchemaNode ChooseRandomLinkSourceInAttentionalFocus
(GroundedSchemaNode ChooseInferenceRule , $var )
(GroundedSchemaNode ChooseInferenceArgument, ($var, $R) )
(GroundedSchemaNode $R, ($var, $var1) )

...

This would seem to give us a simple way to code simple cognitive
processes (like inference steps) directly in the OpenCog hypergraph...

In the case of backward inference, one of the GroundedSchemaNodes
invoked in the sequence would itself contain code invoking the pattern
matcher...

We could also have Simultaneous ExecutionLink, of course, and nest the
two types to do stuff like (suppressing the explicit List and
compressing the notation a little)

BindLink
VariableNode ($v1, $v2, $v3, $v4)
SequentialExecutionLink
GroundedSchemaNode gs1
SimultaneousExecutionLink
(GroundedSchemaNode gs2 ,$v1 )
(GroundedSchemaNode gs3, $v1 )
(GroundedSchemaNode gs4, ($v2, $v3))


The "executor" in the pattern matcher could potentially be extended to
handle these constructs...

Thoughts?

-- Ben



--
Ben Goertzel, PhD
http://goertzel.org

"My humanity is a constant self-overcoming" -- Friedrich Nietzsche

Linas Vepstas

unread,
Apr 29, 2013, 10:39:27 AM4/29/13
to Ben Goertzel, opencog, hk-a...@opencog.org, Ramin Barati
I see the general idea you are moving towards. However, I'm having some trouble understanding how to "put something" into a Node.  A node is a node ... it is not a container.   More below.

For convenience, we could also define a SequentialExecutionLink.
This would take as its argument a list of GroundedSchemaNodes, i.e.


BindLink
      VariableNode $v1
      VariableNode $v2
      ...
      VariableNode $vn
   SequentialExecutionLink
         (GroundedSchemaNode gs_1, args_1)
         (GroundedSchemaNode gs_2, args_2)
          ...
         (GroundedSchemaNode gs_n, args_n)

The basic idea is that, when the Sequential ExecutionLink is executed, then

-- The output of running GroundedSchemaNode gs_k, is placed into the
variable $v_k

-- The argument of GroundedSchemaNode gs_k, args_k, may use the
variables $v_1 ... $v_(k-1)....

-- Also, the GroundedSchemaNode gs_k, itself, may be defined as one of
the variables $v1 ... $v_{k-1}


You are describing what would be called "define", "let", "let*" or "letrec" in lisp.

Rather than overloading BindLink with this, lets just create a new link type to handle this, say DefineLink or LetLink.  And instead of using VariableNode, lets call it NamedFunctionNode or just NameNode.  So, for a single schema:

DefineLink
   NameNode "$my-schema"
   (GroundedSchemaNode gs_1, args_1)

Then, later on, if there is some other schema that has NameNode as one of the args, that would be replaced by the value generated by gs_1

The only (major) difference between what I just said and what you just said is that I changed the name from BindLink to DefineLink and  VariableNode to NameNode.  The reason I changed the names is because BindLink is already being used for something else, and overloading that name will lead to confusion.

The SequentialExectuationLink is more like lisp "let" or "let*" or "letrec"  Its just some "syntactic sugar" that makes it prettier to write a bunch of define's in a row (and have them have only local scope).

I'm not sure why you are distinguishing Sequential and Simultaneous.  Certainly, the  lessons from lazy evaluation is that it doesn't matter.  The lazy evaluator just pulls those values that it actually needs at any given point in time; there is no implied time-ordering and evaluation can be done 'out-of-order' or in parallel, (by multiple threads), governed entirely by the dependency graph of which schemas needed which arguments.

I don't see how this has anything at all to do with the pattern matcher; its a very different thing.  The 'executor' class in the pattern matcher is nothing at  all high-tech; its at most a few dozen lines of code that make sure it got a bona-fide  ExecutionLink,  counts the number of arguments, and checks for errors.   Its dumb as a bucket.  You wouldn't want to re-use it.  At best, its a cheat-sheet for how to invoke scheme from C++ ... and that takes exactly one line of code.  (Invoking python from C++ is "almost" one line of code, except that it crashes for me, so I don't get it.).

--linas

Linas Vepstas

unread,
Apr 29, 2013, 11:02:10 AM4/29/13
to Ben Goertzel, opencog, hk-a...@opencog.org, Ramin Barati
Just after hitting send on the previous email, it occurred to me that I should add just one more thing.  Although I do so with trepidation, for fear of confusing the issue.  The DefineLink/NameNode thing is just a general naming scheme. There is no reason to restrict it to be only ExecutionLinks.   You could, for example say:

DefineLink
   NameNode "$v1"
   (SetLink  A B C D)

and so wherever $v1 showed up, it would get replaced by SetLink ABCD  What you described in the original email was just this:

DefineLink
   NameNode $v2
   ExecutionLink ...

and then described how $v2 would be replaced by the results of performing ExecutionLink.

The only way I see the pattern matcher playing any role in this would be if one had:

DefineLink
   NameNode $v3
   BindLink ....

Whenever $v3 was seen, it would be replaced by the results of performing BindLink.  

I think this decouples the concept of naming things from the concept of executing things (and chaining them together by using names).

-- linas.

Ben Goertzel

unread,
Apr 29, 2013, 11:18:13 AM4/29/13
to linasv...@gmail.com, opencog, hk-a...@opencog.org, Ramin Barati
Hi Linas,

> The only (major) difference between what I just said and what you just said
> is that I changed the name from BindLink to DefineLink and VariableNode to
> NameNode. The reason I changed the names is because BindLink is already
> being used for something else, and overloading that name will lead to
> confusion.

Yeah, I think you're right....

Actually, in the Webmind AI Engine design, way back when, I made that same
mistake, and used the same VariableNode class for both logical variables
and schema-result variables.... I figured out a semantics under which this was
mathematically consistent, but you're correct that it made things
pretty confusing...
Amazingly, Anton Kolonin (aka the "Siberian Madmind" from Novosibirsk)
understood it all and made it work, but it was a mess...

It's cleaner to keep these two kinds of variables separate

I'm fine with

DefineLink
NameNode "$my-schema"
(GroundedSchemaNode gs_1, args_1)

> The SequentialExectuationLink is more like lisp "let" or "let*" or "letrec"
> Its just some "syntactic sugar" that makes it prettier to write a bunch of
> define's in a row (and have them have only local scope).

yes

> I'm not sure why you are distinguishing Sequential and Simultaneous.
> Certainly, the lessons from lazy evaluation is that it doesn't matter. The
> lazy evaluator just pulls those values that it actually needs at any given
> point in time; there is no implied time-ordering and evaluation can be done
> 'out-of-order' or in parallel, (by multiple threads), governed entirely by
> the dependency graph of which schemas needed which arguments.

yeah, you are right once again.... The process that executes the
SequentialExecutionLink can figure out what order to execute the schema in...

So probably we should call it the CompositeExecutionLink or something,
instead of
SequentialExecutionLink...

> I don't see how this has anything at all to do with the pattern matcher; its
> a very different thing.

Use of the pattern matcher, and use of DefineLink and SequentialDefineLink,
are two aspects of "programming with hypergraphs" as you were recently
urging

The PLN design as I'm envisioning it would use these two mechanisms together...

-- Ben
Reply all
Reply to author
Forward
0 new messages