OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / examples / flow / flows.scm

164 lines · scm ref:
;
; flows.scm -- Flowing Values between Atoms.
;
; Atoms can be thought of as "pipes", and Values as the thing that
; "flows through the pipes".  This is a reasonable analogy, because
; Atoms are fairly heavyweight and are immutable, and require a lot of
; machinery to be placed in the AtomSpace. That machinery is required
; in order to be able to search (perform queries) over Atoms. Values,
; by contrast, are much smaller and simpler. They are mutable,
; ephemeral, and can change rapidly. (The price for this: they cannot
; be searched!).
;
; But how does the "fluid" flow in the "pipes"? The example below walks
; through ways in which Values can be pulled out of specific Atoms, then
; transformed or mutated in some specific way, and then re-injected.
; In these examples, the mutations are arithmetic formulas that are
; applied to the Values. The formulas themselves are expressed as
; Atomese.
;
; The goal of having formulas in Atomese is that such formulas, rather
; than being hard-coded in Python, C++ or scheme, can instead be
; imported from either existing datasets (such as the Systems Biology
; Markup Language) or they can be obtained by machine learning (such
; as MOSES).
;
; See the `flow-formulas.scm` example for how to work with dynamically
; updating flows.

(use-modules (opencog))

; The Value is located at key (Predicate "*-TruthValueKey-*")
(define tvkey (Predicate "*-TruthValueKey-*"))

; An atom with a FloatValue on it...
(cog-set-value! (Concept "foo") tvkey (FloatValue 0.3 0.7))

; This is how we get it's Value ...
(cog-execute! (ValueOf (Concept "foo") tvkey))

; Transfer the FloatValue from "foo" to "bar" ... copy it.
(cog-execute!
	(SetValue (Concept "bar") tvkey
		(ValueOf (Concept "foo") tvkey)))

; Verify that the TV on "bar" has changed.
(cog-value (Concept "bar") tvkey)

; SetValue is interesting because it allows complex arithmetic expressions
; to be specified in Atomese. Below, simply take the square of the TV.
(cog-execute!
	(SetValue
		(Concept "bar") tvkey
		(Times
			(FloatValueOf (Concept "foo") tvkey)
			(FloatValueOf (Concept "foo") tvkey))))

; Formulas can be used to compute TV's, as shown in the `formula.scm`
; example. Consider a named formula, with variables.
(define (strength-of ATOM) (ElementOf (Number 0) (ValueOf ATOM tvkey)))
(define (confidence-of ATOM) (ElementOf (Number 1) (ValueOf ATOM tvkey)))

(DefineLink
   (DefinedProcedure "has a reddish color")
	(Lambda
		(VariableList (Variable "$X") (Variable "$Y"))
		(FloatColumn
			(Minus
				(Number 1)
				(Times
					(strength-of (Variable "$X"))
					(strength-of (Variable "$Y"))))
			(Times
				(confidence-of (Variable "$X"))
				(confidence-of (Variable "$Y"))))))

; Some data...
(cog-set-value! (Concept "A") tvkey (FloatValue 0.9 0.98))
(cog-set-value! (Concept "B") tvkey (FloatValue 0.9 0.98))

; Use the formula to compute a new TV, and attach that TV to some Atom.
; This is little more than the copy above, except that the evaluation
; is actually performed, so that the new TV is computed, before being
; copied. In general, if the third Atom passed to SetValue is executable,
; then it will be executed to obtain the TV.
(cog-execute!
	(SetValue
		(Concept "bar") tvkey
		(ExecutionOutput
			(DefinedProcedure "has a reddish color")
			(List (Concept "A") (Concept "B")))))

; That the above really does flow the TV from one place to another can
; be seen by looking at dynamic changes. So -- change the TV on A,
; and recompute...
(cog-set-value! (Concept "A") tvkey (FloatValue 0.8 0.9))
(cog-execute!
	(SetValue
		(Concept "bar") tvkey
		(ExecutionOutput
			(DefinedProcedure "has a reddish color")
			(List (Concept "A") (Concept "B")))))

; In many ways, the SetValueLink behaves a lot like a generalized
; EvaluationLink. So: normally, an EvaluationLink consists of a
; predicate, and the list of arguments that it applies to. The
; SetTVLink is similar, except that it couples the predicate to
; the target Atom that it should apply to.  This can be seen in
; the equivalent form, below.
(cog-execute!
	(SetValue
		(Concept "bar") tvkey
		(DefinedProcedure "has a reddish color")
		(List (Concept "A") (Concept "B"))))

; -----------------------------------------------------------
; Everything demonstrated above can be done in a generalized way, for
; arbitrary values. The primary difference is that the SetValueLink is
; used for this, and a key must be provided as an additional argument.

(define foo (Concept "foo"))
(define bar (Concept "bar"))
(define key (Predicate "some key"))
(define kee (Predicate "other key"))

; Start by setting a value in the "traditional fashion"
(cog-set-value! foo key (FloatValue 1 2 3 4 5))

; Take a look at it
(cog-execute! (ValueOf foo key))

; Copy from foo to bar
(cog-execute! (SetValue bar kee (ValueOf foo key)))

; Take a look at it
(cog-execute! (ValueOf bar kee))

; Try out some math
(cog-execute! (SetValue bar kee
	(Times (FloatValueOf foo key) (FloatValueOf foo key))))

; Verify
(cog-execute! (ValueOf bar kee))

; Define a procedure that computes N(N+1)/2 aka a "triangle number".
; A Procedure is used, instead of a DefinedSchema, since, in principle,
; DefinedSchema should be limited to returning only Atoms, and not
; Values in general.
(DefineLink
   (DefinedProcedure "triangle numbers")
	(Lambda
		(Variable "$X")
		(Divide
			(Times (Variable "$X") (Plus (Variable "$X") (Number 1)))
			(Number 2))))

; Apply the schema to a vector of numbers, and attach the result to
; the bar Atom, much as before.
(cog-execute!
	(SetValue bar kee
		(DefinedProcedure "triangle numbers")
		(FloatValueOf foo key)))
;
; -------- THE END -----------