| import torch
|
| from safetensors.torch import save_file
|
|
|
| weights = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| def add_xor2_weights(prefix, idx_a, idx_b, total_inputs):
|
| """Add weights for XOR(input[a], input[b])."""
|
| w_or = [0.0] * total_inputs
|
| w_or[idx_a] = 1.0
|
| w_or[idx_b] = 1.0
|
| weights[f'{prefix}.or.weight'] = torch.tensor([w_or], dtype=torch.float32)
|
| weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
|
|
| w_nand = [0.0] * total_inputs
|
| w_nand[idx_a] = -1.0
|
| w_nand[idx_b] = -1.0
|
| weights[f'{prefix}.nand.weight'] = torch.tensor([w_nand], dtype=torch.float32)
|
| weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
|
|
| weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
|
|
| def add_xor2_stage_weights(prefix):
|
| """Add weights for XOR of two intermediate signals."""
|
| weights[f'{prefix}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
| weights[f'{prefix}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
|
| weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
| weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
|
|
|
|
|
|
|
|
| add_xor2_weights('crc0', 0, 3, 4)
|
|
|
|
|
| add_xor2_weights('crc1.x12', 1, 2, 4)
|
| add_xor2_stage_weights('crc1.final')
|
|
|
|
|
| add_xor2_weights('crc2', 0, 2, 4)
|
|
|
|
|
| add_xor2_weights('crc3', 0, 1, 4)
|
|
|
| save_file(weights, 'model.safetensors')
|
|
|
| def xor2_eval(a, b, w, or_w, or_b, nand_w, nand_b, and_w, and_b):
|
| """Evaluate XOR using threshold gates."""
|
| inp = torch.tensor([float(a), float(b)])
|
| or_out = int((inp @ or_w.T + or_b >= 0).item())
|
| nand_out = int((inp @ nand_w.T + nand_b >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| return int((l1 @ and_w.T + and_b >= 0).item())
|
|
|
| def crc4(d3, d2, d1, d0):
|
| inp = torch.tensor([float(d3), float(d2), float(d1), float(d0)])
|
|
|
|
|
| or_out = int((inp @ weights['crc0.or.weight'].T + weights['crc0.or.bias'] >= 0).item())
|
| nand_out = int((inp @ weights['crc0.nand.weight'].T + weights['crc0.nand.bias'] >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| crc0 = int((l1 @ weights['crc0.and.weight'].T + weights['crc0.and.bias'] >= 0).item())
|
|
|
|
|
| or_out = int((inp @ weights['crc1.x12.or.weight'].T + weights['crc1.x12.or.bias'] >= 0).item())
|
| nand_out = int((inp @ weights['crc1.x12.nand.weight'].T + weights['crc1.x12.nand.bias'] >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| x12 = int((l1 @ weights['crc1.x12.and.weight'].T + weights['crc1.x12.and.bias'] >= 0).item())
|
|
|
| inp2 = torch.tensor([float(x12), float(d0)])
|
| or_out = int((inp2 @ weights['crc1.final.or.weight'].T + weights['crc1.final.or.bias'] >= 0).item())
|
| nand_out = int((inp2 @ weights['crc1.final.nand.weight'].T + weights['crc1.final.nand.bias'] >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| crc1 = int((l1 @ weights['crc1.final.and.weight'].T + weights['crc1.final.and.bias'] >= 0).item())
|
|
|
|
|
| or_out = int((inp @ weights['crc2.or.weight'].T + weights['crc2.or.bias'] >= 0).item())
|
| nand_out = int((inp @ weights['crc2.nand.weight'].T + weights['crc2.nand.bias'] >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| crc2 = int((l1 @ weights['crc2.and.weight'].T + weights['crc2.and.bias'] >= 0).item())
|
|
|
|
|
| or_out = int((inp @ weights['crc3.or.weight'].T + weights['crc3.or.bias'] >= 0).item())
|
| nand_out = int((inp @ weights['crc3.nand.weight'].T + weights['crc3.nand.bias'] >= 0).item())
|
| l1 = torch.tensor([float(or_out), float(nand_out)])
|
| crc3 = int((l1 @ weights['crc3.and.weight'].T + weights['crc3.and.bias'] >= 0).item())
|
|
|
| return crc3, crc2, crc1, crc0
|
|
|
| def crc4_ref(d3, d2, d1, d0):
|
| """Reference CRC-4 computation."""
|
| crc0 = d3 ^ d0
|
| crc1 = d2 ^ d1 ^ d0
|
| crc2 = d3 ^ d1
|
| crc3 = d3 ^ d2
|
| return crc3, crc2, crc1, crc0
|
|
|
| print("Verifying CRC-4 Generator (polynomial x^4+x+1)...")
|
| errors = 0
|
| for i in range(16):
|
| d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| result = crc4(d3, d2, d1, d0)
|
| expected = crc4_ref(d3, d2, d1, d0)
|
| if result != expected:
|
| errors += 1
|
| print(f"ERROR: {d3}{d2}{d1}{d0} -> {result}, expected {expected}")
|
|
|
| if errors == 0:
|
| print("All 16 test cases passed!")
|
| else:
|
| print(f"FAILED: {errors} errors")
|
|
|
| print("\nTruth Table:")
|
| print("Data | CRC")
|
| print("d3d2d1d0 | c3c2c1c0")
|
| print("-" * 22)
|
| for i in range(16):
|
| d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| c3, c2, c1, c0 = crc4(d3, d2, d1, d0)
|
| print(f" {d3} {d2} {d1} {d0} | {c3} {c2} {c1} {c0}")
|
|
|
| mag = sum(t.abs().sum().item() for t in weights.values())
|
| print(f"\nMagnitude: {mag:.0f}")
|
| print(f"Parameters: {sum(t.numel() for t in weights.values())}")
|
| print(f"Neurons: {len([k for k in weights.keys() if 'weight' in k])}")
|
|
|