phanerozoic commited on
Commit
d8ea23b
·
verified ·
1 Parent(s): 7778e4d

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. README.md +75 -75
  2. config.json +9 -9
  3. create_safetensors.py +75 -75
  4. model.py +22 -22
README.md CHANGED
@@ -1,75 +1,75 @@
1
- ---
2
- license: mit
3
- tags:
4
- - pytorch
5
- - safetensors
6
- - threshold-logic
7
- - neuromorphic
8
- ---
9
-
10
- # threshold-mux16
11
-
12
- 16:1 multiplexer. Selects one of 16 data inputs based on 4-bit select signal.
13
-
14
- ## Function
15
-
16
- MUX16(d0..d15, s3,s2,s1,s0) = d[s] where s = 8*s3 + 4*s2 + 2*s1 + s0
17
-
18
- ## Architecture
19
-
20
- ```
21
- d0..d15 (16 data) s3 s2 s1 s0 (4 select)
22
- | |
23
- +--------------------+
24
- |
25
- v
26
- [N0] d0 AND (s=0000) ----+
27
- [N1] d1 AND (s=0001) ----|
28
- [N2] d2 AND (s=0010) ----|
29
- ... +---> [OR] ---> output
30
- [N14] d14 AND (s=1110) ----|
31
- [N15] d15 AND (s=1111) ----+
32
- ```
33
-
34
- ## Layer 1 Weights
35
-
36
- Each neuron Ni fires when di=1 AND s=i:
37
- - Weight on di: +1
38
- - Weight on each select bit: +1 if that bit is 1 in i, else -1
39
- - Bias: -(1 + popcount(i))
40
-
41
- ## Parameters
42
-
43
- | | |
44
- |---|---|
45
- | Inputs | 20 (16 data + 4 select) |
46
- | Outputs | 1 |
47
- | Neurons | 17 |
48
- | Layers | 2 |
49
- | Parameters | 373 |
50
- | Magnitude | 145 |
51
-
52
- ## Usage
53
-
54
- ```python
55
- from safetensors.torch import load_file
56
- import torch
57
-
58
- w = load_file('model.safetensors')
59
-
60
- def mux16(data, s3, s2, s1, s0):
61
- inp = torch.tensor([float(d) for d in data] +
62
- [float(s3), float(s2), float(s1), float(s0)])
63
- l1 = (inp @ w['layer1.weight'].T + w['layer1.bias'] >= 0).float()
64
- out = (l1 @ w['layer2.weight'].T + w['layer2.bias'] >= 0).float()
65
- return int(out.item())
66
-
67
- # Select d10 (s=1010)
68
- data = [0]*16
69
- data[10] = 1
70
- print(mux16(data, 1, 0, 1, 0)) # 1
71
- ```
72
-
73
- ## License
74
-
75
- MIT
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ ---
9
+
10
+ # threshold-mux16
11
+
12
+ 16:1 multiplexer. Selects one of 16 data inputs based on 4-bit select signal.
13
+
14
+ ## Function
15
+
16
+ MUX16(d0..d15, s3,s2,s1,s0) = d[s] where s = 8*s3 + 4*s2 + 2*s1 + s0
17
+
18
+ ## Architecture
19
+
20
+ ```
21
+ d0..d15 (16 data) s3 s2 s1 s0 (4 select)
22
+ | |
23
+ +--------------------+
24
+ |
25
+ v
26
+ [N0] d0 AND (s=0000) ----+
27
+ [N1] d1 AND (s=0001) ----|
28
+ [N2] d2 AND (s=0010) ----|
29
+ ... +---> [OR] ---> output
30
+ [N14] d14 AND (s=1110) ----|
31
+ [N15] d15 AND (s=1111) ----+
32
+ ```
33
+
34
+ ## Layer 1 Weights
35
+
36
+ Each neuron Ni fires when di=1 AND s=i:
37
+ - Weight on di: +1
38
+ - Weight on each select bit: +1 if that bit is 1 in i, else -1
39
+ - Bias: -(1 + popcount(i))
40
+
41
+ ## Parameters
42
+
43
+ | | |
44
+ |---|---|
45
+ | Inputs | 20 (16 data + 4 select) |
46
+ | Outputs | 1 |
47
+ | Neurons | 17 |
48
+ | Layers | 2 |
49
+ | Parameters | 373 |
50
+ | Magnitude | 145 |
51
+
52
+ ## Usage
53
+
54
+ ```python
55
+ from safetensors.torch import load_file
56
+ import torch
57
+
58
+ w = load_file('model.safetensors')
59
+
60
+ def mux16(data, s3, s2, s1, s0):
61
+ inp = torch.tensor([float(d) for d in data] +
62
+ [float(s3), float(s2), float(s1), float(s0)])
63
+ l1 = (inp @ w['layer1.weight'].T + w['layer1.bias'] >= 0).float()
64
+ out = (l1 @ w['layer2.weight'].T + w['layer2.bias'] >= 0).float()
65
+ return int(out.item())
66
+
67
+ # Select d10 (s=1010)
68
+ data = [0]*16
69
+ data[10] = 1
70
+ print(mux16(data, 1, 0, 1, 0)) # 1
71
+ ```
72
+
73
+ ## License
74
+
75
+ MIT
config.json CHANGED
@@ -1,9 +1,9 @@
1
- {
2
- "name": "threshold-mux16",
3
- "description": "16:1 multiplexer as threshold circuit",
4
- "inputs": 20,
5
- "outputs": 1,
6
- "neurons": 17,
7
- "layers": 2,
8
- "parameters": 373
9
- }
 
