Overview
This issue contains some considerations regarding various ways Atomese
programs could be represented, manipulated and evaluated.
Warning: it is not a plan for immediate actions, just some considerations.
Motivation
As suggested by @Bitseat in order to avoid hacking too much the
atomese interpreter
https://github.com/opencog/atomspace/blob/master/opencog/atoms/execution/Instantiator.h#L141
an option would be to unfold an Atomese program to be readily
interpretable by Instantiator::execute.
For instance given the data set represented as
(Similarity (stv 1 1)
(List (Schema "o") (Schema "i1") (Schema "i2"))
(Set
(List (Node "r1") (List (Number 1) (Number 0) (Number 1)))
(List (Node "r2") (List (Number 1) (Number 1) (Number 0)))
(List (Node "r3") (List (Number 0) (Number 0) (Number 0)))))
and the combo program
(Plus (Schema "i1") (Schema "i2"))
It could be unfolded into
(Set
(List (Node "r1") (Plus (Number 0) (Number 1)))
(List (Node "r2") (Plus (Number 1) (Number 0)))
(List (Node "r3") (Plus (Number 0) (Number 0))))
which passed to the Atomese interpreter would return the desired
result
(Set
(List (Node "r1") (Number 1))
(List (Node "r2") (Number 1))
(List (Node "r3") (Number 0)))
However I'm thinking we can probably take a middle ground approach
where the unfolding would be much lighter and wouldn't involve hacking
the interpreter so that Plus, etc would support higher level inputs
(which ultimately is probably fine and desired, but since we are in an
exploratory stage we want to avoid too much potentially unnecessary
and complicated hacking). Also, I suspect that this sort of
lightweight unfolding will be beneficial for subsequent Atomese
program processing, such as finding patterns in a population of
programs and evaluating them on new inputs.
Proposal
So here it goes, for instance given (Plus (Schema "i1") (Schema "i2")), the first level of unfolding could be (using unimplemented FunMapLink)
(FunMap
(List
(Variable "$R")
(Lambda
(Variable "$R")
(Plus
(ExecutionOutput
(Schema "f1")
(Variable "$R"))
(ExecutionOutput
(Schema "f2")
(Variable "$R")))))
(Domain))
where FunMap is to be distinguished from
http://wiki.opencog.org/w/MapLink as it doesn't assume that its first
argument is a pattern but rather a function, and thus has the same
semantics as
https://hackage.haskell.org/package/base-4.11.1.0/docs/Prelude.html#v:map
or in scheme
https://srfi.schemers.org/srfi-1/srfi-1.html#FoldUnfoldMap
And Domain is just something that retrieves the row names, r1 to
r3, and should probably be written
(Domain (List (Schema "f1") (Schema "f2")))
but is just written (Domain) here for simplicity.
So written in a more casual functional program style it would be
(map (lambda (r) (cons r (+ (f1 r) (f2 r)))) (domain))
Alternatively, as suggested by @kasimebrahim, one could use PutLink
(Put
(Variable "$R")
(List
(Variable "$R")
(Put
(Lambda
(Variable "$R")
(Plus
(ExecutionOutput
(Schema "f1")
(Variable "$R"))
(ExecutionOutput
(Schema "f2")
(Variable "$R"))))
(Variable "$R")))
(Domain))
The next unfolding, which is probably the most interesting is
(FunMap
(List
(Variable "$R")
(Put
(Lambda
(VariableList
(Variable "$X")
(Variable "$Y"))
(Plus
(Variable "$X")
(Variable "$Y")))
(Lambda
(Variable "$R")
(List
(Schema "f1")
(Schema "f2"))))
(Domain)))
because it exposes the heart of the program
(Lambda
(VariableList
(Variable "$X")
(Variable "$Y"))
(Plus
(Variable "$X")
(Variable "$Y")))
then links it to the inputs i1 and i2, via using Put, then
applies to the domain r1 to r3. The good thing about this
representation is that it allows to abstract away the features (which
can be better to reason about some patterns), and it also makes it
easier to evaluate it on new inputs, because you only need to change
one place (Domain) by say (NewDomain) to express that simply.
Overview
This issue contains some considerations regarding various ways Atomese
programs could be represented, manipulated and evaluated.
Warning: it is not a plan for immediate actions, just some considerations.
Motivation
As suggested by @Bitseat in order to avoid hacking too much the
atomese interpreter
https://github.com/opencog/atomspace/blob/master/opencog/atoms/execution/Instantiator.h#L141
an option would be to unfold an Atomese program to be readily
interpretable by
Instantiator::execute.For instance given the data set represented as
and the combo program
It could be unfolded into
which passed to the Atomese interpreter would return the desired
result
However I'm thinking we can probably take a middle ground approach
where the unfolding would be much lighter and wouldn't involve hacking
the interpreter so that
Plus, etc would support higher level inputs(which ultimately is probably fine and desired, but since we are in an
exploratory stage we want to avoid too much potentially unnecessary
and complicated hacking). Also, I suspect that this sort of
lightweight unfolding will be beneficial for subsequent Atomese
program processing, such as finding patterns in a population of
programs and evaluating them on new inputs.
Proposal
So here it goes, for instance given
(Plus (Schema "i1") (Schema "i2")), the first level of unfolding could be (using unimplementedFunMapLink)where
FunMapis to be distinguished fromhttp://wiki.opencog.org/w/MapLink as it doesn't assume that its first
argument is a pattern but rather a function, and thus has the same
semantics as
https://hackage.haskell.org/package/base-4.11.1.0/docs/Prelude.html#v:map
or in scheme
https://srfi.schemers.org/srfi-1/srfi-1.html#FoldUnfoldMap
And
Domainis just something that retrieves the row names,r1tor3, and should probably be writtenbut is just written
(Domain)here for simplicity.So written in a more casual functional program style it would be
Alternatively, as suggested by @kasimebrahim, one could use
PutLinkThe next unfolding, which is probably the most interesting is
because it exposes the heart of the program
then links it to the inputs
i1andi2, via usingPut, thenapplies to the domain
r1tor3. The good thing about thisrepresentation is that it allows to abstract away the features (which
can be better to reason about some patterns), and it also makes it
easier to evaluate it on new inputs, because you only need to change
one place
(Domain)by say(NewDomain)to express that simply.