-
Notifications
You must be signed in to change notification settings - Fork 234
/
flow-formulas.scm
250 lines (213 loc) · 8.97 KB
/
flow-formulas.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
;
; flow-formulas.scm -- Dynamically changing flows.
;
; The concept of a "value flow" is the idea that a Value can change
; dynamically, recomputed from a formula that draws on it's inputs.
; Examples of such formulas are provided below, together with the
; code for wiring them into Atoms.
;
; The core implementation is in two parts: the FormulaTruthValue,
; which implements a dynamically-variable TruthValue, and the
; FormulaPredicateLink, which specifies the formula used to compute
; the TruthValue.
;
; The FormulaTruthValue is a kind of SimpleTruthValue, such that, every
; time that it is accessed, the current value -- that is, the current
; pair of floating point numbers -- is recomputed. The recomputation
; occurs every time the numeric value is accessed (i.e. when the
; strength and confidence of the TV are accessed).
;
; Note that SimpleTV's are just vectors of length two - the strength
; and confidence. These are generalized by FloatValue, which can hold
; a vector of arbitrary length.
;
; The FormulaStream generalizes the FormulaTruthValue, so that it can
; work with any FloatValue, not just TruthValues. An introductory demo
; is provided at the bottom of this file. A more complex demo is in the
; `flow-futures.scm` file.
(use-modules (opencog) (opencog exec))
; The FormulaTruthValue is a kind of TruthValue that is recomputed,
; every time it is accessed. Thus, it is a kind of dynamically-changing
; TruthValue. The value to be computed can be defined in Atomese. Thus,
; in the following, the SimpleTV of (1-sA*sB, cA*cB) is computed.
(define tv-stream
(FormulaTruthValue
(Minus
(Number 1)
(Times
(StrengthOf (Concept "A"))
(StrengthOf (Concept "B"))))
(Times
(ConfidenceOf (Concept "A"))
(ConfidenceOf (Concept "B")))))
; Print it out. Notice a sampling of the current numeric value, printed
; at the bottom. Of course, at this point Concept A and B only have the
; default TV of (1, 0), and so the computed value should be (0, 0).
(display tv-stream) (newline)
; The numeric values only, are printed in a shorter, more readable
; fashion:
(cog-value->list tv-stream)
; When the inputs change, the value will track:
(cog-set-tv! (Concept "A") (stv 0.9 0.2))
(cog-set-tv! (Concept "B") (stv 0.4 0.7))
(cog-value->list tv-stream)
(cog-set-tv! (Concept "A") (stv 0.5 0.8))
(cog-value->list tv-stream)
(cog-set-tv! (Concept "B") (stv 0.314159 0.9))
(cog-value->list tv-stream)
; ----------
; The above example hard-codes the Atoms to be used in the formula.
; It is often convenient to use variables, so that a formula definition
; can be reused. Thus, lets recycle a portion of the `formulas.scm`
; example and create a formula for computing a SimpleTruthValue, based
; on two input Atoms.
(DefineLink
(DefinedPredicate "has a reddish color")
(FormulaPredicate
(Minus
(Number 1)
(Times
(StrengthOf (Variable "$X"))
(StrengthOf (Variable "$Y"))))
(Times
(ConfidenceOf (Variable "$X"))
(ConfidenceOf (Variable "$Y")))))
; Note that FormulaPredicate is a link type; it computes the same
; things as FormulaTruthValue, except that ... it is not a Value!
; It's a link.
; Create an EvaluationLink that will apply the formula above to a pair
; of Atoms. This is as before; see the `formulas.scm` example for details.
(define evlnk
(Evaluation
(DefinedPredicate "has a reddish color")
(List (Concept "A") (Concept "B"))))
; As in earlier examples, the TV on the EvaluationLink is recomputed
; every time that it is evaluated. We repeat this experiment here.
(cog-set-tv! (Concept "A") (stv 0.3 0.7))
(cog-set-tv! (Concept "B") (stv 0.4 0.6))
(cog-evaluate! evlnk)
(cog-tv evlnk)
; Now that we've verified that the EvaluationLink works as expected,
; it can be deployed in the stream.
(define ev-stream (FormulaTruthValue evlnk))
; Print it out. Notice a sampling of the current numeric value, printed
; at the bottom:
(display ev-stream) (newline)
; Change one of the inputs, and notice the output tracks:
(cog-set-tv! (Concept "A") (stv 0.9 0.2))
(cog-value->list ev-stream)
(cog-set-tv! (Concept "A") (stv 0.5 0.8))
(cog-value->list ev-stream)
(cog-set-tv! (Concept "B") (stv 0.314159 0.9))
(cog-value->list ev-stream)
; ----------
; This new kind of TV becomes interesting when it is used to
; automatically maintain the TV of some relationship. Suppose
; that A implied B, and the truth-probability of this is given
; by the formula above. So, first we write the implication:
(define a-implies-b (Implication (Concept "A") (Concept "B")))
; ... and then attach this auto-updating TV to it.
(cog-set-tv! a-implies-b tv-stream)
; Take a look at it, make sure that it is actually there.
(cog-tv a-implies-b)
; The above printed the "actual" TV, as it sits on the Atom.
; However, typically, we want the numeric values, and not the formula.
; These can be gotten simply by asking for them, directly, by name.
(format #t "A implies B has strength ~6F and confidence ~6F\n"
(cog-mean a-implies-b) (cog-confidence a-implies-b))
; Change the TV on A and B ...
(cog-set-tv! (Concept "A") (stv 0.4 0.2))
(cog-set-tv! (Concept "B") (stv 0.7 0.8))
; ... and the TV on the implication stays current.
; Note that a different API is demoed below.
(format #t "A implies B has strength ~6F and confidence ~6F\n"
(cog-tv-mean (cog-tv a-implies-b))
(cog-tv-confidence (cog-tv a-implies-b)))
; ----------
; So far, the above is using a lot of scheme scaffolding to accomplish
; the setting of truth values. Can we do the same, without using scheme?
; Yes, we can. Just use the PromisePredicateLink. This can wrap any
; evaluatable Atom, anything that can produce a TruthValue, and provides
; a promiste that it can be evaluated in the future. The when the SetTV
; is executed, then whatever was wrapped is unwrapped and placed into
; a FormulaTruthValue, which will then update every time it is accessed.
; For example:
(cog-execute!
(SetTV
(Implication (Concept "A") (Concept "B"))
(PromisePredicate
(FormulaPredicate
(Minus
(Number 1)
(Times
(StrengthOf (Concept "A"))
(StrengthOf (Concept "B"))))
(Times
(ConfidenceOf (Concept "A"))
(ConfidenceOf (Concept "B")))))))
; The above can be tedious, as it requires manually creating a new
; formula for each SetTV. Some of this tedium can be avoided by
; using formulas with variables in them. Using the same formula as
; before, we get a dynamic example:
(DefineLink
(DefinedPredicate "dynamic example")
(FormulaPredicate
(Minus
(Number 1)
(Times
(StrengthOf (Variable "$X"))
(StrengthOf (Variable "$Y"))))
(Times
(ConfidenceOf (Variable "$X"))
(ConfidenceOf (Variable "$Y")))))
; This can be used as anywhere any other predicate can be used;
; anywhere a PredicateNode, GroundedPredicateNode, DefinedPredicate,
; or FormulaPredicate can be used. They all provide the same utility:
; they provide a TruthValue. More precisely, a FormulaTruthValue
; is created, that wraps the 2nd and later args to the SetTV.
; This FormulaTruthValue is installed onto the first arg (the
; ImplicationLink). From thenceforth, any calls to get the TV
; on the ImplicatioLink get the FormulaTruthValue, which recomputes
; the TV value each time it's accessed.
(cog-execute!
(SetTV
(Implication (Concept "A") (Concept "B"))
(DefinedPredicate "dynamic example")
(Concept "A") (Concept "B")))
; Double-check, as before:
(cog-tv a-implies-b)
; Change the TV on A and B ...
(cog-set-tv! (Concept "A") (stv 0.1 0.9))
(cog-set-tv! (Concept "B") (stv 0.1 0.9))
; And take another look.
(format #t "A implies B has strength ~6F and confidence ~6F\n"
(cog-mean a-implies-b) (cog-confidence a-implies-b))
; -------------------------------------------------------------
; The FormulaStream is the generalization of FormulaTruthValue, suitable
; for streaming a FloatValue of arbitrary length. As before, whenever it
; is accessed, the current vector value is recomputed. The recomputation
; forced by calling `execute()` on the Atom that the stream is created
; with.
;
; Create an Atom, a key, and a random stream of five numbers.
; The random stream is a FloatValue vector, of length 5; each of
; the numbers are randomly distributed between 0.0 and 1.0
(define foo (Concept "foo"))
(define bar (Concept "bar"))
(define akey (Predicate "some key"))
(define bkey (Predicate "other key"))
(cog-set-value! foo akey (RandomStream 5))
; Take a look at what was created.
(cog-value foo akey)
; Verify that it really is a vector, and that it changes with each
; access. The StreamValueOfLink will sample from the RandomStream.
(cog-execute! (StreamValueOf foo akey))
; Apply a formula to that stream, to get a different stream.
(define fstream (FormulaStream (Plus (Number 10) (FloatValueOf foo akey))))
; Place it on an atom, take a look at it, and make sure that it works.
(cog-set-value! bar bkey fstream)
(cog-value bar bkey)
(cog-execute! (StreamValueOf bar bkey))
(cog-execute! (StreamValueOf bar bkey))
(cog-execute! (StreamValueOf bar bkey))
; ------- THE END -------