| """neural_subleq8io + the universal constructor. |
| |
| The host is the family's one-instruction machine extended with three |
| memory-mapped device cells (all device logic lives in the runtimes, exactly |
| like neural_rv32's console at 0xFF00; the processor's gates are unchanged): |
| |
| 0xFD IN_DATA reads as the current tape byte (device-refreshed) |
| 0xFC IN_STROBE any write advances the tape head (device clears to 0) |
| 0xFE OUT any write emits the written byte (device clears to 0) |
| |
| A 21-instruction SUBLEQ program — the constructor — interprets a construction |
| recipe streamed on the tape: |
| |
| tag 0 END |
| tag 1..127 literal record: the next `tag` tape bytes, each stored |
| negated mod 256, are emitted one per SUBLEQ instruction |
| (M[0xFE] = 0 - M[0xFD] recovers the byte) |
| tag 129..255 repeat record: the next tape byte (negated value) is |
| emitted 256-tag times without strobing (tag 128 unused) |
| |
| `describe(file_bytes)` compiles any safetensors file in the family into a |
| recipe; the constructor run on that recipe emits the file byte for byte, so |
| the constructor is universal and the description selects what is built. |
| Self-reproduction is the case where the description handed to the constructor |
| is that of the running machine: the program's output stream is the |
| byte-for-byte safetensors file of the host itself. |
| |
| The equality is machine-checked rather than observed on a single run: |
| - the recipe codec round-trips every family file (byte equality + sha256); |
| - the constructor program is executed on three proven-equal backends |
| (pure-integer reference, the gate-graph SubleqThresholdCPU walking the |
| shipped netlist, and the host compiled to recurrent ternary matrices with |
| matrix8's compiler) with cycle-lockstep spot checks between them; |
| - the full self-reproduction runs at threshold fidelity on the matrix |
| backend, and the emitted stream must equal the host's file exactly; |
| - the offspring file then boots as generation 2 and reproduces again. |
| |
| Usage: |
| python constructor8.py build # emit variants/neural_subleq8io.safetensors |
| python constructor8.py verify # host soundness + codec + constructor runs |
| python constructor8.py self # full self-reproduction at threshold fidelity |
| python constructor8.py all |
| """ |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import hashlib |
| import json |
| import os |
| import sys |
| import time |
| from typing import Dict, List, Optional, Tuple |
|
|
| import torch |
| from safetensors import safe_open |
| from safetensors.torch import save_file |
|
|
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) |
|
|
| REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| MODEL_PATH = os.path.join(REPO, "variants", "neural_subleq8io.safetensors") |
|
|
| from matrix8 import Net, compile_net |
|
|
| IN_DATA, IN_STROBE, OUT = 0xFD, 0xFC, 0xFE |
| HALT_PC = 0xFF |
|
|
|
|
| |
| |
| |
|
|
| def build_host(save: bool = True) -> str: |
| import build as B |
| from quantize import quantize_tensors |
|
|
| tensors: Dict[str, torch.Tensor] = {} |
| B.add_decoder(tensors, 8, 256) |
| B.add_memory_read_mux(tensors, 256) |
| B.add_memory_write_cells(tensors, 256) |
| B.add_subleq_core(tensors) |
| tensors["manifest.data_bits"] = torch.tensor([8.0]) |
| tensors["manifest.addr_bits"] = torch.tensor([8.0]) |
| tensors["manifest.memory_bytes"] = torch.tensor([256.0]) |
| tensors["manifest.pc_width"] = torch.tensor([8.0]) |
| tensors["manifest.version"] = torch.tensor([4.0]) |
| tensors, reg, stats = B.build_inputs(tensors) |
| tensors, counts, _, _ = quantize_tensors(tensors, ternary=False) |
| for k, t in tensors.items(): |
| if k.endswith(".weight") and not k.startswith("manifest."): |
| tf = t.float() if t.dtype.is_floating_point else t.to(torch.float32) |
| assert (tf.abs() <= 1).all(), f"non-ternary weight {k}" |
| meta = { |
| "machine": "subleq8io", |
| "weight_quantization": "ternary", |
| "signal_registry": reg.to_metadata(), |
| "io": json.dumps({"in_data": IN_DATA, "in_strobe": IN_STROBE, |
| "out": OUT, "halt_pc": HALT_PC}), |
| } |
| if save: |
| save_file(tensors, MODEL_PATH, metadata=meta) |
| sz = os.path.getsize(MODEL_PATH) |
| print(f" built {MODEL_PATH}: {stats['added']} wired gates, " |
| f"{len(tensors)} tensors, {sz:,} bytes") |
| return MODEL_PATH |
|
|
|
|
| |
| |
| |
|
|
| def describe(data: bytes) -> bytes: |
| """Compile raw bytes into a construction recipe for the constructor.""" |
| tape = bytearray() |
| i, n = 0, len(data) |
| while i < n: |
| j = i |
| while j < n and data[j] == data[i] and j - i < 127: |
| j += 1 |
| if j - i >= 4: |
| tape.append(256 - (j - i)) |
| tape.append((256 - data[i]) % 256) |
| i = j |
| continue |
| k = i |
| while k < n and k - i < 127: |
| m = k |
| while m < n and data[m] == data[k] and m - k < 4: |
| m += 1 |
| if m - k >= 4: |
| break |
| k += 1 |
| k = max(k, i + 1) |
| tape.append(k - i) |
| tape.extend((256 - x) % 256 for x in data[i:k]) |
| i = k |
| tape.append(0) |
| return bytes(tape) |
|
|
|
|
| def decode(tape: bytes) -> bytes: |
| """Pure-Python reference semantics of the recipe language.""" |
| out = bytearray() |
| i = 0 |
| while True: |
| t = tape[i] |
| i += 1 |
| if t == 0: |
| return bytes(out) |
| if t <= 127: |
| for _ in range(t): |
| out.append((256 - tape[i]) % 256) |
| i += 1 |
| else: |
| out.extend([(256 - tape[i]) % 256] * (256 - t)) |
| i += 1 |
|
|
|
|
| |
| |
| |
|
|
| Z, ONE, T1, T2 = 0xF0, 0xF1, 0xF2, 0xF3 |
|
|
| CONSTRUCTOR = [ |
| |
| (T2, T2, 0x03), |
| (T1, T1, 0x06), |
| (IN_DATA, T1, 0x09), |
| (Z, IN_STROBE, 0x0C), |
| (T1, T2, 0x0F), |
| (Z, T2, 0x15), |
| (Z, Z, 0x24), |
| (Z, T1, 0x1B), |
| (Z, Z, 0x30), |
| (Z, Z, HALT_PC), |
| (Z, Z, 0x21), |
| (Z, Z, 0x24), |
| (IN_DATA, OUT, 0x27), |
| (Z, IN_STROBE, 0x2A), |
| (ONE, T2, 0x00), |
| (Z, Z, 0x24), |
| (IN_DATA, OUT, 0x33), |
| (ONE, T1, 0x39), |
| (Z, Z, 0x30), |
| (Z, IN_STROBE, 0x3C), |
| (Z, Z, 0x00), |
| ] |
|
|
|
|
| def constructor_image() -> List[int]: |
| mem = [0] * 256 |
| for idx, (a, b, c) in enumerate(CONSTRUCTOR): |
| mem[idx * 3] = a |
| mem[idx * 3 + 1] = b |
| mem[idx * 3 + 2] = c |
| mem[ONE] = 1 |
| return mem |
|
|
|
|
| |
| |
| |
|
|
| def ref_construct(tape: bytes, max_steps: int = 1 << 34, |
| ) -> Tuple[bytes, int]: |
| mem = constructor_image() |
| mem[IN_DATA] = tape[0] if tape else 0 |
| out = bytearray() |
| head = 0 |
| pc = 0 |
| steps = 0 |
| tn = len(tape) |
| while pc != HALT_PC and steps < max_steps: |
| A = mem[pc] |
| Bc = mem[(pc + 1) & 0xFF] |
| C = mem[(pc + 2) & 0xFF] |
| r = (mem[Bc] - mem[A]) & 0xFF |
| mem[Bc] = r |
| pc = C if (r == 0 or r >= 0x80) else (pc + 3) & 0xFF |
| if Bc == OUT: |
| out.append(r) |
| mem[OUT] = 0 |
| elif Bc == IN_STROBE: |
| head += 1 |
| mem[IN_STROBE] = 0 |
| mem[IN_DATA] = tape[head] if head < tn else 0 |
| steps += 1 |
| return bytes(out), steps |
|
|
|
|
| |
| |
| |
|
|
| class GateHost: |
| def __init__(self, path: str = MODEL_PATH): |
| from machines import SubleqThresholdCPU, load_tensors |
| from eval import load_metadata |
| T = load_tensors(path) |
| reg = load_metadata(path)["signal_registry"] |
| self.cpu = SubleqThresholdCPU(T, reg) |
|
|
| def run(self, tape: bytes, max_steps: int) -> Tuple[bytes, int, dict]: |
| s = {"pc": 0, "mem": constructor_image(), "halted": False} |
| s["mem"][IN_DATA] = tape[0] if tape else 0 |
| out = bytearray() |
| head = 0 |
| n = 0 |
| while not s["halted"] and n < max_steps: |
| Bc = s["mem"][(s["pc"] + 1) & 0xFF] |
| s = self.cpu.step(s) |
| if Bc == OUT: |
| out.append(s["mem"][OUT]) |
| s["mem"][OUT] = 0 |
| elif Bc == IN_STROBE: |
| head += 1 |
| s["mem"][IN_STROBE] = 0 |
| s["mem"][IN_DATA] = tape[head] if head < len(tape) else 0 |
| n += 1 |
| return bytes(out), n, s |
|
|
|
|
| |
| |
| |
|
|
| def subleq_state_names() -> List[str]: |
| names = [f"pc{i}" for i in range(8)] + ["halt"] |
| for j in range(256): |
| names += [f"m{j}b{i}" for i in range(8)] |
| return names |
|
|
|
|
| def build_subleq_step_net() -> Tuple[Net, List[str], List[str]]: |
| net = Net() |
| pc = [f"pc{i}" for i in range(8)] |
| halt = "halt" |
| mem = [[f"m{j}b{i}" for i in range(8)] for j in range(256)] |
|
|
| P = [net.DECODE(f"pd{j}", pc, j) for j in range(256)] |
| byte = [] |
| for o in range(3): |
| bo = [net.OR(f"f{o}b{bit}", |
| [net.AND(f"f{o}a{j}b{bit}", [mem[j][bit], P[(j - o) % 256]]) |
| for j in range(256)]) for bit in range(8)] |
| byte.append(bo) |
| A, Bb, C = byte |
|
|
| AD = [net.DECODE(f"ad{j}", A, j) for j in range(256)] |
| BD = [net.DECODE(f"bd{j}", Bb, j) for j in range(256)] |
| x = [net.OR(f"x{bit}", [net.AND(f"x{bit}a{j}", [mem[j][bit], AD[j]]) |
| for j in range(256)]) for bit in range(8)] |
| y = [net.OR(f"y{bit}", [net.AND(f"y{bit}a{j}", [mem[j][bit], BD[j]]) |
| for j in range(256)]) for bit in range(8)] |
|
|
| nx = [net.NOT(f"nx{k}", x[7 - k]) for k in range(8)] |
| c = "#1" |
| r_l = [] |
| for k in range(8): |
| s_, c = net.FA(f"sub.fa{k}", y[7 - k], nx[k], c) |
| r_l.append(s_) |
| r = [r_l[7 - i] for i in range(8)] |
|
|
| zero = net.NOR("rzero", r) |
| leq = net.OR("leq", [r[0], zero]) |
|
|
| pc_l = [pc[7 - k] for k in range(8)] |
| c = "#0" |
| p3_l = [] |
| for k in range(8): |
| addend = "#1" if k in (0, 1) else "#0" |
| s_, c = net.FA(f"pc3.fa{k}", pc_l[k], addend, c) |
| p3_l.append(s_) |
| p3 = [p3_l[7 - i] for i in range(8)] |
|
|
| pcm = [net.MUX(f"pcm{i}", leq, C[i], p3[i]) for i in range(8)] |
| pcn = [net.MUX(f"pcn{i}", halt, pc[i], pcm[i]) for i in range(8)] |
| hdec = net.DECODE("hdec", pcn, HALT_PC) |
| halt_n = net.OR("haltn", [halt, hdec]) |
|
|
| nh = net.NOT("nh", halt) |
| mem_n = [] |
| for j in range(256): |
| ws = net.AND(f"ws{j}", [BD[j], nh]) |
| nws = net.NOT(f"nws{j}", ws) |
| row = [net.OR(f"mn{j}b{bit}", |
| [net.AND(f"mn{j}b{bit}o", [mem[j][bit], nws]), |
| net.AND(f"mn{j}b{bit}n", [r[bit], ws])]) |
| for bit in range(8)] |
| mem_n.append(row) |
|
|
| outputs = pcn + [halt_n] + [s for row in mem_n for s in row] |
| return net, subleq_state_names(), outputs |
|
|
|
|
| class MatrixHost: |
| """The subleq8io processor as a recurrent ternary linear-threshold |
| network, with the device cells poked between recurrences.""" |
|
|
| N = 8 + 1 + 2048 |
|
|
| def __init__(self, device: str = "cpu"): |
| t0 = time.perf_counter() |
| net, inputs, outputs = build_subleq_step_net() |
| layers, info = compile_net(net, inputs, outputs) |
| for W, Bt in layers: |
| vals = set(torch.unique(W).tolist()) |
| assert vals <= {-1, 0, 1} |
| self.W = [W.to(device=device, dtype=torch.float32) for W, _ in layers] |
| self.B = [Bt.to(device=device, dtype=torch.float32) for _, Bt in layers] |
| self.device = device |
| self.info = info |
| print(f" host compiled to {info['layers']} ternary matrices " |
| f"(max width {info['max_width']}, " |
| f"{info['total_weights']:,} weights) in " |
| f"{time.perf_counter() - t0:.1f}s on {device}") |
|
|
| def _vec(self, pc: int, mem: List[int], halt: bool = False) -> torch.Tensor: |
| v = torch.zeros(self.N) |
| for k in range(8): |
| v[k] = (pc >> (7 - k)) & 1 |
| v[8] = 1.0 if halt else 0.0 |
| for j in range(256): |
| for k in range(8): |
| v[9 + j * 8 + k] = (mem[j] >> (7 - k)) & 1 |
| return v |
|
|
| def step(self, v: torch.Tensor) -> torch.Tensor: |
| for W, b in zip(self.W, self.B): |
| v = ((v @ W.T + b) >= 0).float() |
| return v |
|
|
| @staticmethod |
| def _byte(vcpu: torch.Tensor, j: int) -> int: |
| x = 0 |
| for k in range(8): |
| x = (x << 1) | int(vcpu[9 + j * 8 + k]) |
| return x |
|
|
| def run(self, tape: bytes, max_steps: int, expect: Optional[bytes] = None, |
| report_every: int = 100000) -> Tuple[bytes, int]: |
| mem = constructor_image() |
| mem[IN_DATA] = tape[0] if tape else 0 |
| v = self._vec(0, mem).unsqueeze(0).to(self.device) |
| out = bytearray() |
| head = 0 |
| n = 0 |
| idx_pch = torch.arange(0, 9, device=self.device) |
| t0 = time.perf_counter() |
| while n < max_steps: |
| front = v[0, idx_pch].tolist() |
| if front[8] >= 0.5: |
| break |
| pcv = 0 |
| for k in range(8): |
| pcv = (pcv << 1) | int(front[k]) |
| bidx = (pcv + 1) & 0xFF |
| bbits = v[0, 9 + bidx * 8: 9 + bidx * 8 + 8].tolist() |
| Bc = 0 |
| for k in range(8): |
| Bc = (Bc << 1) | int(bbits[k]) |
| v = self.step(v) |
| n += 1 |
| if Bc == OUT: |
| ob = v[0, 9 + OUT * 8: 9 + OUT * 8 + 8].tolist() |
| val = 0 |
| for k in range(8): |
| val = (val << 1) | int(ob[k]) |
| out.append(val) |
| if expect is not None and out[-1] != expect[len(out) - 1]: |
| raise AssertionError( |
| f"stream diverged at byte {len(out) - 1}: " |
| f"got {out[-1]:#04x} want {expect[len(out) - 1]:#04x}") |
| v[0, 9 + OUT * 8: 9 + OUT * 8 + 8] = 0.0 |
| elif Bc == IN_STROBE: |
| head += 1 |
| v[0, 9 + IN_STROBE * 8: 9 + IN_STROBE * 8 + 8] = 0.0 |
| nxt = tape[head] if head < len(tape) else 0 |
| for k in range(8): |
| v[0, 9 + IN_DATA * 8 + k] = float((nxt >> (7 - k)) & 1) |
| if report_every and n % report_every == 0: |
| rate = n / (time.perf_counter() - t0) |
| print(f" ... {n:,} recurrences, {len(out):,} bytes emitted " |
| f"({rate:,.0f} instr/s)") |
| return bytes(out), n |
|
|
| def exhaustive_datapath(self) -> bool: |
| """All 65,536 (x, y) operand pairs through the matrices in one batch.""" |
| xs = torch.arange(65536) % 256 |
| ys = torch.arange(65536) // 256 |
| V = torch.zeros(65536, self.N) |
| mem = [0] * 256 |
| mem[0], mem[1], mem[2] = 0x90, 0x91, 0x30 |
| v0 = self._vec(0, mem) |
| V[:] = v0 |
| for k in range(8): |
| V[:, 9 + 0x90 * 8 + k] = ((xs >> (7 - k)) & 1).float() |
| V[:, 9 + 0x91 * 8 + k] = ((ys >> (7 - k)) & 1).float() |
| V = V.to(self.device) |
| for W, b in zip(self.W, self.B): |
| V = ((V @ W.T + b) >= 0).float() |
| V = V.cpu() |
| r = torch.zeros(65536, dtype=torch.long) |
| for k in range(8): |
| r = (r << 1) | V[:, 9 + 0x91 * 8 + k].long() |
| pcv = torch.zeros(65536, dtype=torch.long) |
| for k in range(8): |
| pcv = (pcv << 1) | V[:, k].long() |
| exp_r = (ys - xs) & 0xFF |
| exp_leq = (exp_r == 0) | (exp_r >= 0x80) |
| exp_pc = torch.where(exp_leq, torch.full_like(pcv, 0x30), |
| torch.full_like(pcv, 3)) |
| ok = bool((r == exp_r).all()) and bool((pcv == exp_pc).all()) |
| print(f" {'OK ' if ok else 'FAIL'} matrix datapath exhaustive: " |
| f"65,536/65,536 subtract results and branch decisions exact") |
| return ok |
|
|
|
|
| |
| |
| |
|
|
| def sha(b: bytes) -> str: |
| return hashlib.sha256(b).hexdigest()[:16] |
|
|
|
|
| def family_files() -> List[str]: |
| files = [os.path.join(REPO, "neural_computer.safetensors")] |
| vdir = os.path.join(REPO, "variants") |
| files += sorted(os.path.join(vdir, f) for f in os.listdir(vdir) |
| if f.endswith(".safetensors")) |
| return files |
|
|
|
|
| def verify(device: str) -> bool: |
| ok = True |
|
|
| print("\n[1/5] Host machine soundness (shipped netlist, exhaustive datapath)") |
| from eval import NetlistEvaluator, load_metadata |
| from machines import load_tensors |
| T = load_tensors(MODEL_PATH) |
| reg = load_metadata(MODEL_PATH)["signal_registry"] |
| ne = NetlistEvaluator(T, reg, "subleq") |
| a_v = torch.arange(65536) % 256 |
| b_v = torch.arange(65536) // 256 |
| ext = {} |
| for k in range(8): |
| ext[f"$a[{k}]"] = ((a_v >> k) & 1).float() |
| ext[f"$b[{k}]"] = ((b_v >> k) & 1).float() |
| ext[f"$pc[{k}]"] = torch.zeros(65536) |
| ext[f"$c[{k}]"] = torch.zeros(65536) |
| o = ne.run(ext) |
| rr = sum(o[f"subleq.sub.fa{k}.ha2.sum.layer2"][:, 0].long() << k for k in range(8)) |
| lq = o["subleq.leq"][:, 0].long() |
| exp_r = (b_v - a_v) & 0xFF |
| exp_l = ((exp_r == 0) | (exp_r >= 128)).long() |
| good = bool((rr == exp_r).all()) and bool((lq == exp_l).all()) |
| print(f" {'OK ' if good else 'FAIL'} gate netlist exhaustive: 65,536/65,536 exact") |
| ok &= good |
|
|
| print("\n[2/5] Recipe codec round-trip over the whole family") |
| total = 0 |
| for p in family_files(): |
| data = open(p, "rb").read() |
| tape = describe(data) |
| good = decode(tape) == data |
| ok &= good |
| total += len(data) |
| print(f" {'OK ' if good else 'FAIL'} {os.path.basename(p):<44} " |
| f"{len(data):>10,} B -> tape {len(tape):>10,} B sha {sha(data)}") |
| print(f" ({total / 1e6:.0f} MB described and decoded back, byte-identical)") |
|
|
| print("\n[3/5] Constructor program on the integer reference " |
| "(output stream == target file, byte for byte)") |
| targets = [MODEL_PATH, |
| os.path.join(REPO, "variants", "neural_subleq8.safetensors"), |
| os.path.join(REPO, "variants", "neural_matrix8.safetensors")] |
| for p in targets: |
| data = open(p, "rb").read() |
| tape = describe(data) |
| t0 = time.perf_counter() |
| out, steps = ref_construct(tape) |
| dt = time.perf_counter() - t0 |
| good = out == data |
| ok &= good |
| tag = "SELF-REPRODUCTION" if p == MODEL_PATH else "universal build" |
| print(f" {'OK ' if good else 'FAIL'} {os.path.basename(p):<40} " |
| f"{len(out):>10,} B in {steps:>12,} instructions ({dt:.1f}s) " |
| f"[{tag}] sha {sha(out)}") |
|
|
| print("\n[4/5] Matrix backend (machine-1 compile of the host)") |
| mh = MatrixHost(device=device) |
| ok &= mh.exhaustive_datapath() |
|
|
| print("\n[5/5] Backend lockstep on a shared prefix " |
| "(gate graph vs matrices vs reference, first 600 cycles)") |
| data = open(MODEL_PATH, "rb").read() |
| tape = describe(data) |
| gh = GateHost() |
| s = {"pc": 0, "mem": constructor_image(), "halted": False} |
| s["mem"][IN_DATA] = tape[0] |
| mem2 = constructor_image() |
| mem2[IN_DATA] = tape[0] |
| v = mh._vec(0, mem2).unsqueeze(0).to(device) |
| headg = headm = 0 |
| outg, outm = bytearray(), bytearray() |
| good = True |
| for n in range(600): |
| Bg = s["mem"][(s["pc"] + 1) & 0xFF] |
| s = gh.cpu.step(s) |
| if Bg == OUT: |
| outg.append(s["mem"][OUT]) |
| s["mem"][OUT] = 0 |
| elif Bg == IN_STROBE: |
| headg += 1 |
| s["mem"][IN_STROBE] = 0 |
| s["mem"][IN_DATA] = tape[headg] if headg < len(tape) else 0 |
| vc = v[0].cpu() |
| pcm = 0 |
| for k in range(8): |
| pcm = (pcm << 1) | int(vc[k]) |
| Bm = MatrixHost._byte(vc, (pcm + 1) & 0xFF) |
| v = mh.step(v) |
| if Bm == OUT: |
| outm.append(MatrixHost._byte(v[0].cpu(), OUT)) |
| v[0, 9 + OUT * 8: 9 + OUT * 8 + 8] = 0.0 |
| elif Bm == IN_STROBE: |
| headm += 1 |
| v[0, 9 + IN_STROBE * 8: 9 + IN_STROBE * 8 + 8] = 0.0 |
| nxt = tape[headm] if headm < len(tape) else 0 |
| for k in range(8): |
| v[0, 9 + IN_DATA * 8 + k] = float((nxt >> (7 - k)) & 1) |
| vc = v[0].cpu() |
| pcm = 0 |
| for k in range(8): |
| pcm = (pcm << 1) | int(vc[k]) |
| memm = [MatrixHost._byte(vc, j) for j in range(256)] |
| if pcm != s["pc"] or memm != s["mem"] or outg != outm: |
| print(f" FAIL lockstep diverged at cycle {n}") |
| good = False |
| break |
| print(f" {'OK ' if good else 'FAIL'} gate graph and matrix form agree " |
| f"cycle-for-cycle for 600 cycles ({len(outg)} bytes emitted identically)") |
| ok &= good |
|
|
| print("\nCONSTRUCTOR VERIFICATION:", "PASS" if ok else "FAIL") |
| return ok |
|
|
|
|
| def self_reproduce(device: str, gen2: bool = True) -> bool: |
| """Full self-reproduction at threshold fidelity on the matrix backend.""" |
| data = open(MODEL_PATH, "rb").read() |
| tape = describe(data) |
| print(f"\nSelf-reproduction on the threshold matrices: target " |
| f"{len(data):,} bytes (sha {sha(data)}), tape {len(tape):,} bytes") |
| ref_out, ref_steps = ref_construct(tape) |
| assert ref_out == data, "reference construction failed" |
| print(f" reference: {ref_steps:,} instructions") |
|
|
| mh = MatrixHost(device=device) |
| t0 = time.perf_counter() |
| out, n = mh.run(tape, max_steps=ref_steps + 64, expect=data) |
| dt = time.perf_counter() - t0 |
| ok = out == data and n == ref_steps |
| print(f" GEN 1: emitted {len(out):,} bytes in {n:,} recurrences " |
| f"({dt / 60:.1f} min, {n / dt:,.0f} instr/s) sha {sha(out)}") |
| print(f" {'OK ' if ok else 'FAIL'} output stream == host safetensors file, " |
| f"byte for byte; instruction count matches reference exactly") |
|
|
| if ok and gen2: |
| off_path = os.path.join(REPO, "variants", "_offspring_subleq8io.safetensors") |
| with open(off_path, "wb") as f: |
| f.write(out) |
| gh = GateHost(off_path) |
| probe_tape = describe(out[:2048]) |
| want = out[:2048] |
| got, steps, _ = gh.run(probe_tape, max_steps=len(probe_tape) * 8 + 64) |
| good2 = got == want |
| print(f" GEN 2: offspring file booted as a machine (gate graph); " |
| f"constructed the first {len(want):,} bytes of itself in " |
| f"{steps:,} instructions: {'exact' if good2 else 'MISMATCH'}") |
| os.remove(off_path) |
| ok &= good2 |
| print("SELF-REPRODUCTION:", "PASS" if ok else "FAIL") |
| return ok |
|
|
|
|
| def main() -> int: |
| ap = argparse.ArgumentParser() |
| ap.add_argument("cmd", choices=["build", "verify", "self", "all"]) |
| ap.add_argument("--device", default="cuda" if torch.cuda.is_available() else "cpu") |
| args = ap.parse_args() |
| rc = 0 |
| if args.cmd in ("build", "all"): |
| build_host(save=True) |
| if args.cmd in ("verify", "all"): |
| rc |= 0 if verify(args.device) else 1 |
| if args.cmd in ("self", "all"): |
| rc |= 0 if self_reproduce(args.device) else 1 |
| return rc |
|
|
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|