CharlesCNorton commited on
Commit ·
f3fd723
1
Parent(s): 9e7c322
neural_ca: construct and verify a logic gate in the automaton rather than citing one. A billiard-ball collision between input particles at (2,2) and (7,7) leaves the deflected cell (3,6) occupied at step 4 iff both inputs are present; and_gate() checks the AND truth table over all four inputs. README and docstrings restated as plain technical description of the rule, the verified dynamics, and the constructed gate.
Browse files- README.md +26 -29
- src/ca.py +40 -20
- tools/build_ca.py +4 -5
README.md
CHANGED
|
@@ -66,10 +66,10 @@ to evaluate, backward to invert (a multiplier run backward returns factors), or
|
|
| 66 |
as a SAT solver. And `neural_reversible` makes the entire state transition a
|
| 67 |
bijection, so no step erases information and the machine runs backward to
|
| 68 |
reconstruct its input, a processor with no Landauer erasure floor. And
|
| 69 |
-
`neural_ca`
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
|
| 74 |
---
|
| 75 |
|
|
@@ -669,37 +669,34 @@ python tools/reversible_matrix.py # ternary matrix stack: permutation transitio
|
|
| 669 |
|
| 670 |
---
|
| 671 |
|
| 672 |
-
## neural_ca — a reversible
|
| 673 |
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
configuration of particles, and running it is letting the medium evolve.
|
| 679 |
|
| 680 |
The block rule rotates each block 180 degrees, except that two particles on a
|
| 681 |
diagonal swap to the other diagonal. It is a permutation of the sixteen block
|
| 682 |
-
states and its own inverse, so the
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
|
| 694 |
-
|
| 695 |
-
|
| 696 |
-
|
| 697 |
-
|
| 698 |
-
construction. It is the family's maximal dissolution of architecture: the same
|
| 699 |
-
rule everywhere, no center, computation as discrete reversible physics.
|
| 700 |
|
| 701 |
```bash
|
| 702 |
-
python src/ca.py # rule bijection, lattice reversibility, ballistic motion,
|
| 703 |
python tools/build_ca.py # ship the block rule as a ternary matrix tile (permutation + 0.5 margin)
|
| 704 |
```
|
| 705 |
|
|
|
|
| 66 |
as a SAT solver. And `neural_reversible` makes the entire state transition a
|
| 67 |
bijection, so no step erases information and the machine runs backward to
|
| 68 |
reconstruct its input, a processor with no Landauer erasure floor. And
|
| 69 |
+
`neural_ca` has no processor at all: one fixed reversible rule applied to every
|
| 70 |
+
2x2 block of a lattice (a Margolus cellular automaton), where a particle
|
| 71 |
+
collision computes an AND gate and ballistic transport plus collisions are the
|
| 72 |
+
billiard-ball universality primitives.
|
| 73 |
|
| 74 |
---
|
| 75 |
|
|
|
|
| 669 |
|
| 670 |
---
|
| 671 |
|
| 672 |
+
## neural_ca — a reversible cellular automaton
|
| 673 |
|
| 674 |
+
A partitioned (Margolus) cellular automaton: one fixed rule applied to every 2x2
|
| 675 |
+
block of a lattice, with the block partition alternating each step. The state is
|
| 676 |
+
the lattice; there is no program counter, register file, or control circuit, and
|
| 677 |
+
one step updates every block.
|
|
|
|
| 678 |
|
| 679 |
The block rule rotates each block 180 degrees, except that two particles on a
|
| 680 |
diagonal swap to the other diagonal. It is a permutation of the sixteen block
|
| 681 |
+
states and its own inverse, so the lattice update is a bijection: replaying the
|
| 682 |
+
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 |
|
src/ca.py
CHANGED
|
@@ -1,22 +1,20 @@
|
|
| 1 |
-
"""Reversible
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
the diagonal-pair set and its complement, so the rule is its own inverse and the
|
| 19 |
-
lattice update run with the partition sequence reversed undoes the computation.
|
| 20 |
"""
|
| 21 |
from __future__ import annotations
|
| 22 |
from typing import List, Tuple
|
|
@@ -162,6 +160,27 @@ def _test_ballistic():
|
|
| 162 |
return ok and steady
|
| 163 |
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
def _test_collision():
|
| 166 |
# Two particles interact (the joint evolution differs from independent
|
| 167 |
# motion) and the collision stays reversible: the physics that logic needs.
|
|
@@ -202,4 +221,5 @@ if __name__ == "__main__":
|
|
| 202 |
b = _test_reversibility()
|
| 203 |
c = _test_ballistic()
|
| 204 |
d = _test_collision()
|
| 205 |
-
|
|
|
|
|
|
| 1 |
+
"""Reversible Margolus (partitioned) cellular automaton.
|
| 2 |
+
|
| 3 |
+
One fixed rule is applied to every 2x2 block, alternating the block partition
|
| 4 |
+
between even and odd alignment each step (the Margolus neighborhood). The state
|
| 5 |
+
is the lattice; there is no program counter, register file, or control circuit.
|
| 6 |
+
|
| 7 |
+
Rule (cells ordered TL,TR,BL,BR): rotate the block 180 degrees, except a pair of
|
| 8 |
+
particles on a diagonal (1001, 0110) swaps to the other diagonal. Both cases are
|
| 9 |
+
involutions and neither maps a state across the diagonal-pair boundary, so the
|
| 10 |
+
rule is a self-inverse permutation of the sixteen block states; the lattice
|
| 11 |
+
update is therefore a bijection and replaying the partition sequence in reverse
|
| 12 |
+
inverts the evolution.
|
| 13 |
+
|
| 14 |
+
Dynamics are the billiard-ball model's: isolated particles move ballistically on
|
| 15 |
+
diagonals and collisions deflect them reversibly. and_gate() computes AND from a
|
| 16 |
+
collision; ballistic transport plus this collision are the primitives of the
|
| 17 |
+
Fredkin-Toffoli universality construction (Margolus 1984).
|
|
|
|
|
|
|
| 18 |
"""
|
| 19 |
from __future__ import annotations
|
| 20 |
from typing import List, Tuple
|
|
|
|
| 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 |
+
|
| 184 |
def _test_collision():
|
| 185 |
# Two particles interact (the joint evolution differs from independent
|
| 186 |
# motion) and the collision stays reversible: the physics that logic needs.
|
|
|
|
| 221 |
b = _test_reversibility()
|
| 222 |
c = _test_ballistic()
|
| 223 |
d = _test_collision()
|
| 224 |
+
e = _test_gate()
|
| 225 |
+
print("PASS" if (a and g and b and c and d and e) else "FAIL")
|
tools/build_ca.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
| 1 |
-
"""Ship the reversible CA's
|
| 2 |
variants/neural_ca.safetensors. The 2x2 block rule compiles to a stack of
|
| 3 |
-
ternary matrices with a Heaviside step;
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
No processor is stored, only the rule of the medium."""
|
| 7 |
from __future__ import annotations
|
| 8 |
import os
|
| 9 |
import sys
|
|
|
|
| 1 |
+
"""Ship the reversible CA's block rule as a ternary matrix tile,
|
| 2 |
variants/neural_ca.safetensors. The 2x2 block rule compiles to a stack of
|
| 3 |
+
ternary matrices with a Heaviside step; the rule is a bijection, so the tile is
|
| 4 |
+
a permutation matrix product with a 0.5 analog margin, and the same tile applied
|
| 5 |
+
to every block of a lattice is one lattice step."""
|
|
|
|
| 6 |
from __future__ import annotations
|
| 7 |
import os
|
| 8 |
import sys
|