CharlesCNorton commited on
Commit
76be67c
·
0 Parent(s):

4-bit incrementer, magnitude 41

Browse files
Files changed (5) hide show
  1. README.md +63 -0
  2. config.json +9 -0
  3. create_safetensors.py +102 -0
  4. model.py +39 -0
  5. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ ---
9
+
10
+ # threshold-incrementer4bit
11
+
12
+ 4-bit incrementer. Adds 1 to input (modulo 16).
13
+
14
+ ## Function
15
+
16
+ incrementer4bit(a3, a2, a1, a0) = (input + 1) mod 16
17
+
18
+ ## Truth Table (selected rows)
19
+
20
+ | Input | Decimal | Output | Decimal |
21
+ |-------|---------|--------|---------|
22
+ | 0000 | 0 | 0001 | 1 |
23
+ | 0001 | 1 | 0010 | 2 |
24
+ | 0111 | 7 | 1000 | 8 |
25
+ | 1111 | 15 | 0000 | 0 |
26
+
27
+ ## Architecture
28
+
29
+ ```
30
+ y0 = NOT(a0)
31
+ y1 = a1 XOR a0
32
+ y2 = a2 XOR (a1 AND a0)
33
+ y3 = a3 XOR (a2 AND a1 AND a0)
34
+ ```
35
+
36
+ Layer 1: Compute NOT(a0), carries (c2, c3), and XOR components for y1
37
+ Layer 2: Compute y1, XOR components for y2 and y3
38
+ Layer 3: Final AND gates for y2 and y3
39
+
40
+ ## Parameters
41
+
42
+ | | |
43
+ |---|---|
44
+ | Inputs | 4 |
45
+ | Outputs | 4 |
46
+ | Neurons | 12 |
47
+ | Layers | 3 |
48
+ | Parameters | 52 |
49
+ | Magnitude | 41 |
50
+
51
+ ## Usage
52
+
53
+ ```python
54
+ from safetensors.torch import load_file
55
+ # See model.py for full implementation
56
+
57
+ # 7 + 1 = 8
58
+ # incrementer4(0, 1, 1, 1) = [1, 0, 0, 0]
59
+ ```
60
+
61
+ ## License
62
+
63
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-incrementer4bit",
3
+ "description": "4-bit incrementer (adds 1)",
4
+ "inputs": 4,
5
+ "outputs": 4,
6
+ "neurons": 12,
7
+ "layers": 3,
8
+ "parameters": 52
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # Input: [a3, a2, a1, a0]
7
+ # Output: input + 1 (mod 16)
8
+ # y0 = NOT(a0)
9
+ # y1 = a1 XOR a0
10
+ # y2 = a2 XOR (a1 AND a0)
11
+ # y3 = a3 XOR (a2 AND a1 AND a0)
12
+
13
+ # Layer 1: NOT, carries, and XOR components
14
+ # y0 = NOT(a0)
15
+ weights['y0.weight'] = torch.tensor([[0.0, 0.0, 0.0, -1.0]], dtype=torch.float32)
16
+ weights['y0.bias'] = torch.tensor([0.0], dtype=torch.float32)
17
+
18
+ # c2 = a1 AND a0
19
+ weights['c2.weight'] = torch.tensor([[0.0, 0.0, 1.0, 1.0]], dtype=torch.float32)
20
+ weights['c2.bias'] = torch.tensor([-2.0], dtype=torch.float32)
21
+
22
+ # c3 = a2 AND a1 AND a0
23
+ weights['c3.weight'] = torch.tensor([[0.0, 1.0, 1.0, 1.0]], dtype=torch.float32)
24
+ weights['c3.bias'] = torch.tensor([-3.0], dtype=torch.float32)
25
+
26
+ # XOR(a1, a0) components
27
+ weights['y1_or.weight'] = torch.tensor([[0.0, 0.0, 1.0, 1.0]], dtype=torch.float32)
28
+ weights['y1_or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
29
+ weights['y1_nand.weight'] = torch.tensor([[0.0, 0.0, -1.0, -1.0]], dtype=torch.float32)
30
+ weights['y1_nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
31
+
32
+ # Layer 2: y1 AND, XOR(a2,c2) and XOR(a3,c3) components
33
+ # Input order for layer 2: [a3, a2, c2, c3, y1_or, y1_nand]
34
+ # y1 = AND(y1_or, y1_nand)
35
+ weights['y1.weight'] = torch.tensor([[0.0, 0.0, 0.0, 0.0, 1.0, 1.0]], dtype=torch.float32)
36
+ weights['y1.bias'] = torch.tensor([-2.0], dtype=torch.float32)
37
+
38
+ # y2 = XOR(a2, c2): OR(a2, c2) and NAND(a2, c2)
39
+ weights['y2_or.weight'] = torch.tensor([[0.0, 1.0, 1.0, 0.0, 0.0, 0.0]], dtype=torch.float32)
40
+ weights['y2_or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
41
+ weights['y2_nand.weight'] = torch.tensor([[0.0, -1.0, -1.0, 0.0, 0.0, 0.0]], dtype=torch.float32)
42
+ weights['y2_nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
43
+
44
+ # y3 = XOR(a3, c3): OR(a3, c3) and NAND(a3, c3)
45
+ weights['y3_or.weight'] = torch.tensor([[1.0, 0.0, 0.0, 1.0, 0.0, 0.0]], dtype=torch.float32)
46
+ weights['y3_or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
47
+ weights['y3_nand.weight'] = torch.tensor([[-1.0, 0.0, 0.0, -1.0, 0.0, 0.0]], dtype=torch.float32)
48
+ weights['y3_nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
49
+
50
+ # Layer 3: y2 and y3 final AND
51
+ weights['y2.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
52
+ weights['y2.bias'] = torch.tensor([-2.0], dtype=torch.float32)
53
+ weights['y3.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
54
+ weights['y3.bias'] = torch.tensor([-2.0], dtype=torch.float32)
55
+
56
+ save_file(weights, 'model.safetensors')
57
+
58
+ # Verify
59
+ def incrementer4(a3, a2, a1, a0):
60
+ inp = torch.tensor([float(a3), float(a2), float(a1), float(a0)])
61
+
62
+ # Layer 1
63
+ y0 = int((inp @ weights['y0.weight'].T + weights['y0.bias'] >= 0).item())
64
+ c2 = int((inp @ weights['c2.weight'].T + weights['c2.bias'] >= 0).item())
65
+ c3 = int((inp @ weights['c3.weight'].T + weights['c3.bias'] >= 0).item())
66
+ y1_or = int((inp @ weights['y1_or.weight'].T + weights['y1_or.bias'] >= 0).item())
67
+ y1_nand = int((inp @ weights['y1_nand.weight'].T + weights['y1_nand.bias'] >= 0).item())
68
+
69
+ # Layer 2
70
+ l2_in = torch.tensor([float(a3), float(a2), float(c2), float(c3), float(y1_or), float(y1_nand)])
71
+ y1 = int((l2_in @ weights['y1.weight'].T + weights['y1.bias'] >= 0).item())
72
+ y2_or = int((l2_in @ weights['y2_or.weight'].T + weights['y2_or.bias'] >= 0).item())
73
+ y2_nand = int((l2_in @ weights['y2_nand.weight'].T + weights['y2_nand.bias'] >= 0).item())
74
+ y3_or = int((l2_in @ weights['y3_or.weight'].T + weights['y3_or.bias'] >= 0).item())
75
+ y3_nand = int((l2_in @ weights['y3_nand.weight'].T + weights['y3_nand.bias'] >= 0).item())
76
+
77
+ # Layer 3
78
+ l3_y2 = torch.tensor([float(y2_or), float(y2_nand)])
79
+ l3_y3 = torch.tensor([float(y3_or), float(y3_nand)])
80
+ y2 = int((l3_y2 @ weights['y2.weight'].T + weights['y2.bias'] >= 0).item())
81
+ y3 = int((l3_y3 @ weights['y3.weight'].T + weights['y3.bias'] >= 0).item())
82
+
83
+ return [y3, y2, y1, y0]
84
+
85
+ print("Verifying incrementer4bit...")
86
+ errors = 0
87
+ for i in range(16):
88
+ a3, a2, a1, a0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
89
+ result = incrementer4(a3, a2, a1, a0)
90
+ expected_val = (i + 1) % 16
91
+ expected = [(expected_val >> 3) & 1, (expected_val >> 2) & 1, (expected_val >> 1) & 1, expected_val & 1]
92
+ if result != expected:
93
+ errors += 1
94
+ print(f"ERROR: {i} ({a3}{a2}{a1}{a0}) + 1 = {result}, expected {expected} ({expected_val})")
95
+
96
+ if errors == 0:
97
+ print("All 16 test cases passed!")
98
+ else:
99
+ print(f"FAILED: {errors} errors")
100
+
101
+ mag = sum(t.abs().sum().item() for t in weights.values())
102
+ print(f"Magnitude: {mag:.0f}")
model.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 incrementer4(a3, a2, a1, a0, w):
8
+ """Add 1 to 4-bit input (mod 16)."""
9
+ inp = torch.tensor([float(a3), float(a2), float(a1), float(a0)])
10
+
11
+ # Layer 1
12
+ y0 = int((inp @ w['y0.weight'].T + w['y0.bias'] >= 0).item())
13
+ c2 = int((inp @ w['c2.weight'].T + w['c2.bias'] >= 0).item())
14
+ c3 = int((inp @ w['c3.weight'].T + w['c3.bias'] >= 0).item())
15
+ y1_or = int((inp @ w['y1_or.weight'].T + w['y1_or.bias'] >= 0).item())
16
+ y1_nand = int((inp @ w['y1_nand.weight'].T + w['y1_nand.bias'] >= 0).item())
17
+
18
+ # Layer 2
19
+ l2_in = torch.tensor([float(a3), float(a2), float(c2), float(c3), float(y1_or), float(y1_nand)])
20
+ y1 = int((l2_in @ w['y1.weight'].T + w['y1.bias'] >= 0).item())
21
+ y2_or = int((l2_in @ w['y2_or.weight'].T + w['y2_or.bias'] >= 0).item())
22
+ y2_nand = int((l2_in @ w['y2_nand.weight'].T + w['y2_nand.bias'] >= 0).item())
23
+ y3_or = int((l2_in @ w['y3_or.weight'].T + w['y3_or.bias'] >= 0).item())
24
+ y3_nand = int((l2_in @ w['y3_nand.weight'].T + w['y3_nand.bias'] >= 0).item())
25
+
26
+ # Layer 3
27
+ y2 = int(y2_or + y2_nand - 2 >= 0)
28
+ y3 = int(y3_or + y3_nand - 2 >= 0)
29
+
30
+ return [y3, y2, y1, y0]
31
+
32
+ if __name__ == '__main__':
33
+ w = load_model()
34
+ print('incrementer4bit:')
35
+ for i in range(16):
36
+ a3, a2, a1, a0 = (i >> 3) & 1, (i >> 2) & 1, (i >> 1) & 1, i & 1
37
+ result = incrementer4(a3, a2, a1, a0, w)
38
+ out_val = result[0]*8 + result[1]*4 + result[2]*2 + result[3]
39
+ print(f' {i:2d} ({a3}{a2}{a1}{a0}) + 1 = {out_val:2d} ({"".join(map(str, result))})')
model.safetensors ADDED
Binary file (1.86 kB). View file