Upload folder using huggingface_hub
Browse files- .gitattributes +34 -0
- README.md +91 -91
- config.json +9 -9
- create_safetensors.py +140 -140
- model.py +21 -21
.gitattributes
CHANGED
|
@@ -1 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
*.safetensors 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
|
@@ -1,91 +1,91 @@
|
|
| 1 |
-
---
|
| 2 |
-
license: mit
|
| 3 |
-
tags:
|
| 4 |
-
- pytorch
|
| 5 |
-
- safetensors
|
| 6 |
-
- threshold-logic
|
| 7 |
-
- neuromorphic
|
| 8 |
-
- error-detection
|
| 9 |
-
- crc
|
| 10 |
-
---
|
| 11 |
-
|
| 12 |
-
# threshold-crc4
|
| 13 |
-
|
| 14 |
-
CRC-4 generator using polynomial x^4 + x + 1 (CRC-4-ITU).
|
| 15 |
-
|
| 16 |
-
## Function
|
| 17 |
-
|
| 18 |
-
crc4(d3, d2, d1, d0) -> (crc3, crc2, crc1, crc0)
|
| 19 |
-
|
| 20 |
-
Computes 4-bit CRC for 4-bit input data.
|
| 21 |
-
|
| 22 |
-
## Polynomial
|
| 23 |
-
|
| 24 |
-
G(x) = x^4 + x + 1 = 10011 (binary)
|
| 25 |
-
|
| 26 |
-
This is the ITU-T standard CRC-4 polynomial.
|
| 27 |
-
|
| 28 |
-
## Parallel CRC Equations
|
| 29 |
-
|
| 30 |
-
For 4-bit input, the CRC bits are:
|
| 31 |
-
- crc0 = d3 XOR d0
|
| 32 |
-
- crc1 = d2 XOR d1 XOR d0
|
| 33 |
-
- crc2 = d3 XOR d1
|
| 34 |
-
- crc3 = d3 XOR d2
|
| 35 |
-
|
| 36 |
-
## Truth Table (selected)
|
| 37 |
-
|
| 38 |
-
| Data | CRC |
|
| 39 |
-
|------|-----|
|
| 40 |
-
| 0000 | 0000 |
|
| 41 |
-
| 0001 | 0011 |
|
| 42 |
-
| 1000 | 1101 |
|
| 43 |
-
| 1111 | 0010 |
|
| 44 |
-
|
| 45 |
-
## Architecture
|
| 46 |
-
|
| 47 |
-
Each CRC bit is computed using XOR gates:
|
| 48 |
-
|
| 49 |
-
```
|
| 50 |
-
d3 d2 d1 d0
|
| 51 |
-
│ │ │ │
|
| 52 |
-
├──┼──┼──┼──► XOR ──► crc0 (d3^d0)
|
| 53 |
-
│ │ │ │
|
| 54 |
-
│ ├──┼──┼──► XOR ──► crc3 (d3^d2)
|
| 55 |
-
│ │ │ │
|
| 56 |
-
├──┼──┼──┼──► XOR ──► crc2 (d3^d1)
|
| 57 |
-
│ │ │ │
|
| 58 |
-
│ └──┴──┴──► XOR3 ─► crc1 (d2^d1^d0)
|
| 59 |
-
```
|
| 60 |
-
|
| 61 |
-
## Parameters
|
| 62 |
-
|
| 63 |
-
| | |
|
| 64 |
-
|---|---|
|
| 65 |
-
| Inputs | 4 |
|
| 66 |
-
| Outputs | 4 |
|
| 67 |
-
| Neurons | 15 |
|
| 68 |
-
| Layers | 4 |
|
| 69 |
-
| Parameters | 61 |
|
| 70 |
-
| Magnitude | 50 |
|
| 71 |
-
|
| 72 |
-
## CRC Properties
|
| 73 |
-
|
| 74 |
-
- Detects all single-bit errors
|
| 75 |
-
- Detects all odd numbers of bit errors
|
| 76 |
-
- Detects burst errors up to length 4
|
| 77 |
-
|
| 78 |
-
## Usage
|
| 79 |
-
|
| 80 |
-
```python
|
| 81 |
-
from safetensors.torch import load_file
|
| 82 |
-
|
| 83 |
-
w = load_file('model.safetensors')
|
| 84 |
-
|
| 85 |
-
# Append CRC to data for transmission
|
| 86 |
-
# Receiver recomputes CRC; if non-zero, error detected
|
| 87 |
-
```
|
| 88 |
-
|
| 89 |
-
## License
|
| 90 |
-
|
| 91 |
-
MIT
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
tags:
|
| 4 |
+
- pytorch
|
| 5 |
+
- safetensors
|
| 6 |
+
- threshold-logic
|
| 7 |
+
- neuromorphic
|
| 8 |
+
- error-detection
|
| 9 |
+
- crc
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# threshold-crc4
|
| 13 |
+
|
| 14 |
+
CRC-4 generator using polynomial x^4 + x + 1 (CRC-4-ITU).
|
| 15 |
+
|
| 16 |
+
## Function
|
| 17 |
+
|
| 18 |
+
crc4(d3, d2, d1, d0) -> (crc3, crc2, crc1, crc0)
|
| 19 |
+
|
| 20 |
+
Computes 4-bit CRC for 4-bit input data.
|
| 21 |
+
|
| 22 |
+
## Polynomial
|
| 23 |
+
|
| 24 |
+
G(x) = x^4 + x + 1 = 10011 (binary)
|
| 25 |
+
|
| 26 |
+
This is the ITU-T standard CRC-4 polynomial.
|
| 27 |
+
|
| 28 |
+
## Parallel CRC Equations
|
| 29 |
+
|
| 30 |
+
For 4-bit input, the CRC bits are:
|
| 31 |
+
- crc0 = d3 XOR d0
|
| 32 |
+
- crc1 = d2 XOR d1 XOR d0
|
| 33 |
+
- crc2 = d3 XOR d1
|
| 34 |
+
- crc3 = d3 XOR d2
|
| 35 |
+
|
| 36 |
+
## Truth Table (selected)
|
| 37 |
+
|
| 38 |
+
| Data | CRC |
|
| 39 |
+
|------|-----|
|
| 40 |
+
| 0000 | 0000 |
|
| 41 |
+
| 0001 | 0011 |
|
| 42 |
+
| 1000 | 1101 |
|
| 43 |
+
| 1111 | 0010 |
|
| 44 |
+
|
| 45 |
+
## Architecture
|
| 46 |
+
|
| 47 |
+
Each CRC bit is computed using XOR gates:
|
| 48 |
+
|
| 49 |
+
```
|
| 50 |
+
d3 d2 d1 d0
|
| 51 |
+
│ │ │ │
|
| 52 |
+
├──┼──┼──┼──► XOR ──► crc0 (d3^d0)
|
| 53 |
+
│ │ │ │
|
| 54 |
+
│ ├──┼──┼──► XOR ──► crc3 (d3^d2)
|
| 55 |
+
│ │ │ │
|
| 56 |
+
├──┼──┼──┼──► XOR ──► crc2 (d3^d1)
|
| 57 |
+
│ │ │ │
|
| 58 |
+
│ └──┴──┴──► XOR3 ─► crc1 (d2^d1^d0)
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
## Parameters
|
| 62 |
+
|
| 63 |
+
| | |
|
| 64 |
+
|---|---|
|
| 65 |
+
| Inputs | 4 |
|
| 66 |
+
| Outputs | 4 |
|
| 67 |
+
| Neurons | 15 |
|
| 68 |
+
| Layers | 4 |
|
| 69 |
+
| Parameters | 61 |
|
| 70 |
+
| Magnitude | 50 |
|
| 71 |
+
|
| 72 |
+
## CRC Properties
|
| 73 |
+
|
| 74 |
+
- Detects all single-bit errors
|
| 75 |
+
- Detects all odd numbers of bit errors
|
| 76 |
+
- Detects burst errors up to length 4
|
| 77 |
+
|
| 78 |
+
## Usage
|
| 79 |
+
|
| 80 |
+
```python
|
| 81 |
+
from safetensors.torch import load_file
|
| 82 |
+
|
| 83 |
+
w = load_file('model.safetensors')
|
| 84 |
+
|
| 85 |
+
# Append CRC to data for transmission
|
| 86 |
+
# Receiver recomputes CRC; if non-zero, error detected
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
## License
|
| 90 |
+
|
| 91 |
+
MIT
|
config.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
-
{
|
| 2 |
-
"name": "threshold-crc4",
|
| 3 |
-
"description": "CRC-4 generator (polynomial x^4+x+1)",
|
| 4 |
-
"inputs": 4,
|
| 5 |
-
"outputs": 4,
|
| 6 |
-
"neurons": 15,
|
| 7 |
-
"layers": 4,
|
| 8 |
-
"parameters": 61
|
| 9 |
-
}
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "threshold-crc4",
|
| 3 |
+
"description": "CRC-4 generator (polynomial x^4+x+1)",
|
| 4 |
+
"inputs": 4,
|
| 5 |
+
"outputs": 4,
|
| 6 |
+
"neurons": 15,
|
| 7 |
+
"layers": 4,
|
| 8 |
+
"parameters": 61
|
| 9 |
+
}
|
create_safetensors.py
CHANGED
|
@@ -1,140 +1,140 @@
|
|
| 1 |
-
import torch
|
| 2 |
-
from safetensors.torch import save_file
|
| 3 |
-
|
| 4 |
-
weights = {}
|
| 5 |
-
|
| 6 |
-
# CRC-4 Generator
|
| 7 |
-
# Polynomial: x^4 + x + 1 (CRC-4-ITU, binary 10011)
|
| 8 |
-
# Inputs: d3, d2, d1, d0 (4 data bits)
|
| 9 |
-
# Outputs: crc3, crc2, crc1, crc0 (4 CRC bits)
|
| 10 |
-
#
|
| 11 |
-
# Derived parallel CRC equations (starting from CRC=0):
|
| 12 |
-
# crc0 = d3 XOR d0
|
| 13 |
-
# crc1 = d2 XOR d1 XOR d0
|
| 14 |
-
# crc2 = d3 XOR d1
|
| 15 |
-
# crc3 = d3 XOR d2
|
| 16 |
-
#
|
| 17 |
-
# Each XOR is implemented as AND(OR, NAND)
|
| 18 |
-
|
| 19 |
-
def add_xor2_weights(prefix, idx_a, idx_b, total_inputs):
|
| 20 |
-
"""Add weights for XOR(input[a], input[b])."""
|
| 21 |
-
w_or = [0.0] * total_inputs
|
| 22 |
-
w_or[idx_a] = 1.0
|
| 23 |
-
w_or[idx_b] = 1.0
|
| 24 |
-
weights[f'{prefix}.or.weight'] = torch.tensor([w_or], dtype=torch.float32)
|
| 25 |
-
weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
| 26 |
-
|
| 27 |
-
w_nand = [0.0] * total_inputs
|
| 28 |
-
w_nand[idx_a] = -1.0
|
| 29 |
-
w_nand[idx_b] = -1.0
|
| 30 |
-
weights[f'{prefix}.nand.weight'] = torch.tensor([w_nand], dtype=torch.float32)
|
| 31 |
-
weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
| 32 |
-
|
| 33 |
-
weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 34 |
-
weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
| 35 |
-
|
| 36 |
-
def add_xor2_stage_weights(prefix):
|
| 37 |
-
"""Add weights for XOR of two intermediate signals."""
|
| 38 |
-
weights[f'{prefix}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 39 |
-
weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
| 40 |
-
weights[f'{prefix}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
|
| 41 |
-
weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
| 42 |
-
weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 43 |
-
weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
| 44 |
-
|
| 45 |
-
# Input indices: d3=0, d2=1, d1=2, d0=3
|
| 46 |
-
|
| 47 |
-
# crc0 = d3 XOR d0 (indices 0, 3)
|
| 48 |
-
add_xor2_weights('crc0', 0, 3, 4)
|
| 49 |
-
|
| 50 |
-
# crc1 = d2 XOR d1 XOR d0 = XOR(XOR(d2, d1), d0) (indices 1, 2, 3)
|
| 51 |
-
add_xor2_weights('crc1.x12', 1, 2, 4) # d2 XOR d1
|
| 52 |
-
add_xor2_stage_weights('crc1.final') # (d2^d1) XOR d0
|
| 53 |
-
|
| 54 |
-
# crc2 = d3 XOR d1 (indices 0, 2)
|
| 55 |
-
add_xor2_weights('crc2', 0, 2, 4)
|
| 56 |
-
|
| 57 |
-
# crc3 = d3 XOR d2 (indices 0, 1)
|
| 58 |
-
add_xor2_weights('crc3', 0, 1, 4)
|
| 59 |
-
|
| 60 |
-
save_file(weights, 'model.safetensors')
|
| 61 |
-
|
| 62 |
-
def xor2_eval(a, b, w, or_w, or_b, nand_w, nand_b, and_w, and_b):
|
| 63 |
-
"""Evaluate XOR using threshold gates."""
|
| 64 |
-
inp = torch.tensor([float(a), float(b)])
|
| 65 |
-
or_out = int((inp @ or_w.T + or_b >= 0).item())
|
| 66 |
-
nand_out = int((inp @ nand_w.T + nand_b >= 0).item())
|
| 67 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 68 |
-
return int((l1 @ and_w.T + and_b >= 0).item())
|
| 69 |
-
|
| 70 |
-
def crc4(d3, d2, d1, d0):
|
| 71 |
-
inp = torch.tensor([float(d3), float(d2), float(d1), float(d0)])
|
| 72 |
-
|
| 73 |
-
# crc0 = d3 XOR d0
|
| 74 |
-
or_out = int((inp @ weights['crc0.or.weight'].T + weights['crc0.or.bias'] >= 0).item())
|
| 75 |
-
nand_out = int((inp @ weights['crc0.nand.weight'].T + weights['crc0.nand.bias'] >= 0).item())
|
| 76 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 77 |
-
crc0 = int((l1 @ weights['crc0.and.weight'].T + weights['crc0.and.bias'] >= 0).item())
|
| 78 |
-
|
| 79 |
-
# crc1 = XOR(XOR(d2, d1), d0)
|
| 80 |
-
or_out = int((inp @ weights['crc1.x12.or.weight'].T + weights['crc1.x12.or.bias'] >= 0).item())
|
| 81 |
-
nand_out = int((inp @ weights['crc1.x12.nand.weight'].T + weights['crc1.x12.nand.bias'] >= 0).item())
|
| 82 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 83 |
-
x12 = int((l1 @ weights['crc1.x12.and.weight'].T + weights['crc1.x12.and.bias'] >= 0).item())
|
| 84 |
-
|
| 85 |
-
inp2 = torch.tensor([float(x12), float(d0)])
|
| 86 |
-
or_out = int((inp2 @ weights['crc1.final.or.weight'].T + weights['crc1.final.or.bias'] >= 0).item())
|
| 87 |
-
nand_out = int((inp2 @ weights['crc1.final.nand.weight'].T + weights['crc1.final.nand.bias'] >= 0).item())
|
| 88 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 89 |
-
crc1 = int((l1 @ weights['crc1.final.and.weight'].T + weights['crc1.final.and.bias'] >= 0).item())
|
| 90 |
-
|
| 91 |
-
# crc2 = d3 XOR d1
|
| 92 |
-
or_out = int((inp @ weights['crc2.or.weight'].T + weights['crc2.or.bias'] >= 0).item())
|
| 93 |
-
nand_out = int((inp @ weights['crc2.nand.weight'].T + weights['crc2.nand.bias'] >= 0).item())
|
| 94 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 95 |
-
crc2 = int((l1 @ weights['crc2.and.weight'].T + weights['crc2.and.bias'] >= 0).item())
|
| 96 |
-
|
| 97 |
-
# crc3 = d3 XOR d2
|
| 98 |
-
or_out = int((inp @ weights['crc3.or.weight'].T + weights['crc3.or.bias'] >= 0).item())
|
| 99 |
-
nand_out = int((inp @ weights['crc3.nand.weight'].T + weights['crc3.nand.bias'] >= 0).item())
|
| 100 |
-
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 101 |
-
crc3 = int((l1 @ weights['crc3.and.weight'].T + weights['crc3.and.bias'] >= 0).item())
|
| 102 |
-
|
| 103 |
-
return crc3, crc2, crc1, crc0
|
| 104 |
-
|
| 105 |
-
def crc4_ref(d3, d2, d1, d0):
|
| 106 |
-
"""Reference CRC-4 computation."""
|
| 107 |
-
crc0 = d3 ^ d0
|
| 108 |
-
crc1 = d2 ^ d1 ^ d0
|
| 109 |
-
crc2 = d3 ^ d1
|
| 110 |
-
crc3 = d3 ^ d2
|
| 111 |
-
return crc3, crc2, crc1, crc0
|
| 112 |
-
|
| 113 |
-
print("Verifying CRC-4 Generator (polynomial x^4+x+1)...")
|
| 114 |
-
errors = 0
|
| 115 |
-
for i in range(16):
|
| 116 |
-
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 117 |
-
result = crc4(d3, d2, d1, d0)
|
| 118 |
-
expected = crc4_ref(d3, d2, d1, d0)
|
| 119 |
-
if result != expected:
|
| 120 |
-
errors += 1
|
| 121 |
-
print(f"ERROR: {d3}{d2}{d1}{d0} -> {result}, expected {expected}")
|
| 122 |
-
|
| 123 |
-
if errors == 0:
|
| 124 |
-
print("All 16 test cases passed!")
|
| 125 |
-
else:
|
| 126 |
-
print(f"FAILED: {errors} errors")
|
| 127 |
-
|
| 128 |
-
print("\nTruth Table:")
|
| 129 |
-
print("Data | CRC")
|
| 130 |
-
print("d3d2d1d0 | c3c2c1c0")
|
| 131 |
-
print("-" * 22)
|
| 132 |
-
for i in range(16):
|
| 133 |
-
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 134 |
-
c3, c2, c1, c0 = crc4(d3, d2, d1, d0)
|
| 135 |
-
print(f" {d3} {d2} {d1} {d0} | {c3} {c2} {c1} {c0}")
|
| 136 |
-
|
| 137 |
-
mag = sum(t.abs().sum().item() for t in weights.values())
|
| 138 |
-
print(f"\nMagnitude: {mag:.0f}")
|
| 139 |
-
print(f"Parameters: {sum(t.numel() for t in weights.values())}")
|
| 140 |
-
print(f"Neurons: {len([k for k in weights.keys() if 'weight' in k])}")
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from safetensors.torch import save_file
|
| 3 |
+
|
| 4 |
+
weights = {}
|
| 5 |
+
|
| 6 |
+
# CRC-4 Generator
|
| 7 |
+
# Polynomial: x^4 + x + 1 (CRC-4-ITU, binary 10011)
|
| 8 |
+
# Inputs: d3, d2, d1, d0 (4 data bits)
|
| 9 |
+
# Outputs: crc3, crc2, crc1, crc0 (4 CRC bits)
|
| 10 |
+
#
|
| 11 |
+
# Derived parallel CRC equations (starting from CRC=0):
|
| 12 |
+
# crc0 = d3 XOR d0
|
| 13 |
+
# crc1 = d2 XOR d1 XOR d0
|
| 14 |
+
# crc2 = d3 XOR d1
|
| 15 |
+
# crc3 = d3 XOR d2
|
| 16 |
+
#
|
| 17 |
+
# Each XOR is implemented as AND(OR, NAND)
|
| 18 |
+
|
| 19 |
+
def add_xor2_weights(prefix, idx_a, idx_b, total_inputs):
|
| 20 |
+
"""Add weights for XOR(input[a], input[b])."""
|
| 21 |
+
w_or = [0.0] * total_inputs
|
| 22 |
+
w_or[idx_a] = 1.0
|
| 23 |
+
w_or[idx_b] = 1.0
|
| 24 |
+
weights[f'{prefix}.or.weight'] = torch.tensor([w_or], dtype=torch.float32)
|
| 25 |
+
weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
| 26 |
+
|
| 27 |
+
w_nand = [0.0] * total_inputs
|
| 28 |
+
w_nand[idx_a] = -1.0
|
| 29 |
+
w_nand[idx_b] = -1.0
|
| 30 |
+
weights[f'{prefix}.nand.weight'] = torch.tensor([w_nand], dtype=torch.float32)
|
| 31 |
+
weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
| 32 |
+
|
| 33 |
+
weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 34 |
+
weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
| 35 |
+
|
| 36 |
+
def add_xor2_stage_weights(prefix):
|
| 37 |
+
"""Add weights for XOR of two intermediate signals."""
|
| 38 |
+
weights[f'{prefix}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 39 |
+
weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
|
| 40 |
+
weights[f'{prefix}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
|
| 41 |
+
weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
|
| 42 |
+
weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
|
| 43 |
+
weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
|
| 44 |
+
|
| 45 |
+
# Input indices: d3=0, d2=1, d1=2, d0=3
|
| 46 |
+
|
| 47 |
+
# crc0 = d3 XOR d0 (indices 0, 3)
|
| 48 |
+
add_xor2_weights('crc0', 0, 3, 4)
|
| 49 |
+
|
| 50 |
+
# crc1 = d2 XOR d1 XOR d0 = XOR(XOR(d2, d1), d0) (indices 1, 2, 3)
|
| 51 |
+
add_xor2_weights('crc1.x12', 1, 2, 4) # d2 XOR d1
|
| 52 |
+
add_xor2_stage_weights('crc1.final') # (d2^d1) XOR d0
|
| 53 |
+
|
| 54 |
+
# crc2 = d3 XOR d1 (indices 0, 2)
|
| 55 |
+
add_xor2_weights('crc2', 0, 2, 4)
|
| 56 |
+
|
| 57 |
+
# crc3 = d3 XOR d2 (indices 0, 1)
|
| 58 |
+
add_xor2_weights('crc3', 0, 1, 4)
|
| 59 |
+
|
| 60 |
+
save_file(weights, 'model.safetensors')
|
| 61 |
+
|
| 62 |
+
def xor2_eval(a, b, w, or_w, or_b, nand_w, nand_b, and_w, and_b):
|
| 63 |
+
"""Evaluate XOR using threshold gates."""
|
| 64 |
+
inp = torch.tensor([float(a), float(b)])
|
| 65 |
+
or_out = int((inp @ or_w.T + or_b >= 0).item())
|
| 66 |
+
nand_out = int((inp @ nand_w.T + nand_b >= 0).item())
|
| 67 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 68 |
+
return int((l1 @ and_w.T + and_b >= 0).item())
|
| 69 |
+
|
| 70 |
+
def crc4(d3, d2, d1, d0):
|
| 71 |
+
inp = torch.tensor([float(d3), float(d2), float(d1), float(d0)])
|
| 72 |
+
|
| 73 |
+
# crc0 = d3 XOR d0
|
| 74 |
+
or_out = int((inp @ weights['crc0.or.weight'].T + weights['crc0.or.bias'] >= 0).item())
|
| 75 |
+
nand_out = int((inp @ weights['crc0.nand.weight'].T + weights['crc0.nand.bias'] >= 0).item())
|
| 76 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 77 |
+
crc0 = int((l1 @ weights['crc0.and.weight'].T + weights['crc0.and.bias'] >= 0).item())
|
| 78 |
+
|
| 79 |
+
# crc1 = XOR(XOR(d2, d1), d0)
|
| 80 |
+
or_out = int((inp @ weights['crc1.x12.or.weight'].T + weights['crc1.x12.or.bias'] >= 0).item())
|
| 81 |
+
nand_out = int((inp @ weights['crc1.x12.nand.weight'].T + weights['crc1.x12.nand.bias'] >= 0).item())
|
| 82 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 83 |
+
x12 = int((l1 @ weights['crc1.x12.and.weight'].T + weights['crc1.x12.and.bias'] >= 0).item())
|
| 84 |
+
|
| 85 |
+
inp2 = torch.tensor([float(x12), float(d0)])
|
| 86 |
+
or_out = int((inp2 @ weights['crc1.final.or.weight'].T + weights['crc1.final.or.bias'] >= 0).item())
|
| 87 |
+
nand_out = int((inp2 @ weights['crc1.final.nand.weight'].T + weights['crc1.final.nand.bias'] >= 0).item())
|
| 88 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 89 |
+
crc1 = int((l1 @ weights['crc1.final.and.weight'].T + weights['crc1.final.and.bias'] >= 0).item())
|
| 90 |
+
|
| 91 |
+
# crc2 = d3 XOR d1
|
| 92 |
+
or_out = int((inp @ weights['crc2.or.weight'].T + weights['crc2.or.bias'] >= 0).item())
|
| 93 |
+
nand_out = int((inp @ weights['crc2.nand.weight'].T + weights['crc2.nand.bias'] >= 0).item())
|
| 94 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 95 |
+
crc2 = int((l1 @ weights['crc2.and.weight'].T + weights['crc2.and.bias'] >= 0).item())
|
| 96 |
+
|
| 97 |
+
# crc3 = d3 XOR d2
|
| 98 |
+
or_out = int((inp @ weights['crc3.or.weight'].T + weights['crc3.or.bias'] >= 0).item())
|
| 99 |
+
nand_out = int((inp @ weights['crc3.nand.weight'].T + weights['crc3.nand.bias'] >= 0).item())
|
| 100 |
+
l1 = torch.tensor([float(or_out), float(nand_out)])
|
| 101 |
+
crc3 = int((l1 @ weights['crc3.and.weight'].T + weights['crc3.and.bias'] >= 0).item())
|
| 102 |
+
|
| 103 |
+
return crc3, crc2, crc1, crc0
|
| 104 |
+
|
| 105 |
+
def crc4_ref(d3, d2, d1, d0):
|
| 106 |
+
"""Reference CRC-4 computation."""
|
| 107 |
+
crc0 = d3 ^ d0
|
| 108 |
+
crc1 = d2 ^ d1 ^ d0
|
| 109 |
+
crc2 = d3 ^ d1
|
| 110 |
+
crc3 = d3 ^ d2
|
| 111 |
+
return crc3, crc2, crc1, crc0
|
| 112 |
+
|
| 113 |
+
print("Verifying CRC-4 Generator (polynomial x^4+x+1)...")
|
| 114 |
+
errors = 0
|
| 115 |
+
for i in range(16):
|
| 116 |
+
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 117 |
+
result = crc4(d3, d2, d1, d0)
|
| 118 |
+
expected = crc4_ref(d3, d2, d1, d0)
|
| 119 |
+
if result != expected:
|
| 120 |
+
errors += 1
|
| 121 |
+
print(f"ERROR: {d3}{d2}{d1}{d0} -> {result}, expected {expected}")
|
| 122 |
+
|
| 123 |
+
if errors == 0:
|
| 124 |
+
print("All 16 test cases passed!")
|
| 125 |
+
else:
|
| 126 |
+
print(f"FAILED: {errors} errors")
|
| 127 |
+
|
| 128 |
+
print("\nTruth Table:")
|
| 129 |
+
print("Data | CRC")
|
| 130 |
+
print("d3d2d1d0 | c3c2c1c0")
|
| 131 |
+
print("-" * 22)
|
| 132 |
+
for i in range(16):
|
| 133 |
+
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 134 |
+
c3, c2, c1, c0 = crc4(d3, d2, d1, d0)
|
| 135 |
+
print(f" {d3} {d2} {d1} {d0} | {c3} {c2} {c1} {c0}")
|
| 136 |
+
|
| 137 |
+
mag = sum(t.abs().sum().item() for t in weights.values())
|
| 138 |
+
print(f"\nMagnitude: {mag:.0f}")
|
| 139 |
+
print(f"Parameters: {sum(t.numel() for t in weights.values())}")
|
| 140 |
+
print(f"Neurons: {len([k for k in weights.keys() if 'weight' in k])}")
|
model.py
CHANGED
|
@@ -1,21 +1,21 @@
|
|
| 1 |
-
import torch
|
| 2 |
-
from safetensors.torch import load_file
|
| 3 |
-
|
| 4 |
-
def load_model(path='model.safetensors'):
|
| 5 |
-
return load_file(path)
|
| 6 |
-
|
| 7 |
-
def crc4_ref(d3, d2, d1, d0):
|
| 8 |
-
"""CRC-4 with polynomial x^4+x+1."""
|
| 9 |
-
crc0 = d3 ^ d0
|
| 10 |
-
crc1 = d2 ^ d1 ^ d0
|
| 11 |
-
crc2 = d3 ^ d1
|
| 12 |
-
crc3 = d3 ^ d2
|
| 13 |
-
return crc3, crc2, crc1, crc0
|
| 14 |
-
|
| 15 |
-
if __name__ == '__main__':
|
| 16 |
-
print('CRC-4 Generator (polynomial x^4+x+1)')
|
| 17 |
-
print('Data -> CRC')
|
| 18 |
-
for i in range(16):
|
| 19 |
-
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 20 |
-
c3, c2, c1, c0 = crc4_ref(d3, d2, d1, d0)
|
| 21 |
-
print(f' {d3}{d2}{d1}{d0} -> {c3}{c2}{c1}{c0}')
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from safetensors.torch import load_file
|
| 3 |
+
|
| 4 |
+
def load_model(path='model.safetensors'):
|
| 5 |
+
return load_file(path)
|
| 6 |
+
|
| 7 |
+
def crc4_ref(d3, d2, d1, d0):
|
| 8 |
+
"""CRC-4 with polynomial x^4+x+1."""
|
| 9 |
+
crc0 = d3 ^ d0
|
| 10 |
+
crc1 = d2 ^ d1 ^ d0
|
| 11 |
+
crc2 = d3 ^ d1
|
| 12 |
+
crc3 = d3 ^ d2
|
| 13 |
+
return crc3, crc2, crc1, crc0
|
| 14 |
+
|
| 15 |
+
if __name__ == '__main__':
|
| 16 |
+
print('CRC-4 Generator (polynomial x^4+x+1)')
|
| 17 |
+
print('Data -> CRC')
|
| 18 |
+
for i in range(16):
|
| 19 |
+
d3, d2, d1, d0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
|
| 20 |
+
c3, c2, c1, c0 = crc4_ref(d3, d2, d1, d0)
|
| 21 |
+
print(f' {d3}{d2}{d1}{d0} -> {c3}{c2}{c1}{c0}')
|