CharlesCNorton commited on
Commit
657864a
·
1 Parent(s): f3fd723

neural_ca: the collision is verified as a reversible interaction gate, not just AND. At step 4 three output cells carry A&B (deflected, (3,6)/(6,3)), A&~B ((6,6)), and ~A&B ((3,3)), checked over all four inputs. Analog robustness sweep on the matrix tile: exact under read noise through sigma 0.10 and conductance mismatch through sigma_G 0.10, matching neural_matrix8. README updated.

Browse files
Files changed (3) hide show
  1. README.md +9 -8
  2. src/ca.py +20 -9
  3. tools/build_ca.py +19 -0
README.md CHANGED
@@ -683,20 +683,21 @@ partition sequence in reverse reconstructs any earlier configuration (verified
683
  over random lattices), and particle number is conserved. The rule is expressed
684
  in the family's Heaviside threshold gates (a diagonal-pair detector XORed onto
685
  the rotated cells) and compiles to a 6-layer ternary matrix tile that is a
686
- permutation with a 0.5 analog margin; that tile applied to every block is one
687
- lattice step, stored as `variants/neural_ca.safetensors`.
 
688
 
689
  The dynamics are the billiard-ball model's: a single particle moves ballistically
690
  along a diagonal at one cell per step, and two particles collide and deflect
691
  reversibly (verified as a genuine interaction, distinct from independent motion).
692
- A collision computes logic directly: with input particles at (2,2) and (7,7), the
693
- deflected cell (3,6) is occupied at step 4 iff both inputs are present, an AND
694
- gate checked over all four input combinations. Ballistic transport and this
695
- collision are the primitives of the Fredkin-Toffoli universality construction
696
- (Margolus 1984).
697
 
698
  ```bash
699
- python src/ca.py # rule bijection, lattice reversibility, ballistic motion, collision, AND gate
700
  python tools/build_ca.py # ship the block rule as a ternary matrix tile (permutation + 0.5 margin)
701
  ```
702
 
 
683
  over random lattices), and particle number is conserved. The rule is expressed
684
  in the family's Heaviside threshold gates (a diagonal-pair detector XORed onto
685
  the rotated cells) and compiles to a 6-layer ternary matrix tile that is a
686
+ permutation with a 0.5 analog margin, bit-exact under read noise through
687
+ sigma ~ 0.10 and conductance mismatch through sigma_G ~ 0.10; that tile applied
688
+ to every block is one lattice step, stored as `variants/neural_ca.safetensors`.
689
 
690
  The dynamics are the billiard-ball model's: a single particle moves ballistically
691
  along a diagonal at one cell per step, and two particles collide and deflect
692
  reversibly (verified as a genuine interaction, distinct from independent motion).
693
+ A collision computes logic directly: with input particles at (2,2) and (7,7),
694
+ three output cells at step 4 carry A AND B (the deflected paths (3,6) and (6,3)),
695
+ A AND NOT B ((6,6)), and NOT A AND B ((3,3)), the billiard-ball interaction
696
+ gate, verified over all four inputs. That gate with mirror routing is
697
+ functionally complete (Margolus 1984).
698
 
699
  ```bash
700
+ python src/ca.py # rule bijection, lattice reversibility, ballistic motion, interaction gate
701
  python tools/build_ca.py # ship the block rule as a ternary matrix tile (permutation + 0.5 margin)
702
  ```
703
 
src/ca.py CHANGED
@@ -160,24 +160,35 @@ def _test_ballistic():
160
  return ok and steady
161
 
162
 
163
- def and_gate(a: int, b: int, N: int = 4) -> int:
164
- """AND from a billiard-ball collision. Input particle A enters at (2,2)
165
- moving SE, B at (7,7) moving NW; they meet only when both are present, so
166
- the deflected output cell (3,6) is occupied at step 4 iff a and b."""
 
 
167
  H = W = 12
168
  g = [[0] * W for _ in range(H)]
169
  if a:
170
  g[2][2] = 1
171
  if b:
172
  g[7][7] = 1
173
- return run(g, N)[3][6]
 
 
 
 
 
