phanerozoic commited on
Commit
6529868
·
verified ·
1 Parent(s): 1d65f31

Upload folder using huggingface_hub

Browse files
Files changed (5) hide show
  1. README.md +175 -0
  2. config.json +9 -0
  3. create_safetensors.py +75 -0
  4. model.py +34 -0
  5. model.safetensors +3 -0
README.md ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ tags:
4
+ - pytorch
5
+ - safetensors
6
+ - threshold-logic
7
+ - neuromorphic
8
+ - arithmetic
9
+ - multiplier
10
+ - compressor
11
+ ---
12
+
13
+ # threshold-3to2-compressor
14
+
15
+ 3:2 compressor (carry-save adder). Reduces 3 input bits to 2 output bits (sum and carry) while preserving arithmetic value. Essential building block for fast multipliers.
16
+
17
+ ## Circuit
18
+
19
+ ```
20
+ x y z
21
+ │ │ │
22
+ └───┬───┴───┬───┘
23
+ │ │
24
+ ┌───┴───┐ │
25
+ │ XOR │ │
26
+ │ (x,y) │ │
27
+ └───┬───┘ │
28
+ │ │
29
+ ┌───┴───────┴───┐
30
+ │ │
31
+ ▼ ▼
32
+ ┌───────┐ ┌───────┐
33
+ │ XOR │ │ MAJ │
34
+ │(xy^,z)│ │(x,y,z)│
35
+ └───────┘ └───────┘
36
+ │ │
37
+ ▼ ▼
38
+ Sum Carry
39
+ ```
40
+
41
+ ## Function
42
+
43
+ ```
44
+ compress(x, y, z) -> (sum, carry)
45
+
46
+ where: x + y + z = sum + 2*carry
47
+ ```
48
+
49
+ The compressor preserves the arithmetic sum while reducing bit count from 3 to 2.
50
+
51
+ ## Truth Table
52
+
53
+ | x | y | z | Sum | x+y+z | Sum | Carry | Sum+2*Carry |
54
+ |---|---|---|-----|:-----:|:---:|:-----:|:-----------:|
55
+ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
56
+ | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 |
57
+ | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 |
58
+ | 0 | 1 | 1 | 2 | 2 | 0 | 1 | 2 |
59
+ | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 |
60
+ | 1 | 0 | 1 | 2 | 2 | 0 | 1 | 2 |
61
+ | 1 | 1 | 0 | 2 | 2 | 0 | 1 | 2 |
62
+ | 1 | 1 | 1 | 3 | 3 | 1 | 1 | 3 |
63
+
64
+ ## Mechanism
65
+
66
+ The 3:2 compressor is identical to a full adder, computing:
67
+
68
+ - **Sum** = x XOR y XOR z (odd parity of inputs)
69
+ - **Carry** = MAJ(x, y, z) = majority function (at least 2 inputs high)
70
+
71
+ **Sum computation (6 neurons):**
72
+ ```
73
+ xor_xy = XOR(x, y) # 3 neurons
74
+ sum = XOR(xor_xy, z) # 3 neurons
75
+ ```
76
+
77
+ **Carry computation (1 neuron):**
78
+ ```
79
+ carry = (x + y + z >= 2) # Threshold gate with weights [1,1,1], bias -2
80
+ ```
81
+
82
+ ## Architecture
83
+
84
+ | Component | Function | Neurons | Layers |
85
+ |-----------|----------|---------|--------|
86
+ | XOR(x,y) | First XOR | 3 | 2 |
87
+ | XOR(xy,z) | Sum output | 3 | 2 |
88
+ | MAJ(x,y,z) | Carry output | 1 | 1 |
89
+
90
+ **Total: 7 neurons**
91
+
92
+ Note: Sum requires 4 layers (2 sequential XORs), Carry requires 1 layer. Overall depth is 4.
93
+
94
+ ## Parameters
95
+
96
+ | | |
97
+ |---|---|
98
+ | Inputs | 3 |
99
+ | Outputs | 2 (sum, carry) |
100
+ | Neurons | 7 |
101
+ | Layers | 4 |
102
+ | Parameters | 22 |
103
+ | Magnitude | 23 |
104
+
105
+ ## Why "Compressor"?
106
+
107
+ In multiplier design, partial products create columns of bits that must be summed. A 3:2 compressor reduces 3 bits in a column to 2 bits, with the carry going to the next column:
108
+
109
+ ```
110
+ Before: x y z (3 bits in one column)
111
+ After: s c (1 bit in this column, 1 in next)
112
+ ```
113
+
114
+ Multiple compressors work in parallel to reduce partial products.
115
+
116
+ ## Usage
117
+
118
+ ```python
119
+ from safetensors.torch import load_file
120
+ import torch
121
+
122
+ w = load_file('model.safetensors')
123
+
124
+ def xor2(a, b, prefix):
125
+ inp = torch.tensor([float(a), float(b)])
126
+ or_out = int((inp @ w[f'{prefix}.or.weight'].T + w[f'{prefix}.or.bias'] >= 0).item())
127
+ nand_out = int((inp @ w[f'{prefix}.nand.weight'].T + w[f'{prefix}.nand.bias'] >= 0).item())
128
+ l1 = torch.tensor([float(or_out), float(nand_out)])
129
+ return int((l1 @ w[f'{prefix}.and.weight'].T + w[f'{prefix}.and.bias'] >= 0).item())
130
+
131
+ def compress_3to2(x, y, z):
132
+ # Sum = x XOR y XOR z
133
+ xor_xy = xor2(x, y, 'xor1')
134
+ sum_out = xor2(xor_xy, z, 'xor2')
135
+
136
+ # Carry = MAJ(x, y, z)
137
+ inp = torch.tensor([float(x), float(y), float(z)])
138
+ carry = int((inp @ w['maj.weight'].T + w['maj.bias'] >= 0).item())
139
+
140
+ return sum_out, carry
141
+
142
+ # Examples
143
+ print(compress_3to2(0, 0, 0)) # (0, 0) -> 0
144
+ print(compress_3to2(1, 1, 0)) # (0, 1) -> 2
145
+ print(compress_3to2(1, 1, 1)) # (1, 1) -> 3
146
+ ```
147
+
148
+ ## Applications
149
+
150
+ - Wallace tree multipliers
151
+ - Dadda tree multipliers
152
+ - Carry-save adder arrays
153
+ - Multi-operand addition
154
+ - DSP accumulator chains
155
+
156
+ ## Related Circuits
157
+
158
+ - `threshold-4to2-compressor`: Reduces 4+carry to 2+carry
159
+ - `threshold-fulladder`: Same circuit, different context
160
+ - `threshold-wallace-tree-3x3`: Uses multiple 3:2 compressors
161
+
162
+ ## Files
163
+
164
+ ```
165
+ threshold-3to2-compressor/
166
+ ├── model.safetensors
167
+ ├── model.py
168
+ ├── create_safetensors.py
169
+ ├── config.json
170
+ └── README.md
171
+ ```
172
+
173
+ ## License
174
+
175
+ MIT
config.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "threshold-3to2-compressor",
3
+ "description": "3:2 compressor (carry-save adder) for multiplier trees",
4
+ "inputs": 3,
5
+ "outputs": 2,
6
+ "neurons": 7,
7
+ "layers": 4,
8
+ "parameters": 22
9
+ }
create_safetensors.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from safetensors.torch import save_file
3
+
4
+ weights = {}
5
+
6
+ # 3:2 Compressor
7
+ # Inputs: x, y, z
8
+ # Outputs: sum = x XOR y XOR z, carry = MAJ(x,y,z)
9
+ # Preserves: x + y + z = sum + 2*carry
10
+
11
+ # XOR block helper
12
+ def add_xor(prefix):
13
+ weights[f'{prefix}.or.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
14
+ weights[f'{prefix}.or.bias'] = torch.tensor([-1.0], dtype=torch.float32)
15
+ weights[f'{prefix}.nand.weight'] = torch.tensor([[-1.0, -1.0]], dtype=torch.float32)
16
+ weights[f'{prefix}.nand.bias'] = torch.tensor([1.0], dtype=torch.float32)
17
+ weights[f'{prefix}.and.weight'] = torch.tensor([[1.0, 1.0]], dtype=torch.float32)
18
+ weights[f'{prefix}.and.bias'] = torch.tensor([-2.0], dtype=torch.float32)
19
+
20
+ # XOR gates for sum
21
+ add_xor('xor1') # XOR(x, y)
22
+ add_xor('xor2') # XOR(xor1, z)
23
+
24
+ # Majority gate for carry
25
+ weights['maj.weight'] = torch.tensor([[1.0, 1.0, 1.0]], dtype=torch.float32)
26
+ weights['maj.bias'] = torch.tensor([-2.0], dtype=torch.float32)
27
+
28
+ save_file(weights, 'model.safetensors')
29
+
30
+ def xor2(a, b, prefix):
31
+ inp = torch.tensor([float(a), float(b)])
32
+ or_out = int((inp @ weights[f'{prefix}.or.weight'].T + weights[f'{prefix}.or.bias'] >= 0).item())
33
+ nand_out = int((inp @ weights[f'{prefix}.nand.weight'].T + weights[f'{prefix}.nand.bias'] >= 0).item())
34
+ l1 = torch.tensor([float(or_out), float(nand_out)])
35
+ return int((l1 @ weights[f'{prefix}.and.weight'].T + weights[f'{prefix}.and.bias'] >= 0).item())
36
+
37
+ def compress_3to2(x, y, z):
38
+ # Sum = x XOR y XOR z
39
+ xor_xy = xor2(x, y, 'xor1')
40
+ sum_out = xor2(xor_xy, z, 'xor2')
41
+
42
+ # Carry = MAJ(x, y, z)
43
+ inp = torch.tensor([float(x), float(y), float(z)])
44
+ carry = int((inp @ weights['maj.weight'].T + weights['maj.bias'] >= 0).item())
45
+
46
+ return sum_out, carry
47
+
48
+ print("Verifying 3:2 compressor...")
49
+ errors = 0
50
+ for x in [0, 1]:
51
+ for y in [0, 1]:
52
+ for z in [0, 1]:
53
+ s, c = compress_3to2(x, y, z)
54
+ input_sum = x + y + z
55
+ output_sum = s + 2 * c
56
+ if input_sum != output_sum:
57
+ errors += 1
58
+ print(f"ERROR: {x}+{y}+{z}={input_sum}, but s={s},c={c} gives {output_sum}")
59
+
60
+ if errors == 0:
61
+ print("All 8 test cases passed!")
62
+ else:
63
+ print(f"FAILED: {errors} errors")
64
+
65
+ print(f"Magnitude: {sum(t.abs().sum().item() for t in weights.values()):.0f}")
66
+ print(f"Parameters: {sum(t.numel() for t in weights.values())}")
67
+
68
+ print("\nTruth Table:")
69
+ print("x y z | sum carry | x+y+z = s+2c")
70
+ print("------+-----------+-------------")
71
+ for x in [0, 1]:
72
+ for y in [0, 1]:
73
+ for z in [0, 1]:
74
+ s, c = compress_3to2(x, y, z)
75
+ print(f"{x} {y} {z} | {s} {c} | {x+y+z} = {s+2*c}")
model.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ inp = torch.tensor([float(a), float(b)])
9
+ or_out = int((inp @ w[f'{prefix}.or.weight'].T + w[f'{prefix}.or.bias'] >= 0).item())
10
+ nand_out = int((inp @ w[f'{prefix}.nand.weight'].T + w[f'{prefix}.nand.bias'] >= 0).item())
11
+ l1 = torch.tensor([float(or_out), float(nand_out)])
12
+ return int((l1 @ w[f'{prefix}.and.weight'].T + w[f'{prefix}.and.bias'] >= 0).item())
13
+
14
+ def compress_3to2(x, y, z, weights):
15
+ """3:2 compressor: returns (sum, carry) where x+y+z = sum + 2*carry."""
16
+ xor_xy = xor2(x, y, 'xor1', weights)
17
+ sum_out = xor2(xor_xy, z, 'xor2', weights)
18
+
19
+ inp = torch.tensor([float(x), float(y), float(z)])
20
+ carry = int((inp @ weights['maj.weight'].T + weights['maj.bias'] >= 0).item())
21
+
22
+ return sum_out, carry
23
+
24
+ if __name__ == '__main__':
25
+ w = load_model()
26
+ print('3:2 Compressor Truth Table:')
27
+ print('x y z | sum carry | verify')
28
+ print('------+-----------+-------')
29
+ for x in [0, 1]:
30
+ for y in [0, 1]:
31
+ for z in [0, 1]:
32
+ s, c = compress_3to2(x, y, z, w)
33
+ check = 'OK' if (x + y + z) == (s + 2 * c) else 'FAIL'
34
+ print(f'{x} {y} {z} | {s} {c} | {check}')
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e5976fe24a7ece79751d3d87419e1db05976c6fd80f0aa5b92e3438c6ba60b0
3
+ size 1056