threshold-computers: a family of machines built from ternary threshold gates, with the paper on universal construction and exact self-reproduction
3579fb4 | """Order-independent settling: a stored acyclic netlist evaluates correctly | |
| after d passes for every order of its records.""" | |
| import os, random, sys, itertools | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| import torch | |
| from reflect import (Cfg, build_net, Leveled, encode_netlist, compile_to_reflect, | |
| adder_net, eval_family_net, state_to_vec, vec_to_state, Runner) | |
| def main() -> int: | |
| cfg = Cfg() | |
| net, inputs, outputs = build_net(cfg) | |
| R = Runner(cfg, Leveled(net, inputs, outputs, device="cpu")) | |
| W = 1 | |
| anet, an, bn, sums, cout = adder_net(W) | |
| ia = {an[0]: cfg.WORK_BASE, bn[0]: cfg.WORK_BASE + 1} | |
| rg, addr, _ = compile_to_reflect(cfg, anet, ia, sums + [cout], cfg.WORK_BASE + 2) | |
| n = len(rg) | |
| print(f"stored netlist: {n} records (a full adder cell), G = {cfg.G}") | |
| orders = list(itertools.permutations(range(n))) if n <= 7 else None | |
| if orders is None: | |
| rng = random.Random(7) | |
| orders = [tuple(rng.sample(range(n), n)) for _ in range(500)] | |
| print(f" sampling {len(orders)} random record orders") | |
| else: | |
| print(f" all {len(orders)} record orders") | |
| bad = 0 | |
| for perm in orders: | |
| nl = encode_netlist(cfg, [rg[p] for p in perm]) | |
| for x in (0, 1): | |
| for y in (0, 1): | |
| sig = [0] * cfg.S | |
| sig[cfg.NET0:cfg.NET0 + len(nl)] = nl | |
| sig[ia[an[0]]] = x | |
| sig[ia[bn[0]]] = y | |
| st = R.run({"sig": sig, "gp": 0, "halt": 0}, cfg.G * cfg.G) | |
| got = st["sig"][addr[sums[0]]] | (st["sig"][addr[cout]] << 1) | |
| fam = eval_family_net(anet, {an[0]: x, bn[0]: y}) | |
| want = fam[sums[0]] | (fam[cout] << 1) | |
| if got != want or got != x + y: | |
| bad += 1 | |
| print(f" correct for every order and every input: " | |
| f"{'yes' if bad == 0 else f'NO ({bad} failures)'}") | |
| return 0 if bad == 0 else 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |