threshold-computers: a family of machines built from ternary threshold gates, with the paper on universal construction and exact self-reproduction
4a3e194 Download src/check_environment.py from phanerozoic/threshold-computers: direct link, hf CLI and curl.
- Browser
- Download file 4.58 kB
-
https://huggingface.co/phanerozoic/threshold-computers/resolve/main/src/check_environment.py
- Command line
-
hf download hf://phanerozoic/threshold-computers/src/check_environment.py
-
curl -L -o check_environment.py https://huggingface.co/phanerozoic/threshold-computers/resolve/main/src/check_environment.py
4.58 kB
| """The cost of instantiation against the cost of the network. | |
| One generation of the host is: inst splits the emitted bytes, sigma^-1 parses | |
| the first field into the netlist, Lev places the rows and entries of the | |
| layered map, and the device is applied once per step. This script counts those | |
| operations, one per byte read by inst and by sigma^-1, one per row and one per | |
| nonzero entry placed by Lev, and one per device application, times each of | |
| them, and compares the total with the T * M unit evaluations of the run. | |
| """ | |
| import json | |
| import os | |
| import sys | |
| import time | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| def runs_path(name: str) -> str: | |
| d = os.path.join(REPO, "paper", "runs") | |
| os.makedirs(d, exist_ok=True) | |
| return os.path.join(d, name) | |
| def main() -> int: | |
| from selfrep import (M_STAR, inst, ser, tau_star, run_reference, read_host, | |
| host_netlist, sigma_host) | |
| from netlist_io import net_of_sigma | |
| from matrix8 import compile_net | |
| sigma_bytes = read_host() | |
| tau = tau_star(sigma_bytes, M_STAR) | |
| s = ser(sigma_bytes, bytes(M_STAR), tau) | |
| # sigma: parameters and predecessor entries stored, and the time to write | |
| t0 = time.perf_counter() | |
| net, inputs, outputs = host_netlist() | |
| t_build = time.perf_counter() - t0 | |
| t0 = time.perf_counter() | |
| encoded = sigma_host() | |
| t_sigma = time.perf_counter() - t0 | |
| assert encoded == sigma_bytes | |
| stored, _, _, _ = net_of_sigma(sigma_bytes) | |
| entries = (2 * len(stored.gates) # bias and fan-in | |
| + sum(len(i) for i, _ in stored.gates.values()) | |
| + len(outputs)) | |
| print(f" sigma: {entries:,} stored entries -> {len(encoded):,} bytes " | |
| f"in {t_sigma * 1e3:.0f} ms ({t_build * 1e3:.0f} ms to assemble " | |
| f"the netlist from source)") | |
| # inst: one pass over the serialized instance, then sigma^-1 on its first field | |
| t0 = time.perf_counter() | |
| reps = 50 | |
| for _ in range(reps): | |
| a, b, c = inst(s) | |
| t_inst = (time.perf_counter() - t0) / reps | |
| assert (a, b, c) == (sigma_bytes, bytes(M_STAR), tau) | |
| t0 = time.perf_counter() | |
| for _ in range(5): | |
| N, I, O, _ = net_of_sigma(a) | |
| t_sigma_inv = (time.perf_counter() - t0) / 5 | |
| assert len(N.gates) == len(stored.gates) | |
| print(f" inst: {len(s):,} bytes parsed in {t_inst * 1e3:.2f} ms, and " | |
| f"{len(N.gates):,} units rebuilt from the first field in " | |
| f"{t_sigma_inv * 1e3:.0f} ms") | |
| # Lev: the units placed, and the time to place them | |
| t0 = time.perf_counter() | |
| layers, info = compile_net(N, I, O) | |
| t_lev = time.perf_counter() - t0 | |
| M = sum(int(W.shape[0]) for W, _ in layers) | |
| nnz = sum(int((W != 0).sum()) for W, _ in layers) | |
| print(f" Lev: {len(N.gates):,} units in, {M:,} rows and {nnz:,} nonzero " | |
| f"entries placed over {info['layers']} layers in {t_lev:.1f} s") | |
| # the device: one application per step, at most one byte moved | |
| t0 = time.perf_counter() | |
| emitted, T = run_reference(M_STAR, tau) | |
| t_run = time.perf_counter() - t0 | |
| assert emitted == s | |
| print(f" device: {T:,} applications, {len(emitted):,} bytes emitted " | |
| f"({t_run:.2f} s for the whole reference run)") | |
| env_ops = len(s) + len(sigma_bytes) + M + nnz + T | |
| closed = 2 * len(sigma_bytes) + len(bytes(M_STAR)) + len(tau) + 16 + M + nnz + T | |
| assert env_ops == closed, (env_ops, closed) | |
| net_ops = T * M | |
| print(f" instantiation: {env_ops:,} elementary operations per generation, " | |
| f"which is the closed form 2|sigma|+|m|+|tau|+16+M+nnz+T") | |
| print(f" network: {net_ops:,} unit evaluations (T = {T:,}, M = {M:,})") | |
| print(f" ratio: {env_ops / net_ops:.3e}") | |
| out = {"sigma_entries": entries, "sigma_bytes": len(encoded), | |
| "sigma_seconds": t_sigma, "build_seconds": t_build, | |
| "inst_bytes": len(s), "inst_seconds": t_inst, | |
| "sigma_inverse_seconds": t_sigma_inv, | |
| "lev_units_in": len(N.gates), "lev_units_out": M, "lev_nonzero": nnz, | |
| "lev_layers": info["layers"], "lev_seconds": t_lev, | |
| "lev_entries": info["total_weights"], | |
| "steps": T, "emitted_bytes": len(emitted), | |
| "reference_seconds": t_run, | |
| "environment_ops": env_ops, "network_ops": net_ops, | |
| "ratio": env_ops / net_ops} | |
| json.dump(out, open(runs_path("paper_environment.json"), "w"), indent=1) | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |