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

8:1 multiplexer threshold circuit, magnitude 61

Browse files
Files changed (5) hide show
  1. README.md +88 -0
  2. config.json +9 -0
  3. create_safetensors.py +67 -0
  4. model.py +24 -0
  5. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ ---
9
+
10
+ # threshold-mux8
11
+
12
+ 8:1 multiplexer. Selects one of 8 data inputs based on 3-bit select signal.
13
+
14
+ ## Function
15
+
16
+ MUX8(d0-d7, s2,s1,s0) = d[s] where s = 4*s2 + 2*s1 + s0
17
+
18
+ ## Architecture
19
+
20
+ ```
21
+ d0 d1 d2 d3 d4 d5 d6 d7 s2 s1 s0
22
+ | | | | | | | | | | |
23
+ +--+--+--+--+--+--+--+----+--+--+
24
+ | |
25
+ v v
26
+ [N0] d0 AND (s=000) ----+
27
+ [N1] d1 AND (s=001) ----|
28
+ [N2] d2 AND (s=010) ----|
29
+ [N3] d3 AND (s=011) ----+---> [OR] ---> output
30
+ [N4] d4 AND (s=100) ----|
31
+ [N5] d5 AND (s=101) ----|
32
+ [N6] d6 AND (s=110) ----|
33
+ [N7] d7 AND (s=111) ----+
34
+ ```
35
+
36
+ ## Parameters
37
+
38
+ | | |
39
+ |---|---|
40
+ | Inputs | 11 (8 data + 3 select) |
41
+ | Outputs | 1 |
42
+ | Neurons | 9 |
43
+ | Layers | 2 |
44
+ | Parameters | 105 |
45
+ | Magnitude | 61 |
46
+
47
+ ## Layer 1 Weights
48
+
49
+ Each neuron Ni fires when di=1 AND s=i:
50
+
51
+ | Neuron | Data weights | Select weights (s2,s1,s0) | Bias |
52
+ |--------|--------------|---------------------------|------|
53
+ | N0 | d0=1 | [-1,-1,-1] | -1 |
54
+ | N1 | d1=1 | [-1,-1,+1] | -2 |
55
+ | N2 | d2=1 | [-1,+1,-1] | -2 |
56
+ | N3 | d3=1 | [-1,+1,+1] | -3 |
57
+ | N4 | d4=1 | [+1,-1,-1] | -2 |
58
+ | N5 | d5=1 | [+1,-1,+1] | -3 |
59
+ | N6 | d6=1 | [+1,+1,-1] | -3 |
60
+ | N7 | d7=1 | [+1,+1,+1] | -4 |
61
+
62
+ ## Layer 2
63
+
64
+ OR gate: weights [1,1,1,1,1,1,1,1], bias -1
65
+
66
+ ## Usage
67
+
68
+ ```python
69
+ from safetensors.torch import load_file
70
+ import torch
71
+
72
+ w = load_file('model.safetensors')
73
+
74
+ def mux8(d0, d1, d2, d3, d4, d5, d6, d7, s2, s1, s0):
75
+ inp = torch.tensor([float(d0), float(d1), float(d2), float(d3),
76
+ float(d4), float(d5), float(d6), float(d7),
77
+ float(s2), float(s1), float(s0)])
78
+ l1 = (inp @ w['layer1.weight'].T + w['layer1.bias'] >= 0).float()
79
+ out = (l1 @ w['layer2.weight'].T + w['layer2.bias'] >= 0).float()
80
+ return int(out.item())
81
+
82
+ # Select d5 (s=101)
83
+ print(mux8(0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1)) # 1
84
+ ```
85
+
86
+ ## License
87
+
88
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-mux8",
3
+ "description": "8:1 multiplexer as threshold circuit",
4
+ "inputs": 11,
5
+ "outputs": 1,
6
+ "neurons": 9,
7
+ "layers": 2,
8
+ "parameters": 105
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # Input order: d0, d1, d2, d3, d4, d5, d6, d7, s2, s1, s0 (11 inputs)
7
+ # Layer 1: 8 neurons, each selects di when s = i
8
+ # Layer 2: OR gate combining all 8
9
+
10
+ layer1_weights = []
11
+ layer1_biases = []
12
+
13
+ for i in range(8):
14
+ w = [0.0] * 11
15
+ # Data input weight
16
+ w[i] = 1.0
17
+ # Select weights: +1 if bit should be 1, -1 if bit should be 0
18
+ s2_bit = (i >> 2) & 1
19
+ s1_bit = (i >> 1) & 1
20
+ s0_bit = i & 1
21
+ w[8] = 1.0 if s2_bit else -1.0 # s2
22
+ w[9] = 1.0 if s1_bit else -1.0 # s1
23
+ w[10] = 1.0 if s0_bit else -1.0 # s0
24
+ # Bias: -(1 + popcount(i))
25
+ bias = -(1 + bin(i).count('1'))
26
+ layer1_weights.append(w)
27
+ layer1_biases.append(bias)
28
+
29
+ weights['layer1.weight'] = torch.tensor(layer1_weights, dtype=torch.float32)
30
+ weights['layer1.bias'] = torch.tensor(layer1_biases, dtype=torch.float32)
31
+
32
+ # Layer 2: OR gate
33
+ weights['layer2.weight'] = torch.tensor([[1.0] * 8], dtype=torch.float32)
34
+ weights['layer2.bias'] = torch.tensor([-1.0], dtype=torch.float32)
35
+
36
+ save_file(weights, 'model.safetensors')
37
+
38
+ # Verify
39
+ def mux8(d0, d1, d2, d3, d4, d5, d6, d7, s2, s1, s0):
40
+ inp = torch.tensor([float(d0), float(d1), float(d2), float(d3),
41
+ float(d4), float(d5), float(d6), float(d7),
42
+ float(s2), float(s1), float(s0)])
43
+ l1 = (inp @ weights['layer1.weight'].T + weights['layer1.bias'] >= 0).float()
44
+ out = (l1 @ weights['layer2.weight'].T + weights['layer2.bias'] >= 0).float()
45
+ return int(out.item())
46
+
47
+ print("Verifying MUX8...")
48
+ errors = 0
49
+ for s in range(8):
50
+ s2, s1, s0 = (s >> 2) & 1, (s >> 1) & 1, s & 1
51
+ for d_vals in range(256):
52
+ d = [(d_vals >> i) & 1 for i in range(8)]
53
+ result = mux8(*d, s2, s1, s0)
54
+ expected = d[s]
55
+ if result != expected:
56
+ errors += 1
57
+ if errors <= 5:
58
+ print(f"ERROR: s={s}, d={d}, got {result}, expected {expected}")
59
+
60
+ if errors == 0:
61
+ print("All 2048 test cases passed!")
62
+ else:
63
+ print(f"FAILED: {errors} errors")
64
+
65
+ # Print magnitude
66
+ mag = sum(t.abs().sum().item() for t in weights.values())
67
+ print(f"Magnitude: {mag:.0f}")
model.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 mux8(d0, d1, d2, d3, d4, d5, d6, d7, s2, s1, s0, weights):
8
+ """8:1 Multiplexer: returns d[s] where s = 4*s2 + 2*s1 + s0"""
9
+ inp = torch.tensor([float(d0), float(d1), float(d2), float(d3),
10
+ float(d4), float(d5), float(d6), float(d7),
11
+ float(s2), float(s1), float(s0)])
12
+ l1 = (inp @ weights['layer1.weight'].T + weights['layer1.bias'] >= 0).float()
13
+ out = (l1 @ weights['layer2.weight'].T + weights['layer2.bias'] >= 0).float()
14
+ return int(out.item())
15
+
16
+ if __name__ == '__main__':
17
+ w = load_model()
18
+ print('MUX8 verification:')
19
+ for s in range(8):
20
+ s2, s1, s0 = (s >> 2) & 1, (s >> 1) & 1, s & 1
21
+ d = [0] * 8
22
+ d[s] = 1
23
+ result = mux8(*d, s2, s1, s0, w)
24
+ print(f' s={s} ({s2}{s1}{s0}), d[{s}]=1 -> {result}')
model.safetensors ADDED
Binary file (708 Bytes). View file