Minimum-magnitude threshold circuit for XNOR (equivalence). Magnitude 7 is optimal via exhaustive enumeration of all 224,143 configurations.
x1 x2
│ │
│ │
┌────┴───────┴────┐
│ │
▼ ▼
┌─────┐ ┌─────┐
│ N1 │ │ N2 │ Layer 1
│[-1,-1] │[-1,-1]
│ b=0 │ │ b=1 │
└──┬──┘ └──┬──┘
│ │
│ ┌────────────┘
│ │
▼ ▼
┌──────┐
│ OUT │ Layer 2
│[1,-1]│
│ b=0 │
└──┬───┘
│
▼
XNOR(x1,x2)
Both solutions use weights from {-1, 0, 1} only. They are related by neuron permutation symmetry (swap N1 ↔ N2).
XNOR has fewer solutions because OR at layer 2 creates tighter constraints than XOR's AND.
Original XNOR (magnitude 9):
NOR: [-1,-1], b=0 → magnitude 2
AND: [1, 1], b=-2 → magnitude 4 ← costly -2 bias
OR: [1, 1], b=-1 → magnitude 3
Optimized (magnitude 7, solution 1):
N1: [-1,-1], b=0 → magnitude 2
N2: [-1,-1], b=1 → magnitude 3
OUT: [1,-1], b=0 → magnitude 2 ← zero bias
1from safetensors.torch import load_file
2import torch
3
4w = load_file('solution1.safetensors')
5
6def xnor_gate(x1, x2):
7 inp = torch.tensor([float(x1), float(x2)])
8
9 n1 = int((inp * w['layer1.neuron1.weight']).sum() + w['layer1.neuron1.bias'] >= 0)
10 n2 = int((inp * w['layer1.neuron2.weight']).sum() + w['layer1.neuron2.bias'] >= 0)
11
12 hid = torch.tensor([float(n1), float(n2)])
13 return int((hid * w['layer2.weight']).sum() + w['layer2.bias'] >= 0)
14
15# Test
16assert xnor_gate(0, 0) == 1 # same
17assert xnor_gate(0, 1) == 0 # different
18assert xnor_gate(1, 0) == 0 # different
19assert xnor_gate(1, 1) == 1 # same
threshold-xnor-mag7/
├── solution1.safetensors # First solution
├── solution2.safetensors # Second solution (neuron swap)
├── model.py # Python implementation
├── config.json # Metadata
├── create_safetensors.py # Script to generate weights
└── README.md