CharlesCNorton commited on
Commit
93b5397
·
0 Parent(s):

3-bit parity threshold circuit, magnitude 20

Browse files
Files changed (5) hide show
  1. README.md +78 -0
  2. config.json +9 -0
  3. create_safetensors.py +44 -0
  4. model.py +22 -0
  5. model.safetensors +0 -0
README.md ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ ---
9
+
10
+ # threshold-parity3
11
+
12
+ 3-bit parity function. Outputs 1 if odd number of inputs are high.
13
+
14
+ ## Function
15
+
16
+ parity3(a, b, c) = a XOR b XOR c
17
+
18
+ ## Truth Table
19
+
20
+ | a | b | c | out |
21
+ |---|---|---|-----|
22
+ | 0 | 0 | 0 | 0 |
23
+ | 0 | 0 | 1 | 1 |
24
+ | 0 | 1 | 0 | 1 |
25
+ | 0 | 1 | 1 | 0 |
26
+ | 1 | 0 | 0 | 1 |
27
+ | 1 | 0 | 1 | 0 |
28
+ | 1 | 1 | 0 | 0 |
29
+ | 1 | 1 | 1 | 1 |
30
+
31
+ ## Architecture
32
+
33
+ Cascade of two XOR2 gates: parity(a,b,c) = XOR(XOR(a,b), c)
34
+
35
+ Each XOR2 uses OR-NAND-AND structure:
36
+ - OR: fires if either input is 1
37
+ - NAND: fires if not both inputs are 1
38
+ - AND: fires if both OR and NAND fire (XOR condition)
39
+
40
+ **Layers:**
41
+ 1. xor1.or, xor1.nand (on inputs a, b)
42
+ 2. xor1.and (combines layer 1)
43
+ 3. xor2.or, xor2.nand (on xor1 output and c)
44
+ 4. xor2.and (final output)
45
+
46
+ ## Parameters
47
+
48
+ | | |
49
+ |---|---|
50
+ | Inputs | 3 |
51
+ | Outputs | 1 |
52
+ | Neurons | 6 |
53
+ | Layers | 4 |
54
+ | Parameters | 18 |
55
+ | Magnitude | 20 |
56
+
57
+ ## Usage
58
+
59
+ ```python
60
+ from safetensors.torch import load_file
61
+
62
+ w = load_file('model.safetensors')
63
+
64
+ def xor2(a, b, prefix):
65
+ or_out = int(a * w[f'{prefix}.or.weight'][0] + b * w[f'{prefix}.or.weight'][1] + w[f'{prefix}.or.bias'] >= 0)
66
+ nand_out = int(a * w[f'{prefix}.nand.weight'][0] + b * w[f'{prefix}.nand.weight'][1] + w[f'{prefix}.nand.bias'] >= 0)
67
+ return int(or_out * w[f'{prefix}.and.weight'][0] + nand_out * w[f'{prefix}.and.weight'][1] + w[f'{prefix}.and.bias'] >= 0)
68
+
69
+ def parity3(a, b, c):
70
+ return xor2(xor2(a, b, 'xor1'), c, 'xor2')
71
+
72
+ print(parity3(1, 0, 1)) # 0 (even parity)
73
+ print(parity3(1, 1, 1)) # 1 (odd parity)
74
+ ```
75
+
76
+ ## License
77
+
78
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-parity3",
3
+ "description": "3-bit parity (XOR of 3 inputs)",
4
+ "inputs": 3,
5
+ "outputs": 1,
6
+ "neurons": 6,
7
+ "layers": 4,
8
+ "parameters": 18
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ # Cascade of two XOR2 gates: parity(a,b,c) = XOR(XOR(a,b), c)
5
+ # Each XOR uses OR-NAND-AND structure
6
+
7
+ def xor_block(prefix):
8
+ return {
9
+ f'{prefix}.or.weight': torch.tensor([1.0, 1.0], dtype=torch.float32),
10
+ f'{prefix}.or.bias': torch.tensor([-1.0], dtype=torch.float32),
11
+ f'{prefix}.nand.weight': torch.tensor([-1.0, -1.0], dtype=torch.float32),
12
+ f'{prefix}.nand.bias': torch.tensor([1.0], dtype=torch.float32),
13
+ f'{prefix}.and.weight': torch.tensor([1.0, 1.0], dtype=torch.float32),
14
+ f'{prefix}.and.bias': torch.tensor([-2.0], dtype=torch.float32),
15
+ }
16
+
17
+ weights = {}
18
+ weights.update(xor_block('xor1'))
19
+ weights.update(xor_block('xor2'))
20
+
21
+ save_file(weights, 'model.safetensors')
22
+
23
+ def xor2(a, b, prefix):
24
+ or_out = int(a * weights[f'{prefix}.or.weight'][0] + b * weights[f'{prefix}.or.weight'][1] + weights[f'{prefix}.or.bias'] >= 0)
25
+ nand_out = int(a * weights[f'{prefix}.nand.weight'][0] + b * weights[f'{prefix}.nand.weight'][1] + weights[f'{prefix}.nand.bias'] >= 0)
26
+ and_out = int(or_out * weights[f'{prefix}.and.weight'][0] + nand_out * weights[f'{prefix}.and.weight'][1] + weights[f'{prefix}.and.bias'] >= 0)
27
+ return and_out
28
+
29
+ def parity3(a, b, c):
30
+ xor_ab = xor2(a, b, 'xor1')
31
+ return xor2(xor_ab, c, 'xor2')
32
+
33
+ print("Verifying parity3...")
34
+ errors = 0
35
+ for i in range(8):
36
+ a, b, c = (i >> 2) & 1, (i >> 1) & 1, i & 1
37
+ result = parity3(a, b, c)
38
+ expected = a ^ b ^ c
39
+ if result != expected:
40
+ errors += 1
41
+ print(f"ERROR: parity({a},{b},{c}) = {result}, expected {expected}")
42
+ if errors == 0:
43
+ print("All 8 test cases passed!")
44
+ print(f"Magnitude: {sum(t.abs().sum().item() for t in weights.values()):.0f}")
model.py ADDED
@@ -0,0 +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 xor2(a, b, prefix, w):
8
+ or_out = int(a * w[f'{prefix}.or.weight'][0] + b * w[f'{prefix}.or.weight'][1] + w[f'{prefix}.or.bias'] >= 0)
9
+ nand_out = int(a * w[f'{prefix}.nand.weight'][0] + b * w[f'{prefix}.nand.weight'][1] + w[f'{prefix}.nand.bias'] >= 0)
10
+ and_out = int(or_out * w[f'{prefix}.and.weight'][0] + nand_out * w[f'{prefix}.and.weight'][1] + w[f'{prefix}.and.bias'] >= 0)
11
+ return and_out
12
+
13
+ def parity3(a, b, c, weights):
14
+ xor_ab = xor2(a, b, 'xor1', weights)
15
+ return xor2(xor_ab, c, 'xor2', weights)
16
+
17
+ if __name__ == '__main__':
18
+ w = load_model()
19
+ print('parity3 truth table:')
20
+ for i in range(8):
21
+ a, b, c = (i >> 2) & 1, (i >> 1) & 1, i & 1
22
+ print(f' parity({a},{b},{c}) = {parity3(a, b, c, w)}')
model.safetensors ADDED
Binary file (896 Bytes). View file