OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-matrix commits / a713904

Rename design notes file
a713904e7e40c79e5a3898b3424a083bd1e0fa79
by Linas Vepštas <linasvepstas@gmail.com> · 2025-01-25T00:17:03.000Z

Changed files (2) +224 -221

opencog/Design-object-atomese.md +224 -0
……@@ -0,0 +1,224 @@
1Design Notes - Objective Atomese
2================================
3Design thoughts about an object-oriented infrastructure, in Atomese.
4nothing here yet, except for a sketch of ideas.
5
6The below sketchs ideas (circa 2024) for an object-oriented variant of
7Atomese.
8
9Motivation
10----------
11The primary goal is to replicate some fraction of the code in the
12[matrix](../matrix) directory, but to do so in pure
13[Atomese](https://wiki.opencog.org/w/Atomese), instead of scheme. The
14matrix code has proven to be exceptionally useful and powerful, but there
15is now a need to be able to run it in (parallel) pipelines (configured
16with [ProxyNode](https://wiki.opencog.org/w/ProxyNode)s.) This includes
17running it over the network (via
18[CogStorageNode](https://wiki.opencog.org/w/CogStorageNode)) or otherwise
19interacting with [StorageNode](https://wiki.opencog.org/w/StorageNode)s
20in interesting, non-trivial ways. For that, the matrix code must become
21specifiable in Atomese. (Yes, we could just wrap it in a
22[GroundedProcedureNode](https://wiki.opencog.org/w/GroundedProcedureNode)
23but that would be ugly and counter-productive.)
24
25Object Basics
26-------------
27The actual code in matrix is written in scheme, and uses a peculiar OO
28programming style variously called
29[Generic Programming](https://en.wikipedia.org/wiki/Generic_programming),
30[Parametric Polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism)
31or [Traits](https://en.wikipedia.org/wiki/Trait_(computer_programming)).
32In short, it is an OO style similar to that of JavaScript, rather than of
33C++.
34
35
36How might this work in Atomese? Maybe like this:
37```
38(DefineLink
39 (DefinedMethodLink
40 (PredicateNode "some object classname")
41 (PredicateNode "some method"))
42 (LambdaLink
43 (VariableList ...)
44 ... atomese ...))
45```
46The `DefinedMethodLink` isn't really needed; one could just use a
47`ListLink` and this would work just fine, today. But it's convenient to
48have a special link type devoted to this task.
49
50Invocation of the object-instance+method paure is "just like always", with
51the [ExecutionOutputLink](https://wiki.opencog.org/w/ExecutionOutputLink):
52```
53(cog-execute!
54 (ExecutionOutputLink
55 (DefinedMethodLink
56 (PredicateNode "some object classname")
57 (PredicateNode "some method"))
58 (ListLink
59 (Predicate "some object instance")
60 ... method args ...)))
61```
62
63The above more or less almost works today, and only minor tweaks are needed
64to get this fully working. That's because there is no particularly great
65secret to OO programming: just provide a way to pass the class instance as
66the first, "this" argument. That's all.
67
68
69Pipelines
70---------
71The need for the above is driven by the need to be able to specify
72processing pipelines, using the
73[DynamicDataProxyNode](https://wiki.opencog.org/w/DynamicDataProxyNode)
74This [ProxyNode](https://wiki.opencog.org/w/ProxyNode) causes Atomese
75snippets to run, whenever a specific key is used to get the Value on
76any Atom handled by the Proxy. The prototypical example is to compute
77the mutual information (MI) on some matrix element.
78
79Matrix elements often (but not always) have the form
80```
81(EvaluationLink
82 (Predicate "name of some matrix")
83 (List
84 (Atom "left or row index")
85 (Atom "right or column index")))
86```
87Some kinds of matrix have a much more complex form; however, in general,
88they all are triplets of the form `(root, left, right)`. In order to be
89able to do generic matrix computations, there must be some way of getting
90the left and right elements given the triplet, and sometimes to construct
91the triplet, given the left and right elements. But how?
92
93In the scheme matrix code, each object has methods, such as
94`get-left-element` and `get-right-element` and so on, that will obtain the
95needed item for the given matrix instance. To do the same thing in Atomese,
96we need to have a way of specifying method names, and using them.
97
98Thus, ***every*** Atomese matrix object ***must*** define the following
99methods:
100* `(Predicate "*-left-element-*")` -- return the left element
101* `(Predicate "*-right-element-*")` -- return the right element
102* And many more; See the [object-api.scm](../matrix/object-api.scm] file
103 for the starter set.
104
105Example
106-------
107Lets asume the simplest case, where the matrix is in the form of the
108`EvaluationLink` shown above. One would then have:
109
110```
111(DefineLink
112 (DefinedMethodLink
113 (Predicate "*-Basic Pairs Matrix-*")
114 (Predicate "*-left-element-*"))
115 (Lambda
116 (Variable "$matrix-entry") ; This will be the EvaluationLink;
117 (ElementOf
118 (ElementOf (Variable "$matrix-entry") (Number 1)) ; the ListLink
119 (Number 0)) ; first item in the ListLink.
120 ))
121```
122
123To run this:
124```
125(cog-execute!
126 (ExecutionOutputLink
127 (DefinedMethodLink
128 (Predicate "*-Basic Pairs Matrix-*")
129 (Predicate "*-left-element-*"))
130 (EvaluationLink
131 (Predicate "word pairs matrix")
132 (List
133 (Word "blue")
134 (Word "sky")))))
135```
136This would return `(Word "blue")` upon execution.
137
138
139This is perhaps a terrible example. We could (maybe should) use
140FilterLink to do this work.
141
142```
143(DefineLink
144 (DefinedMethodLink
145 (Predicate "*-Basic Pairs Matrix-*")
146 (Predicate "*-left-element-*"))
147 (Lambda
148 (Variable "$matrix-entry") ; This will be the EvaluationLink;
149 ; The FilterLink will extract the left elt.
150 (FilterLink
151 (RuleLink
152 ;; Variables in the pattern
153 (VariableList
154 (Variable "$pred") (Variable "$left") (Variable "$right"))
155 ;; The matrix pattern to match.
156 (Evaluation
157 (Variable "$pred")
158 (List (Variable "$left") (Variable "$right")))
159 ;; The rewrite -- what to return, after pattern matching.
160 (Variable "$left"))
161 (Variable "$matrix-entry"))))
162```
163
164Also, this form is possible:
165```
166(DefineLink
167 (DefinedMethodLink
168 (Predicate "*-Basic Pairs Matrix-*")
169 (Predicate "*-left-element-*"))
170 (Lambda
171 (Variable "$matrix-entry") ; This will be the EvaluationLink;
172 ; The UnifierLink will extract the left elt.
173 (UnifierLink
174 (Lambda
175 ;; Variables in the pattern
176 (VariableList
177 (Variable "$pred") (Variable "$left") (Variable "$right"))
178 ;; The matrix pattern to match.
179 (Evaluation
180 (Variable "$pred")
181 (List (Variable "$left") (Variable "$right"))))
182
183 ;; What to unify against
184 (Variable "$matrix-entry")
185
186 ;; The unifer re-write -- What to return, after pattern matching.
187 (Variable "$left"))))
188```
189
190We can get rid of the unused, un-needed variables:
191
192```
193(DefineLink
194 (DefinedMethodLink
195 (Predicate "*-Basic Pairs Matrix-*")
196 (Predicate "*-left-element-*"))
197 (Lambda
198 (Variable "$matrix-entry") ; This will be the EvaluationLink;
199 ; The FilterLink will extract the left elt.
200 (Filter
201 (Rule
202 ;; Variable that we will bind.
203 (Variable "$left")
204 ;; The matrix pattern to match.
205 (Evaluation
206 (Sign 'PredicateNode)
207 (List (Variable "$left") (Sign 'WordNode)))
208 ;; The rewrite -- what to return, after pattern matching.
209 (Variable "$left"))
210 (Variable "$matrix-entry"))))
211```
212
213All four of these forms should "just work".
214
215NB SignNode is a synonym for (SignatureLink (TypeNode 'foo))
216
217
218TODO
219----
220* Handle SignLink See issue #2602
221* Handle Signatures in the pattern matcher, plus examples & tests.
222* Change BoolValue so it can create maskes from bit-specs!?
223* Change NumberOfLink so it can convert bool masks to element numbers ??
224* Most FunctionLinks need to be able to handle streams i.e. QueueValues.
opencog/object-atomese/README.md +0 -221
……@@ -1,221 +0,0 @@
1Objective Atomese
2=================
3An object-oriented infrastructure, in Atomese. Version 0.0.0; there is
4nothing here yet, except for a sketch of ideas.
5
6Motivation
7----------
8The primary goal is to replicate some fraction of the code in the
9[matrix](../matrix) directory, but to do so in pure
10[Atomese](https://wiki.opencog.org/w/Atomese), instead of scheme. The
11matrix code has proven to be exceptionally useful and powerful, but there
12is now a need to be able to run it in (parallel) pipelines (configured
13with [ProxyNode](https://wiki.opencog.org/w/ProxyNode)s.) This includes
14running it over the network (via
15[CogStorageNode](https://wiki.opencog.org/w/CogStorageNode)) or otherwise
16interacting with [StorageNode](https://wiki.opencog.org/w/StorageNode)s
17in interesting, non-trivial ways. For that, the matrix code must become
18specifiable in Atomese. (Yes, we could just wrap it in a
19[GroundedProcedureNode](https://wiki.opencog.org/w/GroundedProcedureNode)
20but that would be ugly and counter-productive.)
21
22Object Basics
23-------------
24The actual code in matrix is written in scheme, and uses a peculiar OO
25programming style variously called
26[Generic Programming](https://en.wikipedia.org/wiki/Generic_programming),
27[Parametric Polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism)
28or [Traits](https://en.wikipedia.org/wiki/Trait_(computer_programming)).
29In short, it is an OO style similar to that of JavaScript, rather than of
30C++.
31
32
33How might this work in Atomese? Maybe like this:
34```
35(DefineLink
36 (DefinedMethodLink
37 (PredicateNode "some object classname")
38 (PredicateNode "some method"))
39 (LambdaLink
40 (VariableList ...)
41 ... atomese ...))
42```
43The `DefinedMethodLink` isn't really needed; one could just use a
44`ListLink` and this would work just fine, today. But it's convenient to
45have a special link type devoted to this task.
46
47Invocation of the object-instance+method paure is "just like always", with
48the [ExecutionOutputLink](https://wiki.opencog.org/w/ExecutionOutputLink):
49```
50(cog-execute!
51 (ExecutionOutputLink
52 (DefinedMethodLink
53 (PredicateNode "some object classname")
54 (PredicateNode "some method"))
55 (ListLink
56 (Predicate "some object instance")
57 ... method args ...)))
58```
59
60The above more or less almost works today, and only minor tweaks are needed
61to get this fully working. That's because there is no particularly great
62secret to OO programming: just provide a way to pass the class instance as
63the first, "this" argument. That's all.
64
65
66Pipelines
67---------
68The need for the above is driven by the need to be able to specify
69processing pipelines, using the
70[DynamicDataProxyNode](https://wiki.opencog.org/w/DynamicDataProxyNode)
71This [ProxyNode](https://wiki.opencog.org/w/ProxyNode) causes Atomese
72snippets to run, whenever a specific key is used to get the Value on
73any Atom handled by the Proxy. The prototypical example is to compute
74the mutual information (MI) on some matrix element.
75
76Matrix elements often (but not always) have the form
77```
78(EvaluationLink
79 (Predicate "name of some matrix")
80 (List
81 (Atom "left or row index")
82 (Atom "right or column index")))
83```
84Some kinds of matrix have a much more complex form; however, in general,
85they all are triplets of the form `(root, left, right)`. In order to be
86able to do generic matrix computations, there must be some way of getting
87the left and right elements given the triplet, and sometimes to construct
88the triplet, given the left and right elements. But how?
89
90In the scheme matrix code, each object has methods, such as
91`get-left-elemet` and `get-right-element` and so on, that will obtain the
92needed item for the given matrix instance. To do the same thing in Atomese,
93we need to have a way of specifying method names, and using them.
94
95Thus, ***every*** Atomese matrix object ***must*** define the following
96methods:
97* `(Predicate "*-left-element-*")` -- return the left element
98* `(Predicate "*-right-element-*")` -- return the right element
99* And many more; See the [object-api.scm](../matrix/object-api.scm] file
100 for the starter set.
101
102Example
103-------
104Lets asume the simplest case, where the matrix is in the form of the
105`EvaluationLink` shown above. One would then have:
106
107```
108(DefineLink
109 (DefinedMethodLink
110 (Predicate "*-Basic Pairs Matrix-*")
111 (Predicate "*-left-element-*"))
112 (Lambda
113 (Variable "$matrix-entry") ; This will be the EvaluationLink;
114 (ElementOf
115 (ElementOf (Variable "$matrix-entry") (Number 1)) ; the ListLink
116 (Number 0)) ; first item in the ListLink.
117 ))
118```
119
120To run this:
121```
122(cog-execute!
123 (ExecutionOutputLink
124 (DefinedMethodLink
125 (Predicate "*-Basic Pairs Matrix-*")
126 (Predicate "*-left-element-*"))
127 (EvaluationLink
128 (Predicate "word pairs matrix")
129 (List
130 (Word "blue")
131 (Word "sky")))))
132```
133This would return `(Word "blue")` upon execution.
134
135
136This is perhaps a terrible example. We could (maybe should) use
137FilterLink to do this work.
138
139```
140(DefineLink
141 (DefinedMethodLink
142 (Predicate "*-Basic Pairs Matrix-*")
143 (Predicate "*-left-element-*"))
144 (Lambda
145 (Variable "$matrix-entry") ; This will be the EvaluationLink;
146 ; The FilterLink will extract the left elt.
147 (FilterLink
148 (RuleLink
149 ;; Variables in the pattern
150 (VariableList
151 (Variable "$pred") (Variable "$left") (Variable "$right"))
152 ;; The matrix pattern to match.
153 (Evaluation
154 (Variable "$pred")
155 (List (Variable "$left") (Variable "$right")))
156 ;; The rewrite -- what to return, after pattern matching.
157 (Variable "$left"))
158 (Variable "$matrix-entry"))))
159```
160
161Also, this form is possible:
162```
163(DefineLink
164 (DefinedMethodLink
165 (Predicate "*-Basic Pairs Matrix-*")
166 (Predicate "*-left-element-*"))
167 (Lambda
168 (Variable "$matrix-entry") ; This will be the EvaluationLink;
169 ; The UnifierLink will extract the left elt.
170 (UnifierLink
171 (Lambda
172 ;; Variables in the pattern
173 (VariableList
174 (Variable "$pred") (Variable "$left") (Variable "$right"))
175 ;; The matrix pattern to match.
176 (Evaluation
177 (Variable "$pred")
178 (List (Variable "$left") (Variable "$right"))))
179
180 ;; What to unify against
181 (Variable "$matrix-entry")
182
183 ;; The unifer re-write -- What to return, after pattern matching.
184 (Variable "$left"))))
185```
186
187We can get rid of the unused, un-needed variables:
188
189```
190(DefineLink
191 (DefinedMethodLink
192 (Predicate "*-Basic Pairs Matrix-*")
193 (Predicate "*-left-element-*"))
194 (Lambda
195 (Variable "$matrix-entry") ; This will be the EvaluationLink;
196 ; The FilterLink will extract the left elt.
197 (Filter
198 (Rule
199 ;; Variable that we will bind.
200 (Variable "$left")
201 ;; The matrix pattern to match.
202 (Evaluation
203 (Sign 'PredicateNode)
204 (List (Variable "$left") (Sign 'WordNode)))
205 ;; The rewrite -- what to return, after pattern matching.
206 (Variable "$left"))
207 (Variable "$matrix-entry"))))
208```
209
210All four of these forms should "just work".
211
212NB SignNode is a synonym for (SignatureLink (TypeNode 'foo))
213
214
215TODO
216----
217* Handle SignLink See issue #2602
218* Handle Signatures in the pattern matcher, plus examples & tests.
219* Change BoolValue so it can create maskes from bit-specs!?
220* Change NumberOfLink so it can convert bool masks to element numbers ??
221* Most FunctionLinks need to be able to handle streams i.e. QueueValues.