Upload folder using huggingface_hub
Browse files- .gitattributes +35 -35
- README.md +3 -4
- iron_eval.py +206 -8
- neural_computer.safetensors +2 -2
.gitattributes
CHANGED
|
@@ -1,35 +1,35 @@
|
|
| 1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -17,9 +17,8 @@ tags:
|
|
| 17 |
Every logic gate is a threshold neuron: `output = 1 if (Σ wᵢxᵢ + b) ≥ 0 else 0`
|
| 18 |
|
| 19 |
```
|
| 20 |
-
Tensors:
|
| 21 |
-
Parameters:
|
| 22 |
-
Tests: 4,416/4,416 passing
|
| 23 |
```
|
| 24 |
|
| 25 |
---
|
|
@@ -85,7 +84,7 @@ The model includes `iron_eval.py` which exhaustively tests all circuits:
|
|
| 85 |
|
| 86 |
```bash
|
| 87 |
python iron_eval.py
|
| 88 |
-
# Output: Fitness: 1.000000 (
|
| 89 |
```
|
| 90 |
|
| 91 |
### Verification Status
|
|
|
|
| 17 |
Every logic gate is a threshold neuron: `output = 1 if (Σ wᵢxᵢ + b) ≥ 0 else 0`
|
| 18 |
|
| 19 |
```
|
| 20 |
+
Tensors: 3,122
|
| 21 |
+
Parameters: 5,648
|
|
|
|
| 22 |
```
|
| 23 |
|
| 24 |
---
|
|
|
|
| 84 |
|
| 85 |
```bash
|
| 86 |
python iron_eval.py
|
| 87 |
+
# Output: Fitness: 1.000000 (4478 tests)
|
| 88 |
```
|
| 89 |
|
| 90 |
### Verification Status
|
iron_eval.py
CHANGED
|
@@ -13,7 +13,7 @@ from typing import Dict, Tuple
|
|
| 13 |
from safetensors import safe_open
|
| 14 |
|
| 15 |
|
| 16 |
-
def load_model_10166(base_path: str = "D:/8bit-threshold-computer
|
| 17 |
"""Load model from safetensors."""
|
| 18 |
f = safe_open(f"{base_path}/neural_computer.safetensors", framework='numpy')
|
| 19 |
tensors = {}
|
|
@@ -315,6 +315,129 @@ class BatchedFitnessEvaluator:
|
|
| 315 |
|
| 316 |
return scores
|
| 317 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
# =========================================================================
|
| 319 |
# ARITHMETIC - COMPARATORS
|
| 320 |
# =========================================================================
|
|
@@ -786,18 +909,22 @@ class BatchedFitnessEvaluator:
|
|
| 786 |
# MAIN EVALUATE
|
| 787 |
# =========================================================================
|
| 788 |
|
| 789 |
-
def evaluate(self, population: Dict[str, torch.Tensor]) -> torch.Tensor:
|
| 790 |
"""Evaluate fitness for entire population."""
|
| 791 |
pop_size = next(iter(population.values())).shape[0]
|
| 792 |
scores = torch.zeros(pop_size, device=self.device)
|
| 793 |
total_tests = 0
|
|
|
|
| 794 |
|
| 795 |
# =================================================================
|
| 796 |
# BOOLEAN GATES (34 tests)
|
| 797 |
# =================================================================
|
|
|
|
|
|
|
| 798 |
for gate in ['and', 'or', 'nand', 'nor']:
|
| 799 |
scores += self._test_single_gate(population, gate, self.tt2, self.expected[gate])
|
| 800 |
total_tests += 4
|
|
|
|
| 801 |
|
| 802 |
# NOT
|
| 803 |
w = population['boolean.not.weight'].view(pop_size, -1)
|
|
@@ -805,111 +932,182 @@ class BatchedFitnessEvaluator:
|
|
| 805 |
out = heaviside(self.not_inputs @ w.T + b)
|
| 806 |
scores += (out == self.expected['not'].unsqueeze(1)).float().sum(0)
|
| 807 |
total_tests += 2
|
|
|
|
| 808 |
|
| 809 |
# IMPLIES
|
| 810 |
scores += self._test_single_gate(population, 'implies', self.tt2, self.expected['implies'])
|
| 811 |
total_tests += 4
|
|
|
|
| 812 |
|
| 813 |
# XOR, XNOR, BIIMPLIES
|
| 814 |
scores += self._test_twolayer_gate(population, 'boolean.xor', self.tt2, self.expected['xor'])
|
| 815 |
scores += self._test_twolayer_gate(population, 'boolean.xnor', self.tt2, self.expected['xnor'])
|
| 816 |
scores += self._test_twolayer_gate(population, 'boolean.biimplies', self.tt2, self.expected['biimplies'])
|
| 817 |
total_tests += 12
|
|
|
|
|
|
|
| 818 |
|
| 819 |
# =================================================================
|
| 820 |
-
# ARITHMETIC - ADDERS (
|
| 821 |
# =================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
| 822 |
scores += self._test_halfadder(population)
|
| 823 |
total_tests += 8
|
|
|
|
|
|
|
| 824 |
|
|
|
|
| 825 |
scores += self._test_fulladder(population)
|
| 826 |
total_tests += 16
|
|
|
|
|
|
|
| 827 |
|
| 828 |
# Ripple carry adders
|
|
|
|
| 829 |
rc2_tests = [(a, b) for a in range(4) for b in range(4)]
|
| 830 |
scores += self._test_ripplecarry(population, 2, rc2_tests)
|
| 831 |
total_tests += 16
|
|
|
|
|
|
|
| 832 |
|
|
|
|
| 833 |
rc4_tests = [(a, b) for a in range(16) for b in range(16)]
|
| 834 |
scores += self._test_ripplecarry(population, 4, rc4_tests)
|
| 835 |
total_tests += 256
|
|
|
|
|
|
|
| 836 |
|
|
|
|
| 837 |
rc8_tests = [(0,0), (1,1), (127,128), (255,1), (128,127), (255,255),
|
| 838 |
(0xAA, 0x55), (0x0F, 0xF0), (100, 155), (200, 55)]
|
| 839 |
scores += self._test_ripplecarry(population, 8, rc8_tests)
|
| 840 |
total_tests += len(rc8_tests)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 841 |
|
| 842 |
# =================================================================
|
| 843 |
-
# ARITHMETIC - COMPARATORS (
|
| 844 |
# =================================================================
|
|
|
|
|
|
|
| 845 |
scores += self._test_comparator(population, 'greaterthan8bit', 'gt')
|
| 846 |
scores += self._test_comparator(population, 'lessthan8bit', 'lt')
|
| 847 |
scores += self._test_comparator(population, 'greaterorequal8bit', 'geq')
|
| 848 |
scores += self._test_comparator(population, 'lessorequal8bit', 'leq')
|
| 849 |
total_tests += 4 * len(self.comp_a)
|
|
|
|
| 850 |
|
| 851 |
scores += self._test_equality(population)
|
| 852 |
total_tests += len(self.comp_a)
|
|
|
|
|
|
|
| 853 |
|
| 854 |
# =================================================================
|
| 855 |
-
# THRESHOLD GATES (
|
| 856 |
# =================================================================
|
|
|
|
|
|
|
| 857 |
for k, name in enumerate(['oneoutof8', 'twooutof8', 'threeoutof8', 'fouroutof8',
|
| 858 |
'fiveoutof8', 'sixoutof8', 'sevenoutof8', 'alloutof8'], 1):
|
| 859 |
scores += self._test_threshold_kofn(population, k, name)
|
| 860 |
total_tests += len(self.test_8bit)
|
|
|
|
| 861 |
|
| 862 |
scores += self._test_majority(population)
|
| 863 |
scores += self._test_minority(population)
|
| 864 |
total_tests += 2 * len(self.test_8bit)
|
|
|
|
| 865 |
|
| 866 |
scores += self._test_atleastk(population, 4)
|
| 867 |
scores += self._test_atmostk(population, 4)
|
| 868 |
scores += self._test_exactlyk(population, 4)
|
| 869 |
total_tests += 3 * len(self.test_8bit)
|
|
|
|
|
|
|
| 870 |
|
| 871 |
# =================================================================
|
| 872 |
# PATTERN RECOGNITION (72 tests)
|
| 873 |
# =================================================================
|
|
|
|
|
|
|
| 874 |
scores += self._test_popcount(population)
|
| 875 |
scores += self._test_allzeros(population)
|
| 876 |
scores += self._test_allones(population)
|
| 877 |
total_tests += 3 * len(self.test_8bit)
|
|
|
|
|
|
|
| 878 |
|
| 879 |
# =================================================================
|
| 880 |
# ERROR DETECTION (48 tests)
|
| 881 |
# =================================================================
|
|
|
|
|
|
|
| 882 |
scores += self._test_parity(population, 'paritychecker8bit', True)
|
| 883 |
scores += self._test_parity(population, 'paritygenerator8bit', True)
|
| 884 |
total_tests += 2 * len(self.test_8bit)
|
|
|
|
|
|
|
| 885 |
|
| 886 |
# =================================================================
|
| 887 |
# MODULAR ARITHMETIC (2816 tests: 256 values × 11 moduli)
|
| 888 |
# =================================================================
|
|
|
|
|
|
|
| 889 |
for mod in [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]:
|
| 890 |
scores += self._test_modular(population, mod)
|
| 891 |
total_tests += len(self.mod_test)
|
|
|
|
|
|
|
| 892 |
|
| 893 |
# =================================================================
|
| 894 |
-
# COMBINATIONAL (
|
| 895 |
# =================================================================
|
|
|
|
|
|
|
| 896 |
scores += self._test_mux2to1(population)
|
| 897 |
total_tests += 8
|
|
|
|
| 898 |
|
| 899 |
scores += self._test_decoder3to8(population)
|
| 900 |
total_tests += 64
|
|
|
|
| 901 |
|
| 902 |
scores += self._test_encoder8to3(population)
|
| 903 |
total_tests += 24
|
|
|
|
|
|
|
| 904 |
|
| 905 |
# =================================================================
|
| 906 |
-
# CONTROL FLOW (
|
| 907 |
# =================================================================
|
|
|
|
|
|
|
| 908 |
for ctrl in ['conditionaljump', 'jz', 'jnz', 'jc', 'jnc', 'jn', 'jp', 'jv', 'jnv']:
|
| 909 |
scores += self._test_conditional_jump(population, ctrl)
|
| 910 |
total_tests += 6 * 8
|
|
|
|
|
|
|
| 911 |
|
| 912 |
self.total_tests = total_tests
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 913 |
return scores / total_tests
|
| 914 |
|
| 915 |
|
|
@@ -943,7 +1141,7 @@ if __name__ == "__main__":
|
|
| 943 |
print("\nRunning evaluation...")
|
| 944 |
torch.cuda.synchronize()
|
| 945 |
start = time.perf_counter()
|
| 946 |
-
fitness = evaluator.evaluate(pop)
|
| 947 |
torch.cuda.synchronize()
|
| 948 |
elapsed = time.perf_counter() - start
|
| 949 |
|
|
|
|
| 13 |
from safetensors import safe_open
|
| 14 |
|
| 15 |
|
| 16 |
+
def load_model_10166(base_path: str = "D:/8bit-threshold-computer") -> Dict[str, torch.Tensor]:
|
| 17 |
"""Load model from safetensors."""
|
| 18 |
f = safe_open(f"{base_path}/neural_computer.safetensors", framework='numpy')
|
| 19 |
tensors = {}
|
|
|
|
| 315 |
|
| 316 |
return scores
|
| 317 |
|
| 318 |
+
def _test_multiplier8x8(self, pop: Dict, debug: bool = False) -> torch.Tensor:
|
| 319 |
+
"""Test 8x8 array multiplier."""
|
| 320 |
+
pop_size = next(iter(pop.values())).shape[0]
|
| 321 |
+
scores = torch.zeros(pop_size, device=self.device)
|
| 322 |
+
failures = []
|
| 323 |
+
|
| 324 |
+
test_pairs = [
|
| 325 |
+
(0, 0), (1, 1), (2, 3), (3, 2), (7, 7), (8, 8),
|
| 326 |
+
(15, 15), (16, 16), (255, 1), (1, 255), (255, 255),
|
| 327 |
+
(12, 12), (10, 25), (17, 15), (128, 2), (64, 4),
|
| 328 |
+
(0, 255), (255, 0), (100, 100), (50, 200), (200, 50),
|
| 329 |
+
(127, 127), (128, 128), (85, 3), (170, 2), (99, 99),
|
| 330 |
+
(13, 17), (23, 29), (31, 33), (41, 43), (53, 59),
|
| 331 |
+
(61, 67), (71, 73), (79, 83), (89, 97), (101, 103),
|
| 332 |
+
(107, 109), (113, 127), (131, 137), (139, 149), (151, 157),
|
| 333 |
+
(163, 167), (173, 179), (181, 191), (193, 197), (199, 211),
|
| 334 |
+
(223, 227), (229, 233), (239, 241), (251, 1), (1, 251),
|
| 335 |
+
(2, 128), (4, 64), (8, 32), (32, 8),
|
| 336 |
+
(3, 85), (5, 51), (7, 36),
|
| 337 |
+
(9, 28), (11, 23), (13, 19), (15, 17)
|
| 338 |
+
]
|
| 339 |
+
|
| 340 |
+
for a_val, b_val in test_pairs:
|
| 341 |
+
expected = (a_val * b_val) & 0xFFFF
|
| 342 |
+
|
| 343 |
+
a_bits = [(a_val >> i) & 1 for i in range(8)]
|
| 344 |
+
b_bits = [(b_val >> i) & 1 for i in range(8)]
|
| 345 |
+
|
| 346 |
+
pp = [[torch.zeros(pop_size, device=self.device) for _ in range(8)] for _ in range(8)]
|
| 347 |
+
for row in range(8):
|
| 348 |
+
for col in range(8):
|
| 349 |
+
a_t = torch.full((pop_size,), float(a_bits[col]), device=self.device)
|
| 350 |
+
b_t = torch.full((pop_size,), float(b_bits[row]), device=self.device)
|
| 351 |
+
inp = torch.stack([a_t, b_t], dim=1)
|
| 352 |
+
w = pop[f'arithmetic.multiplier8x8.pp.r{row}.c{col}.weight'].view(pop_size, -1)
|
| 353 |
+
b = pop[f'arithmetic.multiplier8x8.pp.r{row}.c{col}.bias'].view(pop_size)
|
| 354 |
+
pp[row][col] = heaviside((inp * w).sum(1) + b)
|
| 355 |
+
|
| 356 |
+
result_bits = [torch.zeros(pop_size, device=self.device) for _ in range(16)]
|
| 357 |
+
for col in range(8):
|
| 358 |
+
result_bits[col] = pp[0][col]
|
| 359 |
+
|
| 360 |
+
for stage in range(7):
|
| 361 |
+
row_idx = stage + 1
|
| 362 |
+
shift = row_idx
|
| 363 |
+
sum_width = 8 + stage + 1
|
| 364 |
+
|
| 365 |
+
new_result = [r.clone() for r in result_bits]
|
| 366 |
+
carry = torch.zeros(pop_size, device=self.device)
|
| 367 |
+
|
| 368 |
+
for bit in range(sum_width):
|
| 369 |
+
if bit < shift:
|
| 370 |
+
pp_bit = torch.zeros(pop_size, device=self.device)
|
| 371 |
+
elif bit <= shift + 7:
|
| 372 |
+
pp_bit = pp[row_idx][bit - shift]
|
| 373 |
+
else:
|
| 374 |
+
pp_bit = torch.zeros(pop_size, device=self.device)
|
| 375 |
+
|
| 376 |
+
prev_bit = result_bits[bit] if bit < 16 else torch.zeros(pop_size, device=self.device)
|
| 377 |
+
|
| 378 |
+
prefix = f'arithmetic.multiplier8x8.stage{stage}.bit{bit}'
|
| 379 |
+
|
| 380 |
+
inp_ab = torch.stack([prev_bit, pp_bit], dim=1)
|
| 381 |
+
w1_or = pop[f'{prefix}.ha1.sum.layer1.or.weight'].view(pop_size, -1)
|
| 382 |
+
b1_or = pop[f'{prefix}.ha1.sum.layer1.or.bias'].view(pop_size)
|
| 383 |
+
w1_nand = pop[f'{prefix}.ha1.sum.layer1.nand.weight'].view(pop_size, -1)
|
| 384 |
+
b1_nand = pop[f'{prefix}.ha1.sum.layer1.nand.bias'].view(pop_size)
|
| 385 |
+
w1_l2 = pop[f'{prefix}.ha1.sum.layer2.weight'].view(pop_size, -1)
|
| 386 |
+
b1_l2 = pop[f'{prefix}.ha1.sum.layer2.bias'].view(pop_size)
|
| 387 |
+
|
| 388 |
+
h_or = heaviside((inp_ab * w1_or).sum(1) + b1_or)
|
| 389 |
+
h_nand = heaviside((inp_ab * w1_nand).sum(1) + b1_nand)
|
| 390 |
+
hidden1 = torch.stack([h_or, h_nand], dim=1)
|
| 391 |
+
ha1_sum = heaviside((hidden1 * w1_l2).sum(1) + b1_l2)
|
| 392 |
+
|
| 393 |
+
w_c1 = pop[f'{prefix}.ha1.carry.weight'].view(pop_size, -1)
|
| 394 |
+
b_c1 = pop[f'{prefix}.ha1.carry.bias'].view(pop_size)
|
| 395 |
+
ha1_carry = heaviside((inp_ab * w_c1).sum(1) + b_c1)
|
| 396 |
+
|
| 397 |
+
inp_ha2 = torch.stack([ha1_sum, carry], dim=1)
|
| 398 |
+
w2_or = pop[f'{prefix}.ha2.sum.layer1.or.weight'].view(pop_size, -1)
|
| 399 |
+
b2_or = pop[f'{prefix}.ha2.sum.layer1.or.bias'].view(pop_size)
|
| 400 |
+
w2_nand = pop[f'{prefix}.ha2.sum.layer1.nand.weight'].view(pop_size, -1)
|
| 401 |
+
b2_nand = pop[f'{prefix}.ha2.sum.layer1.nand.bias'].view(pop_size)
|
| 402 |
+
w2_l2 = pop[f'{prefix}.ha2.sum.layer2.weight'].view(pop_size, -1)
|
| 403 |
+
b2_l2 = pop[f'{prefix}.ha2.sum.layer2.bias'].view(pop_size)
|
| 404 |
+
|
| 405 |
+
h2_or = heaviside((inp_ha2 * w2_or).sum(1) + b2_or)
|
| 406 |
+
h2_nand = heaviside((inp_ha2 * w2_nand).sum(1) + b2_nand)
|
| 407 |
+
hidden2 = torch.stack([h2_or, h2_nand], dim=1)
|
| 408 |
+
ha2_sum = heaviside((hidden2 * w2_l2).sum(1) + b2_l2)
|
| 409 |
+
|
| 410 |
+
w_c2 = pop[f'{prefix}.ha2.carry.weight'].view(pop_size, -1)
|
| 411 |
+
b_c2 = pop[f'{prefix}.ha2.carry.bias'].view(pop_size)
|
| 412 |
+
ha2_carry = heaviside((inp_ha2 * w_c2).sum(1) + b_c2)
|
| 413 |
+
|
| 414 |
+
inp_cout = torch.stack([ha1_carry, ha2_carry], dim=1)
|
| 415 |
+
w_cor = pop[f'{prefix}.carry_or.weight'].view(pop_size, -1)
|
| 416 |
+
b_cor = pop[f'{prefix}.carry_or.bias'].view(pop_size)
|
| 417 |
+
carry = heaviside((inp_cout * w_cor).sum(1) + b_cor)
|
| 418 |
+
|
| 419 |
+
if bit < 16:
|
| 420 |
+
new_result[bit] = ha2_sum
|
| 421 |
+
|
| 422 |
+
# Propagate carry to next bit position if within range
|
| 423 |
+
if sum_width < 16:
|
| 424 |
+
new_result[sum_width] = carry
|
| 425 |
+
|
| 426 |
+
result_bits = new_result
|
| 427 |
+
|
| 428 |
+
result = sum(result_bits[i] * (2**i) for i in range(16))
|
| 429 |
+
passed = (result == expected).float()
|
| 430 |
+
scores += passed
|
| 431 |
+
if debug and pop_size == 1 and passed[0].item() == 0:
|
| 432 |
+
failures.append(f"MULT({a_val} * {b_val}) = {int(result[0].item())}, expected {expected}")
|
| 433 |
+
|
| 434 |
+
if debug and failures:
|
| 435 |
+
print(f"\n Multiplier failures ({len(failures)}):")
|
| 436 |
+
for f in failures:
|
| 437 |
+
print(f" {f}")
|
| 438 |
+
|
| 439 |
+
return scores
|
| 440 |
+
|
| 441 |
# =========================================================================
|
| 442 |
# ARITHMETIC - COMPARATORS
|
| 443 |
# =========================================================================
|
|
|
|
| 909 |
# MAIN EVALUATE
|
| 910 |
# =========================================================================
|
| 911 |
|
| 912 |
+
def evaluate(self, population: Dict[str, torch.Tensor], debug: bool = False) -> torch.Tensor:
|
| 913 |
"""Evaluate fitness for entire population."""
|
| 914 |
pop_size = next(iter(population.values())).shape[0]
|
| 915 |
scores = torch.zeros(pop_size, device=self.device)
|
| 916 |
total_tests = 0
|
| 917 |
+
self.category_scores = {} # Track per-category scores for debugging
|
| 918 |
|
| 919 |
# =================================================================
|
| 920 |
# BOOLEAN GATES (34 tests)
|
| 921 |
# =================================================================
|
| 922 |
+
cat_start = scores.clone()
|
| 923 |
+
cat_tests = 0
|
| 924 |
for gate in ['and', 'or', 'nand', 'nor']:
|
| 925 |
scores += self._test_single_gate(population, gate, self.tt2, self.expected[gate])
|
| 926 |
total_tests += 4
|
| 927 |
+
cat_tests += 4
|
| 928 |
|
| 929 |
# NOT
|
| 930 |
w = population['boolean.not.weight'].view(pop_size, -1)
|
|
|
|
| 932 |
out = heaviside(self.not_inputs @ w.T + b)
|
| 933 |
scores += (out == self.expected['not'].unsqueeze(1)).float().sum(0)
|
| 934 |
total_tests += 2
|
| 935 |
+
cat_tests += 2
|
| 936 |
|
| 937 |
# IMPLIES
|
| 938 |
scores += self._test_single_gate(population, 'implies', self.tt2, self.expected['implies'])
|
| 939 |
total_tests += 4
|
| 940 |
+
cat_tests += 4
|
| 941 |
|
| 942 |
# XOR, XNOR, BIIMPLIES
|
| 943 |
scores += self._test_twolayer_gate(population, 'boolean.xor', self.tt2, self.expected['xor'])
|
| 944 |
scores += self._test_twolayer_gate(population, 'boolean.xnor', self.tt2, self.expected['xnor'])
|
| 945 |
scores += self._test_twolayer_gate(population, 'boolean.biimplies', self.tt2, self.expected['biimplies'])
|
| 946 |
total_tests += 12
|
| 947 |
+
cat_tests += 12
|
| 948 |
+
self.category_scores['boolean'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 949 |
|
| 950 |
# =================================================================
|
| 951 |
+
# ARITHMETIC - ADDERS (370 tests)
|
| 952 |
# =================================================================
|
| 953 |
+
cat_start = scores.clone()
|
| 954 |
+
cat_tests = 0
|
| 955 |
+
|
| 956 |
+
sub_start = scores.clone()
|
| 957 |
scores += self._test_halfadder(population)
|
| 958 |
total_tests += 8
|
| 959 |
+
cat_tests += 8
|
| 960 |
+
self.category_scores['halfadder'] = ((scores - sub_start)[0].item(), 8)
|
| 961 |
|
| 962 |
+
sub_start = scores.clone()
|
| 963 |
scores += self._test_fulladder(population)
|
| 964 |
total_tests += 16
|
| 965 |
+
cat_tests += 16
|
| 966 |
+
self.category_scores['fulladder'] = ((scores - sub_start)[0].item(), 16)
|
| 967 |
|
| 968 |
# Ripple carry adders
|
| 969 |
+
sub_start = scores.clone()
|
| 970 |
rc2_tests = [(a, b) for a in range(4) for b in range(4)]
|
| 971 |
scores += self._test_ripplecarry(population, 2, rc2_tests)
|
| 972 |
total_tests += 16
|
| 973 |
+
cat_tests += 16
|
| 974 |
+
self.category_scores['ripplecarry2'] = ((scores - sub_start)[0].item(), 16)
|
| 975 |
|
| 976 |
+
sub_start = scores.clone()
|
| 977 |
rc4_tests = [(a, b) for a in range(16) for b in range(16)]
|
| 978 |
scores += self._test_ripplecarry(population, 4, rc4_tests)
|
| 979 |
total_tests += 256
|
| 980 |
+
cat_tests += 256
|
| 981 |
+
self.category_scores['ripplecarry4'] = ((scores - sub_start)[0].item(), 256)
|
| 982 |
|
| 983 |
+
sub_start = scores.clone()
|
| 984 |
rc8_tests = [(0,0), (1,1), (127,128), (255,1), (128,127), (255,255),
|
| 985 |
(0xAA, 0x55), (0x0F, 0xF0), (100, 155), (200, 55)]
|
| 986 |
scores += self._test_ripplecarry(population, 8, rc8_tests)
|
| 987 |
total_tests += len(rc8_tests)
|
| 988 |
+
cat_tests += len(rc8_tests)
|
| 989 |
+
self.category_scores['ripplecarry8'] = ((scores - sub_start)[0].item(), len(rc8_tests))
|
| 990 |
+
|
| 991 |
+
# 8x8 Multiplier (62 unique test pairs)
|
| 992 |
+
sub_start = scores.clone()
|
| 993 |
+
scores += self._test_multiplier8x8(population, debug=debug)
|
| 994 |
+
total_tests += 62
|
| 995 |
+
cat_tests += 62
|
| 996 |
+
self.category_scores['multiplier8x8'] = ((scores - sub_start)[0].item(), 62)
|
| 997 |
+
|
| 998 |
+
self.category_scores['arithmetic_adders'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 999 |
|
| 1000 |
# =================================================================
|
| 1001 |
+
# ARITHMETIC - COMPARATORS (300 tests)
|
| 1002 |
# =================================================================
|
| 1003 |
+
cat_start = scores.clone()
|
| 1004 |
+
cat_tests = 0
|
| 1005 |
scores += self._test_comparator(population, 'greaterthan8bit', 'gt')
|
| 1006 |
scores += self._test_comparator(population, 'lessthan8bit', 'lt')
|
| 1007 |
scores += self._test_comparator(population, 'greaterorequal8bit', 'geq')
|
| 1008 |
scores += self._test_comparator(population, 'lessorequal8bit', 'leq')
|
| 1009 |
total_tests += 4 * len(self.comp_a)
|
| 1010 |
+
cat_tests += 4 * len(self.comp_a)
|
| 1011 |
|
| 1012 |
scores += self._test_equality(population)
|
| 1013 |
total_tests += len(self.comp_a)
|
| 1014 |
+
cat_tests += len(self.comp_a)
|
| 1015 |
+
self.category_scores['comparators'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1016 |
|
| 1017 |
# =================================================================
|
| 1018 |
+
# THRESHOLD GATES (312 tests)
|
| 1019 |
# =================================================================
|
| 1020 |
+
cat_start = scores.clone()
|
| 1021 |
+
cat_tests = 0
|
| 1022 |
for k, name in enumerate(['oneoutof8', 'twooutof8', 'threeoutof8', 'fouroutof8',
|
| 1023 |
'fiveoutof8', 'sixoutof8', 'sevenoutof8', 'alloutof8'], 1):
|
| 1024 |
scores += self._test_threshold_kofn(population, k, name)
|
| 1025 |
total_tests += len(self.test_8bit)
|
| 1026 |
+
cat_tests += len(self.test_8bit)
|
| 1027 |
|
| 1028 |
scores += self._test_majority(population)
|
| 1029 |
scores += self._test_minority(population)
|
| 1030 |
total_tests += 2 * len(self.test_8bit)
|
| 1031 |
+
cat_tests += 2 * len(self.test_8bit)
|
| 1032 |
|
| 1033 |
scores += self._test_atleastk(population, 4)
|
| 1034 |
scores += self._test_atmostk(population, 4)
|
| 1035 |
scores += self._test_exactlyk(population, 4)
|
| 1036 |
total_tests += 3 * len(self.test_8bit)
|
| 1037 |
+
cat_tests += 3 * len(self.test_8bit)
|
| 1038 |
+
self.category_scores['threshold'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1039 |
|
| 1040 |
# =================================================================
|
| 1041 |
# PATTERN RECOGNITION (72 tests)
|
| 1042 |
# =================================================================
|
| 1043 |
+
cat_start = scores.clone()
|
| 1044 |
+
cat_tests = 0
|
| 1045 |
scores += self._test_popcount(population)
|
| 1046 |
scores += self._test_allzeros(population)
|
| 1047 |
scores += self._test_allones(population)
|
| 1048 |
total_tests += 3 * len(self.test_8bit)
|
| 1049 |
+
cat_tests += 3 * len(self.test_8bit)
|
| 1050 |
+
self.category_scores['pattern'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1051 |
|
| 1052 |
# =================================================================
|
| 1053 |
# ERROR DETECTION (48 tests)
|
| 1054 |
# =================================================================
|
| 1055 |
+
cat_start = scores.clone()
|
| 1056 |
+
cat_tests = 0
|
| 1057 |
scores += self._test_parity(population, 'paritychecker8bit', True)
|
| 1058 |
scores += self._test_parity(population, 'paritygenerator8bit', True)
|
| 1059 |
total_tests += 2 * len(self.test_8bit)
|
| 1060 |
+
cat_tests += 2 * len(self.test_8bit)
|
| 1061 |
+
self.category_scores['error_detection'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1062 |
|
| 1063 |
# =================================================================
|
| 1064 |
# MODULAR ARITHMETIC (2816 tests: 256 values × 11 moduli)
|
| 1065 |
# =================================================================
|
| 1066 |
+
cat_start = scores.clone()
|
| 1067 |
+
cat_tests = 0
|
| 1068 |
for mod in [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]:
|
| 1069 |
scores += self._test_modular(population, mod)
|
| 1070 |
total_tests += len(self.mod_test)
|
| 1071 |
+
cat_tests += len(self.mod_test)
|
| 1072 |
+
self.category_scores['modular'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1073 |
|
| 1074 |
# =================================================================
|
| 1075 |
+
# COMBINATIONAL (96 tests)
|
| 1076 |
# =================================================================
|
| 1077 |
+
cat_start = scores.clone()
|
| 1078 |
+
cat_tests = 0
|
| 1079 |
scores += self._test_mux2to1(population)
|
| 1080 |
total_tests += 8
|
| 1081 |
+
cat_tests += 8
|
| 1082 |
|
| 1083 |
scores += self._test_decoder3to8(population)
|
| 1084 |
total_tests += 64
|
| 1085 |
+
cat_tests += 64
|
| 1086 |
|
| 1087 |
scores += self._test_encoder8to3(population)
|
| 1088 |
total_tests += 24
|
| 1089 |
+
cat_tests += 24
|
| 1090 |
+
self.category_scores['combinational'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1091 |
|
| 1092 |
# =================================================================
|
| 1093 |
+
# CONTROL FLOW (432 tests: 9 circuits × 6 cases × 8 bits)
|
| 1094 |
# =================================================================
|
| 1095 |
+
cat_start = scores.clone()
|
| 1096 |
+
cat_tests = 0
|
| 1097 |
for ctrl in ['conditionaljump', 'jz', 'jnz', 'jc', 'jnc', 'jn', 'jp', 'jv', 'jnv']:
|
| 1098 |
scores += self._test_conditional_jump(population, ctrl)
|
| 1099 |
total_tests += 6 * 8
|
| 1100 |
+
cat_tests += 6 * 8
|
| 1101 |
+
self.category_scores['control_flow'] = ((scores - cat_start)[0].item(), cat_tests)
|
| 1102 |
|
| 1103 |
self.total_tests = total_tests
|
| 1104 |
+
|
| 1105 |
+
if debug and pop_size == 1:
|
| 1106 |
+
print("\n=== DEBUG: Per-category results ===")
|
| 1107 |
+
for cat, (got, expected) in self.category_scores.items():
|
| 1108 |
+
status = "PASS" if got == expected else "FAIL"
|
| 1109 |
+
print(f" {cat}: {int(got)}/{expected} [{status}]")
|
| 1110 |
+
|
| 1111 |
return scores / total_tests
|
| 1112 |
|
| 1113 |
|
|
|
|
| 1141 |
print("\nRunning evaluation...")
|
| 1142 |
torch.cuda.synchronize()
|
| 1143 |
start = time.perf_counter()
|
| 1144 |
+
fitness = evaluator.evaluate(pop, debug=True)
|
| 1145 |
torch.cuda.synchronize()
|
| 1146 |
elapsed = time.perf_counter() - start
|
| 1147 |
|
neural_computer.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:51d4e2725c0d24bce807a5b7dc58319e9eed0f95c17fc39e662272ed0cbe8f1f
|
| 3 |
+
size 351104
|