OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-matrix commits / 8f2c1fd

Move files around
8f2c1fdb1b8ad38cc1ceb62ec236c17a36de4c79
by Linas Vepštas <linasvepstas@gmail.com> · 2025-01-25T01:37:27.000Z

Changed files (6) +267 -251

README.md +11 -2
……@@ -5,9 +5,9 @@ Graph Sparse Vector/Matrix Library
55
66See: [Presentation slides of key ideas](opencog/matrix/docs/AtomSpace.pdf).
77
8Large complex graphs typically have many vertexes and edges that encode
8Large complex graphs typically have many vertices and edges that encode
99similar "objects", much like all of the rows of a database table are
10"similar". That collection of vertexes/edges can be thought of as
10"similar". That collection of vertices/edges can be thought of as
1111forming a vector. Such a vector is sparse, in that it is built out of
1212only some small fragment of the total graph. If the graph is big enough,
1313there might be thousands (or millions) of such vectors. One is then
……@@ -635,3 +635,12 @@ To-do list items.
635635 Currently, the `fetch` methods do this, and there is a scattering
636636 of other store methods provided in an ad hoc, as-needed basis. All
637637 this should be made prettier.
638
639Future Directions
640-----------------
641The API here does everything descirbed above. It works. It's stable.
642It's well-debugged and has been used for years in large compute efforts,
643burning through dozens (maybe hundreds?) of cpu-years of data mangling.
644It's mature. And, like any mature piece of software, we wish it did some
645things differently. Several files of alternative designs can be found in
646the design directory.
design/Design-object-atomese.md +231 -0
……@@ -0,0 +1,231 @@
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 sketches ideas (circa 2024) for an object-oriented variant of
7Atomese. It seems like it would not be hard to implement; it extends
8conventional Atomese in a minor way. Yet, it also feels insufficiently
9abstract. Over time, its become clear that the `ExecutionOutputLink` and
10`EvaluationLink` are problematic. They work, in the sense they were
11originally imagined to work, but they break up data flow in awkward
12ways. They provide the wrong kind of abstraction for an agentic
13architecture. Thus, see [Design-similarity](Design-similarity.md)
14instead.
15
16Motivation
17----------
18The primary goal is to replicate some fraction of the code in the
19[matrix](../matrix) directory, but to do so in pure
20[Atomese](https://wiki.opencog.org/w/Atomese), instead of scheme. The
21matrix code has proven to be exceptionally useful and powerful, but there
22is now a need to be able to run it in (parallel) pipelines (configured
23with [ProxyNode](https://wiki.opencog.org/w/ProxyNode)s.) This includes
24running it over the network (via
25[CogStorageNode](https://wiki.opencog.org/w/CogStorageNode)) or otherwise
26interacting with [StorageNode](https://wiki.opencog.org/w/StorageNode)s
27in interesting, non-trivial ways. For that, the matrix code must become
28specifiable in Atomese. (Yes, we could just wrap it in a
29[GroundedProcedureNode](https://wiki.opencog.org/w/GroundedProcedureNode)
30but that would be ugly and counter-productive.)
31
32Object Basics
33-------------
34The actual code in matrix is written in scheme, and uses a peculiar OO
35programming style variously called
36[Generic Programming](https://en.wikipedia.org/wiki/Generic_programming),
37[Parametric Polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism)
38or [Traits](https://en.wikipedia.org/wiki/Trait_(computer_programming)).
39In short, it is an OO style similar to that of JavaScript, rather than of
40C++.
41
42
43How might this work in Atomese? Maybe like this:
44```
45(DefineLink
46 (DefinedMethodLink
47 (PredicateNode "some object classname")
48 (PredicateNode "some method"))
49 (LambdaLink
50 (VariableList ...)
51 ... atomese ...))
52```
53The `DefinedMethodLink` isn't really needed; one could just use a
54`ListLink` and this would work just fine, today. But it's convenient to
55have a special link type devoted to this task.
56
57Invocation of the object-instance+method pair is "just like always", with
58the [ExecutionOutputLink](https://wiki.opencog.org/w/ExecutionOutputLink):
59```
60(cog-execute!
61 (ExecutionOutputLink
62 (DefinedMethodLink
63 (PredicateNode "some object classname")
64 (PredicateNode "some method"))
65 (ListLink
66 (Predicate "some object instance")
67 ... method args ...)))
68```
69
70The above more or less almost works today, and only minor tweaks are needed
71to get this fully working. That's because there is no particularly great
72secret to OO programming: just provide a way to pass the class instance as
73the first, "this" argument. That's all.
74
75
76Pipelines
77---------
78The need for the above is driven by the need to be able to specify
79processing pipelines, using the
80[DynamicDataProxyNode](https://wiki.opencog.org/w/DynamicDataProxyNode)
81This [ProxyNode](https://wiki.opencog.org/w/ProxyNode) causes Atomese
82snippets to run, whenever a specific key is used to get the Value on
83any Atom handled by the Proxy. The prototypical example is to compute
84the mutual information (MI) on some matrix element.
85
86Matrix elements often (but not always) have the form
87```
88(EvaluationLink
89 (Predicate "name of some matrix")
90 (List
91 (Atom "left or row index")
92 (Atom "right or column index")))
93```
94Some kinds of matrix have a much more complex form; however, in general,
95they all are triplets of the form `(root, left, right)`. In order to be
96able to do generic matrix computations, there must be some way of getting
97the left and right elements given the triplet, and sometimes to construct
98the triplet, given the left and right elements. But how?
99
100In the scheme matrix code, each object has methods, such as
101`get-left-element` and `get-right-element` and so on, that will obtain the
102needed item for the given matrix instance. To do the same thing in Atomese,
103we need to have a way of specifying method names, and using them.
104
105Thus, ***every*** Atomese matrix object ***must*** define the following
106methods:
107* `(Predicate "*-left-element-*")` -- return the left element
108* `(Predicate "*-right-element-*")` -- return the right element
109* And many more; See the [object-api.scm](../matrix/object-api.scm] file
110 for the starter set.
111
112Example
113-------
114Lets assume the simplest case, where the matrix is in the form of the
115`EvaluationLink` shown above. One would then have:
116
117```
118(DefineLink
119 (DefinedMethodLink
120 (Predicate "*-Basic Pairs Matrix-*")
121 (Predicate "*-left-element-*"))
122 (Lambda
123 (Variable "$matrix-entry") ; This will be the EvaluationLink;
124 (ElementOf
125 (ElementOf (Variable "$matrix-entry") (Number 1)) ; the ListLink
126 (Number 0)) ; first item in the ListLink.
127 ))
128```
129
130To run this:
131```
132(cog-execute!
133 (ExecutionOutputLink
134 (DefinedMethodLink
135 (Predicate "*-Basic Pairs Matrix-*")
136 (Predicate "*-left-element-*"))
137 (EvaluationLink
138 (Predicate "word pairs matrix")
139 (List
140 (Word "blue")
141 (Word "sky")))))
142```
143This would return `(Word "blue")` upon execution.
144
145
146This is perhaps a terrible example. We could (maybe should) use
147FilterLink to do this work.
148
149```
150(DefineLink
151 (DefinedMethodLink
152 (Predicate "*-Basic Pairs Matrix-*")
153 (Predicate "*-left-element-*"))
154 (Lambda
155 (Variable "$matrix-entry") ; This will be the EvaluationLink;
156 ; The FilterLink will extract the left elt.
157 (FilterLink
158 (RuleLink
159 ;; Variables in the pattern
160 (VariableList
161 (Variable "$pred") (Variable "$left") (Variable "$right"))
162 ;; The matrix pattern to match.
163 (Evaluation
164 (Variable "$pred")
165 (List (Variable "$left") (Variable "$right")))
166 ;; The rewrite -- what to return, after pattern matching.
167 (Variable "$left"))
168 (Variable "$matrix-entry"))))
169```
170
171Also, this form is possible:
172```
173(DefineLink
174 (DefinedMethodLink
175 (Predicate "*-Basic Pairs Matrix-*")
176 (Predicate "*-left-element-*"))
177 (Lambda
178 (Variable "$matrix-entry") ; This will be the EvaluationLink;
179 ; The UnifierLink will extract the left elt.
180 (UnifierLink
181 (Lambda
182 ;; Variables in the pattern
183 (VariableList
184 (Variable "$pred") (Variable "$left") (Variable "$right"))
185 ;; The matrix pattern to match.
186 (Evaluation
187 (Variable "$pred")
188 (List (Variable "$left") (Variable "$right"))))
189
190 ;; What to unify against
191 (Variable "$matrix-entry")
192
193 ;; The unifer re-write -- What to return, after pattern matching.
194 (Variable "$left"))))
195```
196
197We can get rid of the unused, un-needed variables:
198
199```
200(DefineLink
201 (DefinedMethodLink
202 (Predicate "*-Basic Pairs Matrix-*")
203 (Predicate "*-left-element-*"))
204 (Lambda
205 (Variable "$matrix-entry") ; This will be the EvaluationLink;
206 ; The FilterLink will extract the left elt.
207 (Filter
208 (Rule
209 ;; Variable that we will bind.
210 (Variable "$left")
211 ;; The matrix pattern to match.
212 (Evaluation
213 (Sign 'PredicateNode)
214 (List (Variable "$left") (Sign 'WordNode)))
215 ;; The rewrite -- what to return, after pattern matching.
216 (Variable "$left"))
217 (Variable "$matrix-entry"))))
218```
219
220All four of these forms should "just work".
221
222NB SignNode is a synonym for (SignatureLink (TypeNode 'foo))
223
224
225TODO
226----
227* Handle SignLink See issue #2602
228* Handle Signatures in the pattern matcher, plus examples & tests.
229* Change BoolValue so it can create maskes from bit-specs!?
230* Change NumberOfLink so it can convert bool masks to element numbers ??
231* Most FunctionLinks need to be able to handle streams i.e. QueueValues.
design/Design-similarity.md +18 -0
……@@ -0,0 +1,18 @@
1Sesign notes for similarity measures
2====================================
3Design notes and ideas for similarity measures. Attempts to get at the
4core problem that the matrix API was invented to solve. Tries to do this
5at a deeper, more abstract and simpler way.
6
7Motivation
8---------
9The current matrix API provides an extensive set of objects and
10functions for working with sparse vector embeddings. The vast selection
11is characteristic of what human programmers wnt and expect when
12attempting to write code to solve some problem. However, that same
13richness and variety impedes automatition and automatic construction.
14
15Almost all of the matrix API was developed to support one generic
16problem: obtaining the similarity between two things. Thus, the task at
17hand is find some simpler, easier, more basic way of thinking about and
18working with similarity.
design/README.md +7 -0
……@@ -0,0 +1,7 @@
1Design Notes
2------------
3This directory contains ideas for ***future design points***, and not
4the current design. The current design is sold, stable, mature and well
5debugged, but does not fit into a proper agent framework. The notes
6here attempt to find the appropriate design framework for an agent
7system.
opencog/Design-object-atomese.md +0 -231
……@@ -1,231 +0,0 @@
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. It seems like it would not be hard to implement; it extends
8conventional Atomese in a minor way. Yet, it also feels insufficiently
9abstract. Over time, its become clear that the `ExecutionOutputLink` and
10`EvaluationLink` are problematic. They work, in the sense they were
11originally imagined to work, but they break up data flow in awkward
12ways. They provide the wrong kind of abstraction for a dataflow
13architecture. Thus, see [Design-similarity](Design-similarity.md)
14instead.
15
16Motivation
17----------
18The primary goal is to replicate some fraction of the code in the
19[matrix](../matrix) directory, but to do so in pure
20[Atomese](https://wiki.opencog.org/w/Atomese), instead of scheme. The
21matrix code has proven to be exceptionally useful and powerful, but there
22is now a need to be able to run it in (parallel) pipelines (configured
23with [ProxyNode](https://wiki.opencog.org/w/ProxyNode)s.) This includes
24running it over the network (via
25[CogStorageNode](https://wiki.opencog.org/w/CogStorageNode)) or otherwise
26interacting with [StorageNode](https://wiki.opencog.org/w/StorageNode)s
27in interesting, non-trivial ways. For that, the matrix code must become
28specifiable in Atomese. (Yes, we could just wrap it in a
29[GroundedProcedureNode](https://wiki.opencog.org/w/GroundedProcedureNode)
30but that would be ugly and counter-productive.)
31
32Object Basics
33-------------
34The actual code in matrix is written in scheme, and uses a peculiar OO
35programming style variously called
36[Generic Programming](https://en.wikipedia.org/wiki/Generic_programming),
37[Parametric Polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism)
38or [Traits](https://en.wikipedia.org/wiki/Trait_(computer_programming)).
39In short, it is an OO style similar to that of JavaScript, rather than of
40C++.
41
42
43How might this work in Atomese? Maybe like this:
44```
45(DefineLink
46 (DefinedMethodLink
47 (PredicateNode "some object classname")
48 (PredicateNode "some method"))
49 (LambdaLink
50 (VariableList ...)
51 ... atomese ...))
52```
53The `DefinedMethodLink` isn't really needed; one could just use a
54`ListLink` and this would work just fine, today. But it's convenient to
55have a special link type devoted to this task.
56
57Invocation of the object-instance+method pair is "just like always", with
58the [ExecutionOutputLink](https://wiki.opencog.org/w/ExecutionOutputLink):
59```
60(cog-execute!
61 (ExecutionOutputLink
62 (DefinedMethodLink
63 (PredicateNode "some object classname")
64 (PredicateNode "some method"))
65 (ListLink
66 (Predicate "some object instance")
67 ... method args ...)))
68```
69
70The above more or less almost works today, and only minor tweaks are needed
71to get this fully working. That's because there is no particularly great
72secret to OO programming: just provide a way to pass the class instance as
73the first, "this" argument. That's all.
74
75
76Pipelines
77---------
78The need for the above is driven by the need to be able to specify
79processing pipelines, using the
80[DynamicDataProxyNode](https://wiki.opencog.org/w/DynamicDataProxyNode)
81This [ProxyNode](https://wiki.opencog.org/w/ProxyNode) causes Atomese
82snippets to run, whenever a specific key is used to get the Value on
83any Atom handled by the Proxy. The prototypical example is to compute
84the mutual information (MI) on some matrix element.
85
86Matrix elements often (but not always) have the form
87```
88(EvaluationLink
89 (Predicate "name of some matrix")
90 (List
91 (Atom "left or row index")
92 (Atom "right or column index")))
93```
94Some kinds of matrix have a much more complex form; however, in general,
95they all are triplets of the form `(root, left, right)`. In order to be
96able to do generic matrix computations, there must be some way of getting
97the left and right elements given the triplet, and sometimes to construct
98the triplet, given the left and right elements. But how?
99
100In the scheme matrix code, each object has methods, such as
101`get-left-element` and `get-right-element` and so on, that will obtain the
102needed item for the given matrix instance. To do the same thing in Atomese,
103we need to have a way of specifying method names, and using them.
104
105Thus, ***every*** Atomese matrix object ***must*** define the following
106methods:
107* `(Predicate "*-left-element-*")` -- return the left element
108* `(Predicate "*-right-element-*")` -- return the right element
109* And many more; See the [object-api.scm](../matrix/object-api.scm] file
110 for the starter set.
111
112Example
113-------
114Lets asume the simplest case, where the matrix is in the form of the
115`EvaluationLink` shown above. One would then have:
116
117```
118(DefineLink
119 (DefinedMethodLink
120 (Predicate "*-Basic Pairs Matrix-*")
121 (Predicate "*-left-element-*"))
122 (Lambda
123 (Variable "$matrix-entry") ; This will be the EvaluationLink;
124 (ElementOf
125 (ElementOf (Variable "$matrix-entry") (Number 1)) ; the ListLink
126 (Number 0)) ; first item in the ListLink.
127 ))
128```
129
130To run this:
131```
132(cog-execute!
133 (ExecutionOutputLink
134 (DefinedMethodLink
135 (Predicate "*-Basic Pairs Matrix-*")
136 (Predicate "*-left-element-*"))
137 (EvaluationLink
138 (Predicate "word pairs matrix")
139 (List
140 (Word "blue")
141 (Word "sky")))))
142```
143This would return `(Word "blue")` upon execution.
144
145
146This is perhaps a terrible example. We could (maybe should) use
147FilterLink to do this work.
148
149```
150(DefineLink
151 (DefinedMethodLink
152 (Predicate "*-Basic Pairs Matrix-*")
153 (Predicate "*-left-element-*"))
154 (Lambda
155 (Variable "$matrix-entry") ; This will be the EvaluationLink;
156 ; The FilterLink will extract the left elt.
157 (FilterLink
158 (RuleLink
159 ;; Variables in the pattern
160 (VariableList
161 (Variable "$pred") (Variable "$left") (Variable "$right"))
162 ;; The matrix pattern to match.
163 (Evaluation
164 (Variable "$pred")
165 (List (Variable "$left") (Variable "$right")))
166 ;; The rewrite -- what to return, after pattern matching.
167 (Variable "$left"))
168 (Variable "$matrix-entry"))))
169```
170
171Also, this form is possible:
172```
173(DefineLink
174 (DefinedMethodLink
175 (Predicate "*-Basic Pairs Matrix-*")
176 (Predicate "*-left-element-*"))
177 (Lambda
178 (Variable "$matrix-entry") ; This will be the EvaluationLink;
179 ; The UnifierLink will extract the left elt.
180 (UnifierLink
181 (Lambda
182 ;; Variables in the pattern
183 (VariableList
184 (Variable "$pred") (Variable "$left") (Variable "$right"))
185 ;; The matrix pattern to match.
186 (Evaluation
187 (Variable "$pred")
188 (List (Variable "$left") (Variable "$right"))))
189
190 ;; What to unify against
191 (Variable "$matrix-entry")
192
193 ;; The unifer re-write -- What to return, after pattern matching.
194 (Variable "$left"))))
195```
196
197We can get rid of the unused, un-needed variables:
198
199```
200(DefineLink
201 (DefinedMethodLink
202 (Predicate "*-Basic Pairs Matrix-*")
203 (Predicate "*-left-element-*"))
204 (Lambda
205 (Variable "$matrix-entry") ; This will be the EvaluationLink;
206 ; The FilterLink will extract the left elt.
207 (Filter
208 (Rule
209 ;; Variable that we will bind.
210 (Variable "$left")
211 ;; The matrix pattern to match.
212 (Evaluation
213 (Sign 'PredicateNode)
214 (List (Variable "$left") (Sign 'WordNode)))
215 ;; The rewrite -- what to return, after pattern matching.
216 (Variable "$left"))
217 (Variable "$matrix-entry"))))
218```
219
220All four of these forms should "just work".
221
222NB SignNode is a synonym for (SignatureLink (TypeNode 'foo))
223
224
225TODO
226----
227* Handle SignLink See issue #2602
228* Handle Signatures in the pattern matcher, plus examples & tests.
229* Change BoolValue so it can create maskes from bit-specs!?
230* Change NumberOfLink so it can convert bool masks to element numbers ??
231* Most FunctionLinks need to be able to handle streams i.e. QueueValues.
opencog/Design-similarity.md +0 -18
……@@ -1,18 +0,0 @@
1Sesign notes for similarity measures
2====================================
3Design notes and ideas for similarity measures. Attempts to get at the
4core problem that the matrix API was invented to solve. Tries to do this
5at a deeper, more abstract and simpler way.
6
7Motivation
8---------
9The current matrix API provides an extensive set of objects and
10functions for working with sparse vector embeddings. The vast selection
11is characteristic of what human programmers wnt and expect when
12attempting to write code to solve some problem. However, that same
13richness and variety impedes automatition and automatic construction.
14
15Almost all of the matrix API was developed to support one generic
16problem: obtaining the similarity between two things. Thus, the task at
17hand is find some simpler, easier, more basic way of thinking about and
18working with similarity.