|
|
---
|
|
|
license: mit
|
|
|
tags:
|
|
|
- pytorch
|
|
|
- safetensors
|
|
|
- threshold-logic
|
|
|
- neuromorphic
|
|
|
- arithmetic
|
|
|
---
|
|
|
|
|
|
# threshold-fullsubtractor
|
|
|
|
|
|
Subtracts three 1-bit inputs (a, b, borrow_in), producing difference and borrow_out. The subtraction counterpart to the full adder.
|
|
|
|
|
|
## Circuit
|
|
|
|
|
|
```
|
|
|
a b
|
|
|
β β
|
|
|
βββββ¬ββββ
|
|
|
βΌ
|
|
|
βββββββββββ
|
|
|
β HS1 β First half subtractor
|
|
|
βββββββββββ
|
|
|
β β
|
|
|
d1 b1
|
|
|
β \
|
|
|
β bin \
|
|
|
ββββ¬βββ \
|
|
|
βΌ \
|
|
|
βββββββββββ \
|
|
|
β HS2 β β
|
|
|
βββββββββββ β
|
|
|
β β β
|
|
|
diff b2 β
|
|
|
β β
|
|
|
ββββ¬ββββ
|
|
|
βΌ
|
|
|
ββββββββ
|
|
|
β OR β
|
|
|
ββββββββ
|
|
|
β
|
|
|
βΌ
|
|
|
bout
|
|
|
```
|
|
|
|
|
|
## Half Subtractor Detail
|
|
|
|
|
|
```
|
|
|
x y
|
|
|
β β
|
|
|
βββββ¬ββββ€
|
|
|
β β β
|
|
|
βΌ β βΌ
|
|
|
βββββββββββββββββ βββββββββ
|
|
|
β OR βββ NAND β β Β¬x β§ yβ
|
|
|
βw:1,1 βββw:-1,-1β βw:-1,1 β
|
|
|
βb: -1 βββb: +1 β βb: -1 β
|
|
|
βββββββββββββββββ βββββββββ
|
|
|
β β β β
|
|
|
βββββΌββββ β
|
|
|
βΌ β
|
|
|
ββββββββ β
|
|
|
β AND β β
|
|
|
ββββββββ β
|
|
|
β β
|
|
|
βΌ βΌ
|
|
|
diff borrow
|
|
|
```
|
|
|
|
|
|
## Truth Table
|
|
|
|
|
|
| a | b | bin | diff | bout |
|
|
|
|---|---|-----|------|------|
|
|
|
| 0 | 0 | 0 | 0 | 0 |
|
|
|
| 0 | 0 | 1 | 1 | 1 |
|
|
|
| 0 | 1 | 0 | 1 | 1 |
|
|
|
| 0 | 1 | 1 | 0 | 1 |
|
|
|
| 1 | 0 | 0 | 1 | 0 |
|
|
|
| 1 | 0 | 1 | 0 | 0 |
|
|
|
| 1 | 1 | 0 | 0 | 0 |
|
|
|
| 1 | 1 | 1 | 1 | 1 |
|
|
|
|
|
|
Binary: a - b - bin = diff - (bout Γ 2)
|
|
|
|
|
|
## Composition
|
|
|
|
|
|
```
|
|
|
d1, b1 = HalfSubtractor(a, b)
|
|
|
diff, b2 = HalfSubtractor(d1, bin)
|
|
|
bout = OR(b1, b2)
|
|
|
```
|
|
|
|
|
|
A borrow propagates if either half subtractor produces one.
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
| Component | Neurons |
|
|
|
|-----------|---------|
|
|
|
| HS1 (a - b) | 4 |
|
|
|
| HS2 (d1 - bin) | 4 |
|
|
|
| OR (b1, b2) | 1 |
|
|
|
|
|
|
**Total: 9 neurons, 27 parameters, 4 layers**
|
|
|
|
|
|
## Contrast with Full Adder
|
|
|
|
|
|
| Circuit | Carry/Borrow | HS function |
|
|
|
|---------|--------------|-------------|
|
|
|
| FullAdder | cout = OR(c1, c2) | c = a AND b |
|
|
|
| FullSubtractor | bout = OR(b1, b2) | b = NOT(a) AND b |
|
|
|
|
|
|
The only structural difference: the borrow circuit uses NOT(a) AND b instead of AND.
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
```python
|
|
|
from safetensors.torch import load_file
|
|
|
import torch
|
|
|
|
|
|
w = load_file('model.safetensors')
|
|
|
|
|
|
def full_subtractor(a, b, bin_in):
|
|
|
inp = torch.tensor([float(a), float(b)])
|
|
|
|
|
|
# HS1
|
|
|
hs1_l1 = (inp @ w['hs1.xor.layer1.weight'].T + w['hs1.xor.layer1.bias'] >= 0).float()
|
|
|
d1 = (hs1_l1 @ w['hs1.xor.layer2.weight'].T + w['hs1.xor.layer2.bias'] >= 0).float().item()
|
|
|
b1 = (inp @ w['hs1.borrow.weight'].T + w['hs1.borrow.bias'] >= 0).float().item()
|
|
|
|
|
|
# HS2
|
|
|
inp2 = torch.tensor([d1, float(bin_in)])
|
|
|
hs2_l1 = (inp2 @ w['hs2.xor.layer1.weight'].T + w['hs2.xor.layer1.bias'] >= 0).float()
|
|
|
diff = int((hs2_l1 @ w['hs2.xor.layer2.weight'].T + w['hs2.xor.layer2.bias'] >= 0).item())
|
|
|
b2 = (inp2 @ w['hs2.borrow.weight'].T + w['hs2.borrow.bias'] >= 0).float().item()
|
|
|
|
|
|
# Final borrow
|
|
|
bout = int((torch.tensor([b1, b2]) @ w['bout.weight'].T + w['bout.bias'] >= 0).item())
|
|
|
|
|
|
return diff, bout
|
|
|
```
|
|
|
|
|
|
## Files
|
|
|
|
|
|
```
|
|
|
threshold-fullsubtractor/
|
|
|
βββ model.safetensors
|
|
|
βββ model.py
|
|
|
βββ config.json
|
|
|
βββ README.md
|
|
|
```
|
|
|
|
|
|
## License
|
|
|
|
|
|
MIT
|
|
|
|