CharlesCNorton commited on
Commit ·
3a58474
0
Parent(s):
CRC-16 CCITT at magnitude 53 using optimal XOR/XOR3
Browse files- README.md +145 -0
- config.json +17 -0
- create_safetensors.py +215 -0
- model.safetensors +0 -0
README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
tags:
|
| 4 |
+
- pytorch
|
| 5 |
+
- safetensors
|
| 6 |
+
- threshold-logic
|
| 7 |
+
- neuromorphic
|
| 8 |
+
- error-detection
|
| 9 |
+
- crc
|
| 10 |
+
- optimized
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# threshold-crc16-mag53
|
| 14 |
+
|
| 15 |
+
CRC-16 CCITT single-step function using **magnitude-optimal XOR components**.
|
| 16 |
+
|
| 17 |
+
## Optimization
|
| 18 |
+
|
| 19 |
+
This circuit uses proven-optimal XOR decompositions instead of naive OR+NAND+AND:
|
| 20 |
+
|
| 21 |
+
| Component | Naive Approach | Optimized | Savings |
|
| 22 |
+
|-----------|---------------|-----------|---------|
|
| 23 |
+
| XOR (2-input) | OR+NAND+AND (mag 10) | mag-7 symmetric | 30% |
|
| 24 |
+
| XOR3 (3-input) | ge1/ge2/ge3 (mag 19) | mag-10 flat | 47% |
|
| 25 |
+
|
| 26 |
+
**Total magnitude: 74 → 53 (28% reduction)**
|
| 27 |
+
|
| 28 |
+
## XOR Component Choices
|
| 29 |
+
|
| 30 |
+
### XOR (2-input) - Magnitude 7
|
| 31 |
+
|
| 32 |
+
From the 6 proven-optimal solutions, we use the **symmetric opposites** family:
|
| 33 |
+
|
| 34 |
+
```
|
| 35 |
+
h1: [-1, +1], bias=0 (fires when b > a)
|
| 36 |
+
h2: [+1, -1], bias=0 (fires when a > b)
|
| 37 |
+
out: [-1, -1], bias=1 (NOR of hidden)
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
Selected for:
|
| 41 |
+
- Zero biases in hidden layer (simpler accumulator)
|
| 42 |
+
- Symmetric structure (clearer mathematical reasoning)
|
| 43 |
+
- Proven optimal via exhaustive search (no mag-6 solutions exist)
|
| 44 |
+
|
| 45 |
+
### XOR3 (3-input) - Magnitude 10
|
| 46 |
+
|
| 47 |
+
From the 18 proven-optimal solutions, we use the **selector + full** pattern:
|
| 48 |
+
|
| 49 |
+
```
|
| 50 |
+
h1: [0, 0, -1], bias=0 (selector: fires when c=0)
|
| 51 |
+
h2: [-1, +1, -1], bias=0 (full: fires when b > a+c)
|
| 52 |
+
h3: [-1, -1, +1], bias=0 (full: fires when c > a+b)
|
| 53 |
+
out: [+1, -1, -1], bias=0
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
Selected for:
|
| 57 |
+
- All biases are zero
|
| 58 |
+
- Selector neuron isolates the "unique" input in CRC context
|
| 59 |
+
- Proven optimal via exhaustive search (387M configs, no mag-9 solutions)
|
| 60 |
+
|
| 61 |
+
## Polynomial
|
| 62 |
+
|
| 63 |
+
`0x1021` = x^16 + x^12 + x^5 + 1 (CRC-16-CCITT)
|
| 64 |
+
|
| 65 |
+
## Function
|
| 66 |
+
|
| 67 |
+
```
|
| 68 |
+
feedback = C[15] XOR D
|
| 69 |
+
|
| 70 |
+
C'[0] = feedback (tap at x^0) ← XOR (mag 7)
|
| 71 |
+
C'[1] = C[0]
|
| 72 |
+
C'[2] = C[1]
|
| 73 |
+
C'[3] = C[2]
|
| 74 |
+
C'[4] = C[3]
|
| 75 |
+
C'[5] = C[4] XOR feedback (tap at x^5) ← XOR3 (mag 10)
|
| 76 |
+
C'[6] = C[5]
|
| 77 |
+
...
|
| 78 |
+
C'[11] = C[10]
|
| 79 |
+
C'[12] = C[11] XOR feedback (tap at x^12) ← XOR3 (mag 10)
|
| 80 |
+
C'[13] = C[12]
|
| 81 |
+
C'[14] = C[13]
|
| 82 |
+
C'[15] = C[14]
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
## Architecture
|
| 86 |
+
|
| 87 |
+
| | |
|
| 88 |
+
|---|---|
|
| 89 |
+
| Inputs | 17 (C[0:15] + D) |
|
| 90 |
+
| Outputs | 16 (C'[0:15]) |
|
| 91 |
+
| Neurons | 24 |
|
| 92 |
+
| Layers | 2 |
|
| 93 |
+
| Parameters | 389 |
|
| 94 |
+
| **Magnitude** | **53** |
|
| 95 |
+
|
| 96 |
+
### Breakdown
|
| 97 |
+
|
| 98 |
+
| Component | Neurons | Magnitude |
|
| 99 |
+
|-----------|---------|-----------|
|
| 100 |
+
| 13 pass-throughs | 13 | 26 |
|
| 101 |
+
| C'[0] XOR | 3 | 7 |
|
| 102 |
+
| C'[5] XOR3 | 4 | 10 |
|
| 103 |
+
| C'[12] XOR3 | 4 | 10 |
|
| 104 |
+
| **Total** | **24** | **53** |
|
| 105 |
+
|
| 106 |
+
## Verification
|
| 107 |
+
|
| 108 |
+
- Exhaustively tested against all 2^17 = 131,072 input combinations
|
| 109 |
+
- XOR optimality proven via exhaustive search (magnitude 7, 6 solutions)
|
| 110 |
+
- XOR3 optimality proven via exhaustive search (magnitude 10, 18 solutions)
|
| 111 |
+
|
| 112 |
+
## Comparison to Naive Implementation
|
| 113 |
+
|
| 114 |
+
| Version | Magnitude | Reduction |
|
| 115 |
+
|---------|-----------|-----------|
|
| 116 |
+
| threshold-crc16 (naive) | 74 | baseline |
|
| 117 |
+
| **threshold-crc16-mag53** | **53** | **28%** |
|
| 118 |
+
|
| 119 |
+
## Files
|
| 120 |
+
|
| 121 |
+
```
|
| 122 |
+
threshold-crc16-mag53/
|
| 123 |
+
├── model.safetensors
|
| 124 |
+
├── model.py
|
| 125 |
+
├── create_safetensors.py
|
| 126 |
+
├── config.json
|
| 127 |
+
└── README.md
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
## Usage
|
| 131 |
+
|
| 132 |
+
```python
|
| 133 |
+
from safetensors.torch import load_file
|
| 134 |
+
from model import forward
|
| 135 |
+
|
| 136 |
+
weights = load_file('model.safetensors')
|
| 137 |
+
|
| 138 |
+
# Single step: 16-bit CRC state + 1 data bit → new 16-bit state
|
| 139 |
+
inputs = [c0, c1, ..., c15, d] # 17 binary values
|
| 140 |
+
outputs = forward(inputs, weights) # 16 binary values
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
## License
|
| 144 |
+
|
| 145 |
+
MIT
|
config.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "threshold-crc16-mag53",
|
| 3 |
+
"description": "CRC-16 CCITT single-step using magnitude-optimal XOR components",
|
| 4 |
+
"inputs": 17,
|
| 5 |
+
"outputs": 16,
|
| 6 |
+
"neurons": 24,
|
| 7 |
+
"layers": 2,
|
| 8 |
+
"parameters": 389,
|
| 9 |
+
"magnitude": 53,
|
| 10 |
+
"polynomial": "0x1021",
|
| 11 |
+
"optimization": {
|
| 12 |
+
"xor_magnitude": 7,
|
| 13 |
+
"xor3_magnitude": 10,
|
| 14 |
+
"baseline_magnitude": 74,
|
| 15 |
+
"reduction_percent": 28
|
| 16 |
+
}
|
| 17 |
+
}
|
create_safetensors.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from safetensors.torch import save_file
|
| 3 |
+
|
| 4 |
+
weights = {}
|
| 5 |
+
|
| 6 |
+
def add_neuron(name, w_list, bias):
|
| 7 |
+
weights[f'{name}.weight'] = torch.tensor([w_list], dtype=torch.float32)
|
| 8 |
+
weights[f'{name}.bias'] = torch.tensor([bias], dtype=torch.float32)
|
| 9 |
+
|
| 10 |
+
# CRC-16-CCITT (polynomial 0x1021: x^16 + x^12 + x^5 + 1)
|
| 11 |
+
# Inputs: C[0], C[1], ..., C[15], D (indices 0-16), 17 total
|
| 12 |
+
#
|
| 13 |
+
# Using proven-optimal XOR (mag 7) and XOR3 (mag 10) structures:
|
| 14 |
+
# - XOR mag-7: symmetric family, h1=[-1,1] b=0, h2=[1,-1] b=0, out=[-1,-1] b=1
|
| 15 |
+
# - XOR3 mag-10: selector+full pattern, h1=sel, h2=full, h3=full, out weights
|
| 16 |
+
#
|
| 17 |
+
# Outputs:
|
| 18 |
+
# C'[0] = C[15] XOR D (2-input XOR, mag 7)
|
| 19 |
+
# C'[5] = C[4] XOR C[15] XOR D (3-input XOR, mag 10)
|
| 20 |
+
# C'[12] = C[11] XOR C[15] XOR D (3-input XOR, mag 10)
|
| 21 |
+
# C'[i] = C[i-1] for other positions (pass-through, mag 2 each)
|
| 22 |
+
|
| 23 |
+
# ============================================================
|
| 24 |
+
# PASS-THROUGH NEURONS (13 total, magnitude = 26)
|
| 25 |
+
# C'[i] = C[i-1]: weight 1 on input, bias -1
|
| 26 |
+
# ============================================================
|
| 27 |
+
|
| 28 |
+
w = [0.0]*17; w[0] = 1.0
|
| 29 |
+
add_neuron('c1', w, -1.0) # C'[1] = C[0]
|
| 30 |
+
|
| 31 |
+
w = [0.0]*17; w[1] = 1.0
|
| 32 |
+
add_neuron('c2', w, -1.0) # C'[2] = C[1]
|
| 33 |
+
|
| 34 |
+
w = [0.0]*17; w[2] = 1.0
|
| 35 |
+
add_neuron('c3', w, -1.0) # C'[3] = C[2]
|
| 36 |
+
|
| 37 |
+
w = [0.0]*17; w[3] = 1.0
|
| 38 |
+
add_neuron('c4', w, -1.0) # C'[4] = C[3]
|
| 39 |
+
|
| 40 |
+
w = [0.0]*17; w[5] = 1.0
|
| 41 |
+
add_neuron('c6', w, -1.0) # C'[6] = C[5]
|
| 42 |
+
|
| 43 |
+
w = [0.0]*17; w[6] = 1.0
|
| 44 |
+
add_neuron('c7', w, -1.0) # C'[7] = C[6]
|
| 45 |
+
|
| 46 |
+
w = [0.0]*17; w[7] = 1.0
|
| 47 |
+
add_neuron('c8', w, -1.0) # C'[8] = C[7]
|
| 48 |
+
|
| 49 |
+
w = [0.0]*17; w[8] = 1.0
|
| 50 |
+
add_neuron('c9', w, -1.0) # C'[9] = C[8]
|
| 51 |
+
|
| 52 |
+
w = [0.0]*17; w[9] = 1.0
|
| 53 |
+
add_neuron('c10', w, -1.0) # C'[10] = C[9]
|
| 54 |
+
|
| 55 |
+
w = [0.0]*17; w[10] = 1.0
|
| 56 |
+
add_neuron('c11', w, -1.0) # C'[11] = C[10]
|
| 57 |
+
|
| 58 |
+
w = [0.0]*17; w[12] = 1.0
|
| 59 |
+
add_neuron('c13', w, -1.0) # C'[13] = C[12]
|
| 60 |
+
|
| 61 |
+
w = [0.0]*17; w[13] = 1.0
|
| 62 |
+
add_neuron('c14', w, -1.0) # C'[14] = C[13]
|
| 63 |
+
|
| 64 |
+
w = [0.0]*17; w[14] = 1.0
|
| 65 |
+
add_neuron('c15', w, -1.0) # C'[15] = C[14]
|
| 66 |
+
|
| 67 |
+
# ============================================================
|
| 68 |
+
# C'[0] = C[15] XOR D (2-input XOR, magnitude 7)
|
| 69 |
+
# Using mag-7 symmetric family: h1=[-1,1], h2=[1,-1], out=[-1,-1] b=1
|
| 70 |
+
# Inputs at indices 15 (C[15]) and 16 (D)
|
| 71 |
+
# ============================================================
|
| 72 |
+
|
| 73 |
+
w = [0.0]*17; w[15] = -1.0; w[16] = 1.0
|
| 74 |
+
add_neuron('c0.h1', w, 0.0) # fires when D > C[15]
|
| 75 |
+
|
| 76 |
+
w = [0.0]*17; w[15] = 1.0; w[16] = -1.0
|
| 77 |
+
add_neuron('c0.h2', w, 0.0) # fires when C[15] > D
|
| 78 |
+
|
| 79 |
+
add_neuron('c0.out', [-1.0, -1.0], 1.0) # fires when exactly one hidden fires
|
| 80 |
+
|
| 81 |
+
# ============================================================
|
| 82 |
+
# C'[5] = C[4] XOR C[15] XOR D (3-input XOR, magnitude 10)
|
| 83 |
+
# Using mag-10 selector pattern: sel on C[4], fulls on (C[4], C[15], D)
|
| 84 |
+
# Inputs at indices 4 (C[4]), 15 (C[15]), 16 (D)
|
| 85 |
+
# ============================================================
|
| 86 |
+
|
| 87 |
+
w = [0.0]*17; w[4] = -1.0 # selector on C[4]
|
| 88 |
+
add_neuron('c5.h1', w, 0.0) # fires when C[4] = 0
|
| 89 |
+
|
| 90 |
+
w = [0.0]*17; w[4] = -1.0; w[15] = 1.0; w[16] = -1.0
|
| 91 |
+
add_neuron('c5.h2', w, 0.0) # full pattern
|
| 92 |
+
|
| 93 |
+
w = [0.0]*17; w[4] = -1.0; w[15] = -1.0; w[16] = 1.0
|
| 94 |
+
add_neuron('c5.h3', w, 0.0) # full pattern
|
| 95 |
+
|
| 96 |
+
add_neuron('c5.out', [1.0, -1.0, -1.0], 0.0)
|
| 97 |
+
|
| 98 |
+
# ============================================================
|
| 99 |
+
# C'[12] = C[11] XOR C[15] XOR D (3-input XOR, magnitude 10)
|
| 100 |
+
# Using mag-10 selector pattern: sel on C[11], fulls on (C[11], C[15], D)
|
| 101 |
+
# Inputs at indices 11 (C[11]), 15 (C[15]), 16 (D)
|
| 102 |
+
# ============================================================
|
| 103 |
+
|
| 104 |
+
w = [0.0]*17; w[11] = -1.0 # selector on C[11]
|
| 105 |
+
add_neuron('c12.h1', w, 0.0) # fires when C[11] = 0
|
| 106 |
+
|
| 107 |
+
w = [0.0]*17; w[11] = -1.0; w[15] = 1.0; w[16] = -1.0
|
| 108 |
+
add_neuron('c12.h2', w, 0.0) # full pattern
|
| 109 |
+
|
| 110 |
+
w = [0.0]*17; w[11] = -1.0; w[15] = -1.0; w[16] = 1.0
|
| 111 |
+
add_neuron('c12.h3', w, 0.0) # full pattern
|
| 112 |
+
|
| 113 |
+
add_neuron('c12.out', [1.0, -1.0, -1.0], 0.0)
|
| 114 |
+
|
| 115 |
+
save_file(weights, 'model.safetensors')
|
| 116 |
+
|
| 117 |
+
# ============================================================
|
| 118 |
+
# Verification
|
| 119 |
+
# ============================================================
|
| 120 |
+
|
| 121 |
+
def crc16_step_ref(crc, data_bit):
|
| 122 |
+
feedback = ((crc >> 15) ^ data_bit) & 1
|
| 123 |
+
crc = (crc << 1) & 0xFFFF
|
| 124 |
+
if feedback:
|
| 125 |
+
crc ^= 0x1021
|
| 126 |
+
return crc
|
| 127 |
+
|
| 128 |
+
def threshold_eval(inputs):
|
| 129 |
+
# Pass-throughs (layer 1, direct from inputs)
|
| 130 |
+
pass_throughs = {}
|
| 131 |
+
for name in ['c1', 'c2', 'c3', 'c4', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c13', 'c14', 'c15']:
|
| 132 |
+
w = weights[f'{name}.weight'].flatten()
|
| 133 |
+
b = weights[f'{name}.bias'].item()
|
| 134 |
+
pass_throughs[name] = 1.0 if (inputs * w).sum() + b >= 0 else 0.0
|
| 135 |
+
|
| 136 |
+
# C'[0] XOR (layer 1 hidden)
|
| 137 |
+
c0_h1 = 1.0 if (inputs * weights['c0.h1.weight'].flatten()).sum() + weights['c0.h1.bias'].item() >= 0 else 0.0
|
| 138 |
+
c0_h2 = 1.0 if (inputs * weights['c0.h2.weight'].flatten()).sum() + weights['c0.h2.bias'].item() >= 0 else 0.0
|
| 139 |
+
|
| 140 |
+
# C'[0] XOR (layer 2 output)
|
| 141 |
+
h = torch.tensor([c0_h1, c0_h2])
|
| 142 |
+
c0_out = 1.0 if (h * weights['c0.out.weight'].flatten()).sum() + weights['c0.out.bias'].item() >= 0 else 0.0
|
| 143 |
+
|
| 144 |
+
# C'[5] XOR3 (layer 1 hidden)
|
| 145 |
+
c5_h1 = 1.0 if (inputs * weights['c5.h1.weight'].flatten()).sum() + weights['c5.h1.bias'].item() >= 0 else 0.0
|
| 146 |
+
c5_h2 = 1.0 if (inputs * weights['c5.h2.weight'].flatten()).sum() + weights['c5.h2.bias'].item() >= 0 else 0.0
|
| 147 |
+
c5_h3 = 1.0 if (inputs * weights['c5.h3.weight'].flatten()).sum() + weights['c5.h3.bias'].item() >= 0 else 0.0
|
| 148 |
+
|
| 149 |
+
# C'[5] XOR3 (layer 2 output)
|
| 150 |
+
h = torch.tensor([c5_h1, c5_h2, c5_h3])
|
| 151 |
+
c5_out = 1.0 if (h * weights['c5.out.weight'].flatten()).sum() + weights['c5.out.bias'].item() >= 0 else 0.0
|
| 152 |
+
|
| 153 |
+
# C'[12] XOR3 (layer 1 hidden)
|
| 154 |
+
c12_h1 = 1.0 if (inputs * weights['c12.h1.weight'].flatten()).sum() + weights['c12.h1.bias'].item() >= 0 else 0.0
|
| 155 |
+
c12_h2 = 1.0 if (inputs * weights['c12.h2.weight'].flatten()).sum() + weights['c12.h2.bias'].item() >= 0 else 0.0
|
| 156 |
+
c12_h3 = 1.0 if (inputs * weights['c12.h3.weight'].flatten()).sum() + weights['c12.h3.bias'].item() >= 0 else 0.0
|
| 157 |
+
|
| 158 |
+
# C'[12] XOR3 (layer 2 output)
|
| 159 |
+
h = torch.tensor([c12_h1, c12_h2, c12_h3])
|
| 160 |
+
c12_out = 1.0 if (h * weights['c12.out.weight'].flatten()).sum() + weights['c12.out.bias'].item() >= 0 else 0.0
|
| 161 |
+
|
| 162 |
+
# Assemble outputs
|
| 163 |
+
outputs = {
|
| 164 |
+
0: c0_out, 1: pass_throughs['c1'], 2: pass_throughs['c2'], 3: pass_throughs['c3'],
|
| 165 |
+
4: pass_throughs['c4'], 5: c5_out, 6: pass_throughs['c6'], 7: pass_throughs['c7'],
|
| 166 |
+
8: pass_throughs['c8'], 9: pass_throughs['c9'], 10: pass_throughs['c10'],
|
| 167 |
+
11: pass_throughs['c11'], 12: c12_out, 13: pass_throughs['c13'],
|
| 168 |
+
14: pass_throughs['c14'], 15: pass_throughs['c15']
|
| 169 |
+
}
|
| 170 |
+
return outputs
|
| 171 |
+
|
| 172 |
+
print("Verifying CRC-16 mag53 threshold circuit...")
|
| 173 |
+
errors = 0
|
| 174 |
+
total = 0
|
| 175 |
+
|
| 176 |
+
for crc in range(0, 65536, 257):
|
| 177 |
+
for d in [0, 1]:
|
| 178 |
+
inputs = torch.tensor([(crc >> i) & 1 for i in range(16)] + [d], dtype=torch.float32)
|
| 179 |
+
outputs = threshold_eval(inputs)
|
| 180 |
+
circuit_result = sum(int(outputs[i]) << i for i in range(16))
|
| 181 |
+
expected = crc16_step_ref(crc, d)
|
| 182 |
+
if circuit_result != expected:
|
| 183 |
+
errors += 1
|
| 184 |
+
if errors <= 5:
|
| 185 |
+
print(f" FAIL: CRC=0x{crc:04X}, D={d} -> got 0x{circuit_result:04X}, expected 0x{expected:04X}")
|
| 186 |
+
total += 1
|
| 187 |
+
|
| 188 |
+
if errors == 0:
|
| 189 |
+
print(f"All {total} sample tests passed!")
|
| 190 |
+
else:
|
| 191 |
+
print(f"FAILED: {errors}/{total} errors")
|
| 192 |
+
|
| 193 |
+
print("\nRunning exhaustive test (131,072 cases)...")
|
| 194 |
+
errors = 0
|
| 195 |
+
for crc in range(65536):
|
| 196 |
+
for d in [0, 1]:
|
| 197 |
+
inputs = torch.tensor([(crc >> i) & 1 for i in range(16)] + [d], dtype=torch.float32)
|
| 198 |
+
outputs = threshold_eval(inputs)
|
| 199 |
+
circuit_result = sum(int(outputs[i]) << i for i in range(16))
|
| 200 |
+
expected = crc16_step_ref(crc, d)
|
| 201 |
+
if circuit_result != expected:
|
| 202 |
+
errors += 1
|
| 203 |
+
|
| 204 |
+
if errors == 0:
|
| 205 |
+
print("Exhaustive test PASSED!")
|
| 206 |
+
else:
|
| 207 |
+
print(f"Exhaustive test FAILED: {errors}/131072 errors")
|
| 208 |
+
|
| 209 |
+
mag = sum(t.abs().sum().item() for t in weights.values())
|
| 210 |
+
params = sum(t.numel() for t in weights.values())
|
| 211 |
+
neurons = len([k for k in weights if '.weight' in k])
|
| 212 |
+
print(f"\nCircuit stats:")
|
| 213 |
+
print(f" Neurons: {neurons}")
|
| 214 |
+
print(f" Parameters: {params}")
|
| 215 |
+
print(f" Magnitude: {mag:.0f}")
|
model.safetensors
ADDED
|
Binary file (4.82 kB). View file
|
|
|