Tiny Verified Logic Circuits
Collection
Formally verified threshold logic circuits. Compatible with neuromorphic hardware.
•
33 items
•
Updated
Formally verified full adder circuit. Adds three 1-bit inputs (a, b, carry_in), producing sum and carry_out outputs with 100% accuracy.
| Component | Value |
|---|---|
| Inputs | 3 (a, b, carry_in) |
| Outputs | 2 (sum, carry_out) |
| Neurons | 9 (2 HalfAdders + OR) |
| Parameters | 27 |
| Depth | 3 layers |
| Activation | Heaviside step |
Composed from two half adders and an OR gate:
HalfAdder1: (a, b) -> (s1, c1)
HalfAdder2: (s1, carry_in) -> (sum, c2)
carry_out = OR(c1, c2)
Components:
import torch
from safetensors.torch import load_file
weights = load_file('fulladder.safetensors')
def heaviside(x):
return int(x >= 0)
def full_adder(a, b, carry_in):
# HalfAdder1: (a, b) -> (s1, c1)
inputs_ha1 = torch.tensor([float(a), float(b)])
or_out1 = heaviside((inputs_ha1 * weights['ha1.sum.layer1.or.weight']).sum() +
weights['ha1.sum.layer1.or.bias'])
nand_out1 = heaviside((inputs_ha1 * weights['ha1.sum.layer1.nand.weight']).sum() +
weights['ha1.sum.layer1.nand.bias'])
layer1_outs1 = torch.tensor([float(or_out1), float(nand_out1)])
s1 = heaviside((layer1_outs1 * weights['ha1.sum.layer2.weight']).sum() +
weights['ha1.sum.layer2.bias'])
c1 = heaviside((inputs_ha1 * weights['ha1.carry.weight']).sum() +
weights['ha1.carry.bias'])
# HalfAdder2: (s1, carry_in) -> (sum, c2)
inputs_ha2 = torch.tensor([float(s1), float(carry_in)])
or_out2 = heaviside((inputs_ha2 * weights['ha2.sum.layer1.or.weight']).sum() +
weights['ha2.sum.layer1.or.bias'])
nand_out2 = heaviside((inputs_ha2 * weights['ha2.sum.layer1.nand.weight']).sum() +
weights['ha2.sum.layer1.nand.bias'])
layer1_outs2 = torch.tensor([float(or_out2), float(nand_out2)])
sum_out = heaviside((layer1_outs2 * weights['ha2.sum.layer2.weight']).sum() +
weights['ha2.sum.layer2.bias'])
c2 = heaviside((inputs_ha2 * weights['ha2.carry.weight']).sum() +
weights['ha2.carry.bias'])
# Carry out: OR(c1, c2)
carry_inputs = torch.tensor([float(c1), float(c2)])
carry_out = heaviside((carry_inputs * weights['carry_or.weight']).sum() +
weights['carry_or.bias'])
return sum_out, carry_out
# Test
print(full_adder(0, 0, 0)) # (0, 0)
print(full_adder(1, 1, 0)) # (0, 1) - 1+1=2, sum=0, carry=1
print(full_adder(1, 1, 1)) # (1, 1) - 1+1+1=3, sum=1, carry=1
| a | b | cin | sum | cout |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
Coq Theorem:
Theorem full_adder_correct : forall a b c,
full_adder a b c = full_adder_spec a b c.
Where full_adder_spec computes:
sum = a XOR b XOR ccarry_out = (a AND b) OR (c AND (a XOR b))Proven axiom-free with verified properties:
Full proof: coq-circuits/Arithmetic/FullAdder.v
@software{tiny_fulladder_verified_2025,
title={tiny-FullAdder-verified: Formally Verified Full Adder},
author={Norton, Charles},
url={https://huggingface.co/phanerozoic/tiny-FullAdder-verified},
year={2025}
}