1
+ {
2
+ "name": "threshold-mux16",
3
+ "description": "16:1 multiplexer as threshold circuit",
4
+ "inputs": 20,
5
+ "outputs": 1,
6
+ "neurons": 17,
7
+ "layers": 2,
8
+ "parameters": 373
9
+ }
create_safetensors.py CHANGED
@@ -1,75 +1,75 @@
1
- import torch
2
- from safetensors.torch import save_file
3
-
4
- weights = {}
5
-
6
- # Input order: d0..d15, s3, s2, s1, s0 (20 inputs)
7
- # Layer 1: 16 neurons, each selects di when s = i
8
- # Layer 2: OR gate
9
-
10
- layer1_weights = []
11
- layer1_biases = []
12
-
13
- for i in range(16):
14
- w = [0.0] * 20
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
- s3_bit = (i >> 3) & 1
19
- s2_bit = (i >> 2) & 1
20
- s1_bit = (i >> 1) & 1
21
- s0_bit = i & 1
22
- w[16] = 1.0 if s3_bit else -1.0 # s3
23
- w[17] = 1.0 if s2_bit else -1.0 # s2
24
- w[18] = 1.0 if s1_bit else -1.0 # s1
25
- w[19] = 1.0 if s0_bit else -1.0 # s0
26
- # Bias: -(1 + popcount(i))
27
- bias = -(1 + bin(i).count('1'))
28
- layer1_weights.append(w)
29
- layer1_biases.append(bias)
30
-
31
- weights['layer1.weight'] = torch.tensor(layer1_weights, dtype=torch.float32)
32
- weights['layer1.bias'] = torch.tensor(layer1_biases, dtype=torch.float32)
33
-
34
- # Layer 2: OR gate
35
- weights['layer2.weight'] = torch.tensor([[1.0] * 16], dtype=torch.float32)
36
- weights['layer2.bias'] = torch.tensor([-1.0], dtype=torch.float32)
37
-
38
- save_file(weights, 'model.safetensors')
39
-
40
- # Verify
41
- def mux16(data, s3, s2, s1, s0):
42
- inp = torch.tensor([float(d) for d in data] + [float(s3), 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 MUX16...")
48
- errors = 0
49
- test_count = 0
50
- for s in range(16):
51
- s3, s2, s1, s0 = (s >> 3) & 1, (s >> 2) & 1, (s >> 1) & 1, s & 1
52
- # Test with selected data = 1, others = 0
53
- data = [0] * 16
54
- data[s] = 1
55
- result = mux16(data, s3, s2, s1, s0)
56
- if result != 1:
57
- errors += 1
58
- print(f"ERROR: s={s}, d[{s}]=1 -> {result}, expected 1")
59
- test_count += 1
60
-
61
- # Test with selected data = 0
62
- data[s] = 0
63
- result = mux16(data, s3, s2, s1, s0)
64
- if result != 0:
65
- errors += 1
66
- print(f"ERROR: s={s}, d[{s}]=0 -> {result}, expected 0")
67
- test_count += 1
68
-
69
- if errors == 0:
70
- print(f"All {test_count} test cases passed!")
71
- else:
72
- print(f"FAILED: {errors} errors")
73
-
74
- mag = sum(t.abs().sum().item() for t in weights.values())
75
- print(f"Magnitude: {mag:.0f}")
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # Input order: d0..d15, s3, s2, s1, s0 (20 inputs)
7
+ # Layer 1: 16 neurons, each selects di when s = i
8
+ # Layer 2: OR gate
9
+
10
+ layer1_weights = []
11
+ layer1_biases = []
12
+
13
+ for i in range(16):
14
+ w = [0.0] * 20
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
+ s3_bit = (i >> 3) & 1
19
+ s2_bit = (i >> 2) & 1
20
+ s1_bit = (i >> 1) & 1
21
+ s0_bit = i & 1
22
+ w[16] = 1.0 if s3_bit else -1.0 # s3
23
+ w[17] = 1.0 if s2_bit else -1.0 # s2
24
+ w[18] = 1.0 if s1_bit else -1.0 # s1
25
+ w[19] = 1.0 if s0_bit else -1.0 # s0
26
+ # Bias: -(1 + popcount(i))
27
+ bias = -(1 + bin(i).count('1'))
28
+ layer1_weights.append(w)
29
+ layer1_biases.append(bias)
30
+
31
+ weights['layer1.weight'] = torch.tensor(layer1_weights, dtype=torch.float32)
32
+ weights['layer1.bias'] = torch.tensor(layer1_biases, dtype=torch.float32)
33
+
34
+ # Layer 2: OR gate
35
+ weights['layer2.weight'] = torch.tensor([[1.0] * 16], dtype=torch.float32)
36
+ weights['layer2.bias'] = torch.tensor([-1.0], dtype=torch.float32)
37
+
38
+ save_file(weights, 'model.safetensors')
39
+
40
+ # Verify
41
+ def mux16(data, s3, s2, s1, s0):
42
+ inp = torch.tensor([float(d) for d in data] + [float(s3), 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 MUX16...")
48
+ errors = 0
49
+ test_count = 0
50
+ for s in range(16):
51
+ s3, s2, s1, s0 = (s >> 3) & 1, (s >> 2) & 1, (s >> 1) & 1, s & 1
52
+ # Test with selected data = 1, others = 0
53
+ data = [0] * 16
54
+ data[s] = 1
55
+ result = mux16(data, s3, s2, s1, s0)
56
+ if result != 1:
57
+ errors += 1
58
+ print(f"ERROR: s={s}, d[{s}]=1 -> {result}, expected 1")
59
+ test_count += 1
60
+
61
+ # Test with selected data = 0
62
+ data[s] = 0
63
+ result = mux16(data, s3, s2, s1, s0)
64
+ if result != 0:
65
+ errors += 1
66
+ print(f"ERROR: s={s}, d[{s}]=0 -> {result}, expected 0")
67
+ test_count += 1
68
+
69
+ if errors == 0:
70
+ print(f"All {test_count} test cases passed!")
71
+ else:
72
+ print(f"FAILED: {errors} errors")
73
+
74
+ mag = sum(t.abs().sum().item() for t in weights.values())
75
+ print(f"Magnitude: {mag:.0f}")
model.py CHANGED
@@ -1,22 +1,22 @@
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 mux16(data, s3, s2, s1, s0, weights):
8
- """16:1 Multiplexer: returns data[s] where s = 8*s3 + 4*s2 + 2*s1 + s0"""
9
- inp = torch.tensor([float(d) for d in data] + [float(s3), float(s2), float(s1), float(s0)])
10
- l1 = (inp @ weights['layer1.weight'].T + weights['layer1.bias'] >= 0).float()
11
- out = (l1 @ weights['layer2.weight'].T + weights['layer2.bias'] >= 0).float()
12
- return int(out.item())
13
-
14
- if __name__ == '__main__':
15
- w = load_model()
16
- print('MUX16 verification:')
17
- for s in range(16):
18
- s3, s2, s1, s0 = (s >> 3) & 1, (s >> 2) & 1, (s >> 1) & 1, s & 1
19
- data = [0] * 16
20
- data[s] = 1
21
- result = mux16(data, s3, s2, s1, s0, w)
22
- print(f' s={s:2d} ({s3}{s2}{s1}{s0}), d[{s}]=1 -> {result}')
 
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 mux16(data, s3, s2, s1, s0, weights):
8
+ """16:1 Multiplexer: returns data[s] where s = 8*s3 + 4*s2 + 2*s1 + s0"""
9
+ inp = torch.tensor([float(d) for d in data] + [float(s3), float(s2), float(s1), float(s0)])
10
+ l1 = (inp @ weights['layer1.weight'].T + weights['layer1.bias'] >= 0).float()
11
+ out = (l1 @ weights['layer2.weight'].T + weights['layer2.bias'] >= 0).float()
12
+ return int(out.item())
13
+
14
+ if __name__ == '__main__':
15
+ w = load_model()
16
+ print('MUX16 verification:')
17
+ for s in range(16):
18
+ s3, s2, s1, s0 = (s >> 3) & 1, (s >> 2) & 1, (s >> 1) & 1, s & 1
19
+ data = [0] * 16
20
+ data[s] = 1
21
+ result = mux16(data, s3, s2, s1, s0, w)
22
+ print(f' s={s:2d} ({s3}{s2}{s1}{s0}), d[{s}]=1 -> {result}')