phanerozoic commited on
Commit
38b0582
·
verified ·
1 Parent(s): bbff33a

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. .gitattributes +35 -35
  2. README.md +3 -4
  3. iron_eval.py +206 -8
  4. 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: 1,482
21
- Parameters: 3,188
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 (4416/4416 tests passing)
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-10166") -> Dict[str, torch.Tensor]:
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 (340 tests)
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 (240 tests)
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 (264 tests)
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 (88 tests)
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 (480 tests: 10 circuits × 6 cases × 8 bits)
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:3c843f449639750f270702f5d5600d063c8e7d28f4a234fe062d3fcd8caf644b
3
- size 151728
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:51d4e2725c0d24bce807a5b7dc58319e9eed0f95c17fc39e662272ed0cbe8f1f
3
+ size 351104