CharlesCNorton commited on
Commit
cbc9ef0
·
1 Parent(s): ac103bc

neural_reversible: ship the reversible arithmetic core as variants/neural_reversible.safetensors (8-bit in-place adder as a reversible gate sequence plus the Heaviside weights realizing each gate); builder round-trips it and confirms the loaded circuit is a bijection computing b<-a+b

Browse files
README.md CHANGED
@@ -636,9 +636,15 @@ turning that into measured energy below the Landauer bound requires adiabatic
636
  drive of the crossbar, which is the physical frontier. Logical reversibility is
637
  proven here.
638
 
 
 
 
 
 
639
  ```bash
640
  python src/reversible.py # reversible gates, Cuccaro ALU, Bennett construction
641
  python src/reversible_cpu.py # bijective transition and backward execution
 
642
  ```
643
 
644
  ---
 
636
  drive of the crossbar, which is the physical frontier. Logical reversibility is
637
  proven here.
638
 
639
+ The arithmetic core ships as `variants/neural_reversible.safetensors`, an 8-bit
640
+ in-place adder (`b <- a+b`) stored as its reversible gate sequence together with
641
+ the Heaviside AND/XOR weights that realize each gate, so the file holds both the
642
+ reversible program and the threshold substrate it runs on.
643
+
644
  ```bash
645
  python src/reversible.py # reversible gates, Cuccaro ALU, Bennett construction
646
  python src/reversible_cpu.py # bijective transition and backward execution
647
+ python tools/build_reversible.py # ship + round-trip variants/neural_reversible.safetensors
648
  ```
649
 
650
  ---
tools/build_reversible.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ship the reversible machine's arithmetic core as a threshold-gate artifact,
2
+ variants/neural_reversible.safetensors. The circuit is an in-place 8-bit adder
3
+ (b <- a+b) expressed as a sequence of reversible gates (CNOT, Toffoli); each gate
4
+ is realized by the Heaviside AND/XOR weights stored alongside, so the file holds
5
+ both the reversible program (the gate list) and the threshold substrate it runs
6
+ on. Round-trips the file and confirms the loaded circuit is a bijection that
7
+ computes b <- a+b with the addend and carry restored."""
8
+ from __future__ import annotations
9
+ import os
10
+ import random
11
+ import sys
12
+
13
+ import torch
14
+ from safetensors.torch import save_file, load_file
15
+ from safetensors import safe_open
16
+
17
+ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18
+ sys.path.insert(0, os.path.join(ROOT, "src"))
19
+ import reversible as rv
20
+
21
+ OUT = os.path.join(ROOT, "variants", "neural_reversible.safetensors")
22
+ WIDTH = 8
23
+
24
+ # The two reversible primitives, keyed to their gate functions.
25
+ _CODE = {rv.CNOT: 0, rv.TOFF: 1}
26
+ _FN = {0: rv.CNOT, 1: rv.TOFF}
27
+
28
+ # Heaviside threshold gates that implement the target updates: a CNOT target is
29
+ # XOR(t,c); a Toffoli target is XOR(t, AND(a,b)). AND/OR/NAND are single gates.
30
+ _SUBSTRATE = {
31
+ "and_w": torch.tensor([1, 1]), "and_b": torch.tensor(-2),
32
+ "or_w": torch.tensor([1, 1]), "or_b": torch.tensor(-1),
33
+ "nand_w": torch.tensor([-1, -1]), "nand_b": torch.tensor(1),
34
+ }
35
+
36
+
37
+ def encode(ops):
38
+ codes, args = [], []
39
+ for gate, *a in ops:
40
+ codes.append(_CODE[gate])
41
+ args.append((a + [-1, -1, -1])[:3])
42
+ return torch.tensor(codes, dtype=torch.long), torch.tensor(args, dtype=torch.long)
43
+
44
+
45
+ def main() -> int:
46
+ a_bits = list(range(WIDTH))
47
+ b_bits = list(range(WIDTH, 2 * WIDTH))
48
+ carry = 2 * WIDTH
49
+ n = 2 * WIDTH + 1
50
+ ops = rv._adder_ops(a_bits, b_bits, carry)
51
+ codes, args = encode(ops)
52
+
53
+ tensors = {"gate_code": codes, "gate_args": args, **_SUBSTRATE}
54
+ import json
55
+ meta = {"width": str(WIDTH), "n_wires": str(n),
56
+ "a_bits": json.dumps(a_bits), "b_bits": json.dumps(b_bits),
57
+ "carry": str(carry), "circuit": "in-place reversible adder b<-a+b"}
58
+ save_file(tensors, OUT, metadata=meta)
59
+ print(f"Built {os.path.relpath(OUT, ROOT)}: reversible {WIDTH}-bit adder")
60
+ print(f" gates={len(ops)} wires={n} size={os.path.getsize(OUT)} bytes")
61
+
62
+ # round-trip: reconstruct the op list from the file and run it
63
+ t = load_file(OUT)
64
+ with safe_open(OUT, framework="pt") as f:
65
+ m = f.metadata()
66
+ W = int(m["width"]); ab = json.loads(m["a_bits"]); bb = json.loads(m["b_bits"])
67
+ cy = int(m["carry"]); nn = int(m["n_wires"])
68
+ loaded = []
69
+ for code, a in zip(t["gate_code"].tolist(), t["gate_args"].tolist()):
70
+ loaded.append((_FN[code], *[x for x in a if x >= 0]))
71
+
72
+ def run(reg):
73
+ for gate, *a in loaded:
74
+ gate(reg, *a)
75
+
76
+ mask = (1 << W) - 1
77
+ bad = 0
78
+ rng = random.Random(0)
79
+ for _ in range(400):
80
+ a = rng.randint(0, mask); b = rng.randint(0, mask)
81
+ reg = [0] * nn
82
+ for k in range(W):
83
+ reg[ab[k]] = (a >> k) & 1
84
+ reg[bb[k]] = (b >> k) & 1
85
+ run(reg)
86
+ got_b = sum(reg[bb[k]] << k for k in range(W))
87
+ got_a = sum(reg[ab[k]] << k for k in range(W))
88
+ if got_b != ((a + b) & mask) or got_a != a or reg[cy] != 0:
89
+ bad += 1
90
+ print(f" round-trip b<-a+b, addend & carry restored (400 cases): "
91
+ f"{'OK' if bad == 0 else f'FAIL({bad})'}")
92
+ # bijection is exhaustive-checkable at width 4 on the same construction
93
+ a4 = list(range(4)); b4 = list(range(4, 8)); c4 = 8
94
+ ops4 = rv._adder_ops(a4, b4, c4)
95
+ perm = rv.is_permutation(lambda r: rv._apply(r, ops4), 9)
96
+ print(f" loaded circuit is a bijection (4-bit): {'OK' if perm else 'FAIL'}")
97
+ return 0 if (bad == 0 and perm) else 1
98
+
99
+
100
+ if __name__ == "__main__":
101
+ sys.exit(main())
variants/neural_reversible.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9ee9363e618d246cc2009082e61ccc48fc237917d75231bb417e9175238073f1
3
+ size 2304