174
 
175
 
176
  def _test_gate():
177
- table = {(a, b): and_gate(a, b) for a in (0, 1) for b in (0, 1)}
178
- ok = all(table[(a, b)] == (a & b) for a in (0, 1) for b in (0, 1))
179
- print(f" billiard-ball AND at deflected cell (3,6), all 4 inputs: "
180
- f"{'OK' if ok else 'FAIL'} {table}")
 
 
 
 
181
  return ok
182
 
183
 
 
160
  return ok and steady
161
 
162
 
163
+ def interaction_gate(a: int, b: int) -> dict:
164
+ """One billiard-ball collision as a reversible interaction gate. Input
165
+ particle A enters at (2,2) moving SE and B at (7,7) moving NW; at step 4
166
+ three output cells carry A&B (the deflected paths), A&~B and ~A&B (the
167
+ straight-through paths). AND plus routing by mirrors is functionally
168
+ complete for the billiard-ball construction (Margolus 1984)."""
169
  H = W = 12
170
  g = [[0] * W for _ in range(H)]
171
  if a:
172
  g[2][2] = 1
173
  if b:
174
  g[7][7] = 1
175
+ g = run(g, 4)
176
+ return {"A_and_B": g[3][6], "A_and_notB": g[6][6], "notA_and_B": g[3][3]}
177
+
178
+
179
+ def and_gate(a: int, b: int) -> int:
180
+ return interaction_gate(a, b)["A_and_B"]
181
 
182
 
183
  def _test_gate():
184
+ ok = True
185
+ for a in (0, 1):
186
+ for b in (0, 1):
187
+ o = interaction_gate(a, b)
188
+ ok &= (o["A_and_B"] == (a & b) and o["A_and_notB"] == (a & (1 - b))
189
+ and o["notA_and_B"] == ((1 - a) & b))
190
+ print(f" billiard-ball interaction gate (A&B, A&~B, ~A&B) over all 4 inputs: "
191
+ f"{'OK' if ok else 'FAIL'}")
192
  return ok
193
 
194
 
tools/build_ca.py CHANGED
@@ -81,6 +81,25 @@ def main() -> int:
81
  print(f" tile is a permutation (16 distinct outputs): {'OK' if perm else 'FAIL'}")
82
  print(f" analog noise margin: {margin:.3f} (guarantee 0.5)")
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  # the loaded tile, applied to every block, is one whole-lattice CA step
85
  t = load_file(OUT)
86
  n = 0
 
81
  print(f" tile is a permutation (16 distinct outputs): {'OK' if perm else 'FAIL'}")
82
  print(f" analog noise margin: {margin:.3f} (guarantee 0.5)")
83
 
84
+ # analog robustness: the tile must reproduce the rule under read noise and
85
+ # static conductance mismatch, as neural_matrix8 measures
86
+ states = torch.stack(vecs)
87
+ ref = [ca.rule(tuple((s >> k) & 1 for k in (3, 2, 1, 0))) for s in range(16)]
88
+
89
+ def outs(machine, **kw):
90
+ v = machine.step(states, **kw)
91
+ return [tuple(int(v[i][j]) for j in range(4)) for i in range(v.shape[0])]
92
+
93
+ print(" read-noise sweep (exact = tile matches the rule on all 16 states):")
94
+ for sigma in (0.05, 0.10, 0.15, 0.20):
95
+ okn = all(outs(mm, analog=True, noise_sigma=sigma,
96
+ gen=torch.Generator().manual_seed(s)) == ref for s in range(4))
97
+ print(f" sigma={sigma:.2f}: {'exact' if okn else 'errors appear'}")
98
+ print(" conductance-mismatch sweep:")
99
+ for sg in (0.05, 0.10, 0.15):
100
+ okg = outs(mm.perturbed(sg, seed=0), analog=True) == ref
101
+ print(f" sigma_G={sg:.2f}: {'exact' if okg else 'errors appear'}")
102
+
103
  # the loaded tile, applied to every block, is one whole-lattice CA step
104
  t = load_file(OUT)
105
  n = 0