File size: 6,139 Bytes
54b75b1
 
 
 
 
 
 
 
 
45cc459
 
54b75b1
 
 
45cc459
54b75b1
45cc459
54b75b1
 
45cc459
 
54b75b1
 
45cc459
 
 
54b75b1
45cc459
54b75b1
45cc459
54b75b1
45cc459
 
54b75b1
45cc459
 
 
 
 
 
54b75b1
45cc459
 
 
 
54b75b1
45cc459
be04d92
 
 
 
45cc459
54b75b1
be04d92
 
45cc459
54b75b1
45cc459
 
 
54b75b1
45cc459
 
 
54b75b1
45cc459
54b75b1
45cc459
 
 
 
 
 
 
54b75b1
45cc459
54b75b1
45cc459
54b75b1
45cc459
 
54b75b1
 
45cc459
54b75b1
45cc459
 
 
 
54b75b1
 
45cc459
 
 
 
54b75b1
45cc459
 
54b75b1
45cc459
 
 
 
54b75b1
be04d92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45cc459
54b75b1
be04d92
 
 
 
 
 
45cc459
 
 
 
54b75b1
45cc459
54b75b1
45cc459
 
 
54b75b1
45cc459
54b75b1
45cc459
 
 
 
 
 
 
54b75b1
 
 
45cc459
 
 
 
 
 
 
54b75b1
 
 
 
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
---
license: apache-2.0
tags:
- active-inference
- causal-inference
- bayesian
- free-energy-principle
- non-gradient
- cognitive-architecture
- predictive-coding
- fhrr
- hopfield-network
---

# Tensegrity: Non-Gradient Cognitive Architecture

Tensegrity is centered on a unified energy landscape:

```
FHRR encoding -> hierarchical predictive coding -> Hopfield memory
              -> optional causal energy terms -> Broca/LLM graft
```

The language model is treated as a linguistic interface. The cognitive layer
owns belief revision, causal competition, memory, and action selection; the LLM
only verbalizes under optional logit guidance.

## Current API

Use the V2 unified field by default:

```python
from tensegrity import UnifiedField

field = UnifiedField(
    obs_dim=128,
    hidden_dims=[64, 16],
    fhrr_dim=1024,
    ngc_settle_steps=15,
)

cycle = field.observe(
    {"object": "ball", "color": "red", "location": "table"},
    input_type="bindings",
)

print(cycle["energy"].total)
expected_obs = field.predict()          # np.ndarray, shape (obs_dim,) — settled NGC readout
# This is the sensory prediction from the current internal state (not a class label).
print("expected observation vector (first 8 dims):", expected_obs[:8])
# Common follow-ups: flatten to a label by argmax over logits elsewhere, or pipe into a probe / monitor.
```

**`UnifiedField.predict()`** returns a **`numpy.ndarray`** of shape **`(obs_dim,)`**: the **predicted next observation** vector from the settled hierarchical circuit after the last `observe` (NGC’s `predict_observation()`). Assign it (as above), inspect slice or norm, or send it to downstream binding / decoding—there is no bundled string label.

The old Morton/POMDP frontend is still available for migration and baselines:

```python
from tensegrity.legacy.v1 import TensegrityAgent, MortonEncoder, MarkovBlanket
```

Compatibility shims remain under `tensegrity.core.agent`,
`tensegrity.core.morton`, and `tensegrity.core.blanket`, but those modules emit
deprecation warnings and are not part of the primary export surface.

## Core Pieces

| Package                                 | Role                                                           |
|-----------------------------------------|----------------------------------------------------------------|
| `tensegrity.core` / `tensegrity.engine` | V2 unified field, FHRR, NGC, Hopfield memory, causal energy    |
| `tensegrity.graft`                      | Broca-style LLM graft with keyword or semantic token grounding |
| `tensegrity.causal`                     | Pearl SCMs, do-calculus, counterfactuals                       |
| `tensegrity.memory`                     | Epistemic, episodic, and associative memory baselines          |
| `tensegrity.legacy.v1`                  | Morton-coded Markov blanket and flat POMDP agent               |

## Unified Energy

The unified field decomposes total energy into local prediction-error terms:

```
E_total = E_perception + E_memory + E_causal
```

Where:

```text
E_perception = hierarchical predictive-coding residuals
E_memory     = Modern Hopfield retrieval energy
E_causal     = SCM prediction error over causal variables
```

All updates are local fixed-point or Hebbian-style operations. There is no
runtime backpropagation loop or optimizer state in the cognitive architecture.

## Causal Topology Mapping

`tensegrity.engine.causal_energy.TopologyMapper` makes the Pearl/Friston bridge
explicit. It projects an arbitrary acyclic SCM graph into NGC-compatible layers:

- direct layer-to-layer causal edges become top-down predictions;
- bypass edges receive relay nodes for skipped hierarchy levels;
- same-layer or inverted edges receive virtual parent nodes one layer above the
  endpoints, turning lateral causal structure into shared vertical dependency.

Minimal example (four variables so one graph can show **direct**, **bypass**, and **same-layer lateral** edges). The mapper API is **`TopologyMapper.project_graph(...)`** (or **`TopologyMapper.from_scm(scm, ...)`** with the same `variable_layers`):

```python
import networkx as nx
from tensegrity.causal.scm import StructuralCausalModel
from tensegrity.engine.causal_energy import TopologyMapper

scm = StructuralCausalModel("topology_demo")
scm.add_variable("A", n_values=4, parents=[])
scm.add_variable("D", n_values=4, parents=["A"])   # bypass path A → D
scm.add_variable("B", n_values=4, parents=["A"])   # direct step A → B
scm.add_variable("C", n_values=4, parents=["B"])   # lateral topology: B,C share a layer below

variable_layers = {"A": 3, "D": 0, "B": 2, "C": 2}
# A→B / A→D: direct + bypass | B→C at same abstract layer → virtual parent in the embedding

mapping = TopologyMapper(expand_layers=True).from_scm(
    scm,
    n_layers=8,
    variable_layers=variable_layers,
)
print(dict(mapping.embedded_layers))   # layer index per node after relays / vparents
print(mapping.ngc_layer_sizes())       # e.g. widths per layer → output "shape" at a glance
```

## Semantic Grafting

```python
from tensegrity.graft.vocabulary import VocabularyGrounding
# Keyword baseline: VocabularyGrounding.from_keywords(...)
# Semantic: VocabularyGrounding.from_semantic_projection(...)
```

`VocabularyGrounding.from_keywords(...)` remains as a deterministic baseline.
For less brittle grounding, `VocabularyGrounding.from_semantic_projection(...)`
uses frozen phrase/token embeddings and cosine proximity to build weighted
token sets without runtime gradient training.

## What Is Not Here

- No SGD or Adam-style optimizer state in the cognitive loop
- No backpropagation-through-time training loop
- No prompt-only delegation of reasoning to the LLM

## What Is Here

- FHRR compositional observation encoding
- Hierarchical predictive coding
- Modern Hopfield memory
- Structural causal models and counterfactuals
- Explicit SCM-to-NGC topology mapping
- Keyword and semantic LLM logit grounding
- Legacy V1 baselines for comparison

## Dependencies

- `numpy`
- `scipy`
- `networkx`
- `pydantic`
- `torch`
- `transformers`
- `sentence-transformers`

## License

Apache 2.0