CharlesCNorton commited on
Commit
dd97b24
·
0 Parent(s):

Add 4-to-2 one-hot decoder threshold circuit

Browse files

2 neurons, 1 layer, 10 parameters, magnitude 6.

Files changed (6) hide show
  1. .gitattributes +1 -0
  2. README.md +95 -0
  3. config.json +9 -0
  4. create_safetensors.py +76 -0
  5. model.py +23 -0
  6. model.safetensors +3 -0
.gitattributes ADDED
@@ -0,0 +1 @@
 
 
1
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - encoding
9
+ ---
10
+
11
+ # threshold-onehot-decoder
12
+
13
+ 4-to-2 one-hot decoder. Converts a 4-bit one-hot representation to a 2-bit binary value.
14
+
15
+ ## Function
16
+
17
+ onehot_decode(y3, y2, y1, y0) -> (a1, a0)
18
+
19
+ Input must have exactly one bit set.
20
+
21
+ ## Truth Table
22
+
23
+ | y3 | y2 | y1 | y0 | a1 | a0 | Value |
24
+ |----|----|----|----|----|-----|-------|
25
+ | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
26
+ | 0 | 0 | 1 | 0 | 0 | 1 | 1 |
27
+ | 0 | 1 | 0 | 0 | 1 | 0 | 2 |
28
+ | 1 | 0 | 0 | 0 | 1 | 1 | 3 |
29
+
30
+ ## Architecture
31
+
32
+ Single-layer implementation:
33
+
34
+ ```
35
+ y3 y2 y1 y0
36
+ │ │ │ │
37
+ └────┴────┴────┘
38
+
39
+ ┌────┴────┐
40
+ │ │
41
+ ▼ ▼
42
+ ┌───┐ ┌───┐
43
+ │a1 │ │a0 │ Layer 1
44
+ │OR │ │OR │
45
+ └───┘ └───┘
46
+ │ │
47
+ ▼ ▼
48
+ ```
49
+
50
+ Each output is a single OR gate:
51
+ - a0 = OR(y1, y3): w=[1,0,1,0], b=-1
52
+ - a1 = OR(y2, y3): w=[1,1,0,0], b=-1
53
+
54
+ The decoder recognizes that:
55
+ - Bit 0 of position = 1 for positions 1 and 3
56
+ - Bit 1 of position = 1 for positions 2 and 3
57
+
58
+ ## Parameters
59
+
60
+ | | |
61
+ |---|---|
62
+ | Inputs | 4 |
63
+ | Outputs | 2 |
64
+ | Neurons | 2 |
65
+ | Layers | 1 |
66
+ | Parameters | 10 |
67
+ | Magnitude | 6 |
68
+
69
+ ## Usage
70
+
71
+ ```python
72
+ from safetensors.torch import load_file
73
+ import torch
74
+
75
+ w = load_file('model.safetensors')
76
+
77
+ def decode(y3, y2, y1, y0):
78
+ inp = torch.tensor([float(y3), float(y2), float(y1), float(y0)])
79
+ a0 = int((inp @ w['a0.weight'].T + w['a0.bias'] >= 0).item())
80
+ a1 = int((inp @ w['a1.weight'].T + w['a1.bias'] >= 0).item())
81
+ return a1, a0
82
+
83
+ # decode(0, 1, 0, 0) = (1, 0) # value 2
84
+ ```
85
+
86
+ ## Applications
87
+
88
+ - Priority encoder output processing
89
+ - State machine decoding
90
+ - Memory address reconstruction
91
+ - Neural network output interpretation
92
+
93
+ ## License
94
+
95
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-onehot-decoder",
3
+ "description": "4-to-2 one-hot decoder",
4
+ "inputs": 4,
5
+ "outputs": 2,
6
+ "neurons": 2,
7
+ "layers": 1,
8
+ "parameters": 10
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # One-Hot Decoder (4-to-2)
7
+ # Inputs: y3, y2, y1, y0 (one-hot encoding, exactly one bit set)
8
+ # Outputs: a1, a0 (binary value 0-3)
9
+ #
10
+ # y3 y2 y1 y0 | a1 a0 | value
11
+ # -----------+-------+------
12
+ # 0 0 0 1 | 0 0 | 0
13
+ # 0 0 1 0 | 0 1 | 1
14
+ # 0 1 0 0 | 1 0 | 2
15
+ # 1 0 0 0 | 1 1 | 3
16
+ #
17
+ # Single layer implementation:
18
+ # a0 = OR(y1, y3) = 1 when position 1 or 3
19
+ # a1 = OR(y2, y3) = 1 when position 2 or 3
20
+
21
+ # a0 = OR(y1, y3)
22
+ weights['a0.weight'] = torch.tensor([[1.0, 0.0, 1.0, 0.0]], dtype=torch.float32)
23
+ weights['a0.bias'] = torch.tensor([-1.0], dtype=torch.float32)
24
+
25
+ # a1 = OR(y2, y3)
26
+ weights['a1.weight'] = torch.tensor([[1.0, 1.0, 0.0, 0.0]], dtype=torch.float32)
27
+ weights['a1.bias'] = torch.tensor([-1.0], dtype=torch.float32)
28
+
29
+ save_file(weights, 'model.safetensors')
30
+
31
+ def onehot_decode(y3, y2, y1, y0):
32
+ inp = torch.tensor([float(y3), float(y2), float(y1), float(y0)])
33
+
34
+ a0 = int((inp @ weights['a0.weight'].T + weights['a0.bias'] >= 0).item())
35
+ a1 = int((inp @ weights['a1.weight'].T + weights['a1.bias'] >= 0).item())
36
+
37
+ return a1, a0
38
+
39
+ def reference_decode(y3, y2, y1, y0):
40
+ if y0 == 1:
41
+ return 0, 0
42
+ if y1 == 1:
43
+ return 0, 1
44
+ if y2 == 1:
45
+ return 1, 0
46
+ if y3 == 1:
47
+ return 1, 1
48
+ return 0, 0
49
+
50
+ print("Verifying One-Hot Decoder (4-to-2)...")
51
+ errors = 0
52
+ test_cases = [(0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)]
53
+ for y3, y2, y1, y0 in test_cases:
54
+ result = onehot_decode(y3, y2, y1, y0)
55
+ expected = reference_decode(y3, y2, y1, y0)
56
+ if result != expected:
57
+ errors += 1
58
+ print(f"ERROR: ({y3},{y2},{y1},{y0}) -> {result}, expected {expected}")
59
+
60
+ if errors == 0:
61
+ print("All 4 test cases passed!")
62
+ else:
63
+ print(f"FAILED: {errors} errors")
64
+
65
+ print("\nTruth Table:")
66
+ print("y3 y2 y1 y0 | a1 a0 | value")
67
+ print("-" * 30)
68
+ for y3, y2, y1, y0 in test_cases:
69
+ a1, a0 = onehot_decode(y3, y2, y1, y0)
70
+ val = a1 * 2 + a0
71
+ print(f" {y3} {y2} {y1} {y0} | {a1} {a0} | {val}")
72
+
73
+ mag = sum(t.abs().sum().item() for t in weights.values())
74
+ print(f"\nMagnitude: {mag:.0f}")
75
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
76
+ print(f"Neurons: {len([k for k in weights.keys() if 'weight' in k])}")
model.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 onehot_decode(y3, y2, y1, y0, weights):
8
+ """Convert 4-bit one-hot encoding to 2-bit binary."""
9
+ inp = torch.tensor([float(y3), float(y2), float(y1), float(y0)])
10
+
11
+ a0 = int((inp @ weights['a0.weight'].T + weights['a0.bias'] >= 0).item())
12
+ a1 = int((inp @ weights['a1.weight'].T + weights['a1.bias'] >= 0).item())
13
+
14
+ return a1, a0
15
+
16
+ if __name__ == '__main__':
17
+ w = load_model()
18
+ print('One-Hot Decoder (4-to-2):')
19
+ test_cases = [(0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)]
20
+ for y3, y2, y1, y0 in test_cases:
21
+ a1, a0 = onehot_decode(y3, y2, y1, y0, w)
22
+ val = a1 * 2 + a0
23
+ print(f' {y3}{y2}{y1}{y0} -> {a1}{a0} = {val}')
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:19a17bf0ef03de9e187b2d75b28f633d5544bf93ef0d4b28bfea0952a64eedde
3
+ size 304