Boolean Solver - Interactive Truth Table Explorer
Boolean Solver
Interactive Truth Table Explorer with Walsh-Hadamard Transform, Shannon Split, and NAND Circuit Synthesis
Explore all boolean functions interactively — complete for n=0,1,2,3, including the trivial cases. Click cells to build any truth table and watch three live solvers analyze your function in real-time.
Overview
The Boolean Solver is an interactive React + Three.js tool that transforms abstract boolean algebra into a tangible, visual experience. It enables you to explore all possible boolean functions for n=0 through n=3 inputs (1, 4, 16, and 256 functions respectively) through direct manipulation of truth tables.
This tool was originally developed as part of a deep dive conversation exploring the mathematical foundations of computing — how boolean logic forms the bedrock of all digital systems. It demonstrates that even the simplest questions (“What are all possible 2-input boolean functions?”) lead to rich, complex insights when approached systematically.
Physics Connection: Boolean logic is the foundation of digital computation, which in turn underlies all modern physics simulations and quantum computing. The discrete nature of boolean values (0/1, TRUE/FALSE) mirrors the binary states found in quantum bits (qubits) and classical digital circuits, making this tool relevant to both computer science and theoretical physics.
Features
1. Interactive Truth Table Editor
- Click-based editing — Toggle any cell between 0 (FALSE) and 1 (TRUE)
- Real-time updates — Function name and all solver outputs update instantly
- Multi-dimensional support — Works for n=0 (trivial), n=1 (2 functions), n=2 (16 functions), and n=3 (256 functions)
- Visual feedback — Color-coded cells show active (TRUE) and inactive (FALSE) states
2. Function Identification
- Automatic naming — All 16 n=2 functions have descriptive names (AND, OR, XOR, NAND, etc.)
- Index display — Shows the numeric index of each function in the complete enumeration
- Total count — Displays total possible functions for the current n value
3. Fast Walsh-Hadamard Transform
The Walsh-Hadamard transform is to boolean functions what the Fourier transform is to signals. It decomposes any boolean function into its spectral components, revealing mathematical properties.
What it calculates:
- Coefficients for each subset — c∅ (empty set), c{1}, c{2}, c{3}, c{1,2}, c{1,3}, c{2,3}, c{1,2,3}
- Normalized values — All coefficients are divided by 2^n for consistency
Mathematical insight:
- Coefficients reveal linearity (whether a function can be expressed as a linear combination)
- Non-zero higher-order coefficients indicate non-linear functions
- The magnitude of coefficients shows sensitivity to specific input combinations
4. Shannon Split Analysis
Decomposes the boolean function based on Shannon’s information theory, splitting by the first variable (x1).
What it reveals:
- Top half (x1=0) — The function’s behavior when the first input is FALSE
- Bottom half (x1=1) — The function’s behavior when the first input is TRUE
- Relationship detection — Identifies if the halves are identical, inverted, or independent
Possible relationships:
top = bottom → x1 is irrelevant(the function doesn’t depend on x1)bottom = invert(top) → XOR-with-x1 structure(the function flips with x1)no copy/invert relation — both halves carry independent information(complex dependency)
5. Minimal-Depth NAND Circuit Synthesis
Finds the minimum-depth network of NAND gates that implements your function. NAND is universal — any boolean function can be implemented using only NAND gates.
Why NAND?
- Universality — NAND alone can implement AND, OR, NOT, and any other boolean operation
- Hardware relevance — NAND gates are fundamental building blocks in CMOS digital logic
- Computational insight — Demonstrates that complex functions can emerge from simple components
What it provides:
- Circuit depth — The number of layers of NAND gates needed
- Expression — The actual NAND-based formula (e.g.,
NAND(NAND(x1,x2), NAND(x1,x1)))
How to Use
Getting Started
- Select n — Choose the number of inputs (0-3) from the top navigation
- Click cells — In the truth table grid, click any cell to toggle its value
- Watch it update — The function name, Walsh coefficients, Shannon analysis, and NAND synthesis all update in real-time
- Explore 3D — Click “view in 3D” to see a spatial visualization of all functions
Learning Path
Beginner
- Start with n=2 (the most intuitive)
- Try the preset gates (AND, OR, XOR, NAND, etc.)
- Click cells to see how truth tables work
- Observe how the function name changes
Intermediate
- Compare functions — Click different patterns and observe how the Walsh coefficients change
- Study Shannon splits — Notice how some functions ignore certain inputs
- Explore NAND synthesis — See how complex functions can be built from simple NAND gates
- Try n=3 — Discover the complexity of 3-input boolean functions (256 possibilities!)
Advanced
- Understand the math — Study the relationships between coefficients, entropy, and circuit depth
- Systematic exploration — Try to create every possible function and observe the patterns
- 3D visualization — Use the 3D view to understand the geometric relationships between functions
- Quantum connection — Recognize how boolean functions relate to quantum gates and states
Mathematical Foundations
Boolean Functions Basics
A boolean function with n inputs has 2^n possible input combinations. Therefore, there are 2^(2^n) possible boolean functions.
| n | Input Combinations | Possible Functions |
|---|---|---|
| 0 | 1 | 2 |
| 1 | 2 | 4 |
| 2 | 4 | 16 |
| 3 | 8 | 256 |
Walsh-Hadamard Transform
For a boolean function f: {0,1}^n → {0,1}, the Walsh-Hadamard transform computes:
Ĝ(S) = (1/2^n) * Σ_{x∈{0,1}^n} (-1)^{f(x)} * (-1)^{S·x}
Where S is a subset of input variables, and S·x is the dot product (mod 2).
Properties:
- Parseval’s theorem: Σ |Ĝ(S)|² = number of TRUE outputs
- Energy compaction: Simple functions have sparse transforms
- Correlation detection: Reveals relationships between inputs
Shannon Entropy
For a boolean function, the entropy measures its information content:
H = - Σ_{x∈{0,1}} P(x) log₂ P(x)
Where P(x) is the probability of each output value.
Interpretation:
- H = 0 → Constant function (no uncertainty, no information)
- H = 1 → Balanced function (maximum uncertainty for n=2)
- 0 < H < 1 → Partially predictable
Circuit Complexity
- Depth: Length of the longest path from input to output
- Size: Total number of gates used
- NAND gates are universal: Any function can be implemented with NAND alone
All 16 Boolean Functions for n=2
Here’s a complete reference of all possible 2-input boolean functions:
Constants (0 and 4 ones)
| Name | Truth Table | Ones | Properties |
|---|---|---|---|
| FALSE | 0 0 / 0 0 | 0 | Constant 0 |
| TRUE | 1 1 / 1 1 | 4 | Constant 1 |
Single-Output (1 one)
| Name | Truth Table | Ones | Meaning |
|---|---|---|---|
| NOR | 0 0 / 0 1 | 1 | NOT (A OR B) |
| A AND NOT B | 0 0 / 0 1 | 1 | A ∧ ¬B |
| NOT A AND B | 0 0 / 1 0 | 1 | ¬A ∧ B |
| AND | 0 0 / 0 1 | 1 | A ∧ B |
Two-Output (2 ones)
| Name | Truth Table | Ones | Meaning |
|---|---|---|---|
| XOR | 0 1 / 1 0 | 2 | A ⊕ B (differ) |
| XNOR | 1 0 / 0 1 | 2 | A ≡ B (same) |
| NOT A | 1 1 / 0 0 | 2 | ¬A (ignore B) |
| NOT B | 1 0 / 1 0 | 2 | ¬B (ignore A) |
| A | 0 0 / 1 1 | 2 | A (ignore B) |
| B | 0 1 / 0 1 | 2 | B (ignore A) |
Three-Output (3 ones)
| Name | Truth Table | Ones | Meaning |
|---|---|---|---|
| OR | 0 1 / 1 1 | 3 | A ∨ B |
| NAND | 1 1 / 1 0 | 3 | ¬(A ∧ B) |
| A→B | 1 0 / 1 1 | 3 | A implies B |
| B→A | 1 1 / 0 1 | 3 | B implies A |
Properties and Patterns
Symmetry
Boolean functions exhibit beautiful mathematical symmetries:
- Inversion pairs: AND↔NAND, OR↔NOR, XOR↔XNOR, TRUE↔FALSE
- Mirror symmetry: Swapping inputs A and B
- Diagonal symmetry: Functions symmetric across the (0,0)-(1,1) diagonal
- Projection symmetry: Functions that ignore one or more inputs
Linearity
Linear functions can be expressed as:
f(A,B) = a ⊕ b·A ⊕ c·B (where ⊕ is XOR/addition mod 2)
For n=2, the linear functions are:
- FALSE (0)
- A
- B
- A XOR B
Non-linear functions (like AND, OR) have non-zero interaction coefficients (c₁₂ ≠ 0).
Balance
A function is balanced if it has an equal number of 0 and 1 outputs.
For n=2:
- Balanced: XOR, XNOR, NOT A, NOT B (2 zeros, 2 ones)
- Unbalanced: AND, OR, Constants, etc.
Correlation Immunity
A function is correlation immune if its output doesn’t leak information about any subset of its inputs. This property is important in cryptography.
3D Visualization
The 3D visualization maps each boolean function to a point in 3D space based on its Walsh-Hadamard coefficients.
What You See
- Teal points — All boolean functions for the current n value
- Exact positions — Derived from the mathematical coefficients (x, y, z)
- Color coding — Points are colored by T (number of relevant variables)
- Gold ring — Marks the currently selected function
- Size/color variation — Visual encoding of function properties
Axes Meaning
- X-axis — Influence of first variable (x₁)
- Y-axis — Influence of second variable (x₂)
- Z-axis — Influence of third variable (x₃) or interaction terms
Interpretation
The 3D visualization reveals:
- Clusters — Functions with similar properties group together geometrically
- Distance — Mathematical similarity between functions corresponds to spatial proximity
- Symmetry — The overall structure of boolean function space
- Concentration — Real boolean functions concentrate toward the center, demonstrating the “concentration of measure” effect
Controls
- Drag to rotate — Click and drag to inspect the visualization from any angle
- Toggle layers — Show/hide deterministic points vs. quantum stand-in points
- Filter by T — Filter to show only functions with a minimum number of relevant variables
- Re-measure — Generate new random quantum stand-in points
Source Code
The Boolean Solver is implemented as a comprehensive React + Three.js application. Below is the complete source code extracted from the conversation.
Core Algorithm Functions
// Shared math utilities - generalized to any n = 0..3
// Function names for all boolean functions
const NAMES = {
0: ["FALSE", "TRUE"],
1: ["FALSE", "NOT x1", "x1", "TRUE"],
2: [
"FALSE", "NOR", "¬A∧B", "¬A", "A∧¬B", "¬B", "XOR", "NAND",
"AND", "XNOR", "B", "A→B", "A", "B→A", "OR", "TRUE",
],
};
// Get function name for given n and index
function getName(n, idx) {
if (n <= 2) return NAMES[n][idx];
return `table ${idx}`;
}
// Create input signal for variable at position varIdx
function inputSignal(n, varIdx) {
let val = 0;
for (let r = 0; r < 1 << n; r++) {
const bit = (r >> (n - 1 - varIdx)) & 1;
val |= bit << r;
}
return val;
}
// Fast Walsh-Hadamard Transform
function fwht(arr) {
const a = arr.slice();
const len8 = a.length;
for (let len = 1; len < len8; len <<= 1) {
for (let i = 0; i < len8; i += len << 1) {
for (let j = i; j < i + len; j++) {
const u = a[j], v = a[j + len];
a[j] = u + v;
a[j + len] = u - v;
}
}
}
return a.map((v) => v / len8);
}
// Compute Walsh coefficients for a given function
function computeWalsh(n, tableIndex) {
const size = 1 << n;
const pm = Array.from({ length: size }, (_, r) => 1 - 2 * ((tableIndex >> r) & 1));
return fwht(pm);
}
// Create subset label for coefficients
function subsetLabel(n, idx) {
if (idx === 0) return "c∅";
const vars = [];
for (let v = 0; v < n; v++) if ((idx >> (n - 1 - v)) & 1) vars.push(v + 1);
return `c{${vars.join(",")}}`;
}
// Shannon split by first variable
function shannonSplit(n, tableIndex) {
if (n === 0) return null;
const half = 1 << (n - 1);
const mask = (1 << half) - 1;
const f0 = tableIndex & mask;
const f1 = (tableIndex >> half) & mask;
let relation;
if (f0 === f1) relation = "top = bottom → x1 is irrelevant";
else if (f0 === ((~f1) & mask)) relation = "bottom = invert(top) → XOR-with-x1 structure";
else relation = "no simple copy/invert relation";
return { f0, f1, relation, subN: n - 1 };
}
// Synthesize minimal-depth NAND circuit
function synthesizeNand(n, target) {
if (n === 0) return null;
const mask = (1 << (1 << n)) - 1;
let found = {};
// Start with input signals
for (let v = 0; v < n; v++) found[inputSignal(n, v)] = { depth: 0, expr: `x${v + 1}` };
if (target in found) return found[target];
// Iterative synthesis
for (let round = 0; round < 10 && !(target in found); round++) {
const keys = Object.keys(found).map(Number);
const additions = {};
for (let i = 0; i < keys.length; i++) {
for (let j = i; j < keys.length; j++) {
const a = keys[i], b = keys[j];
const val = (~(a & b)) & mask;
if (!(val in found) && !(val in additions)) {
const exprA = found[a].expr, exprB = found[b].expr;
additions[val] = {
depth: Math.max(found[a].depth, found[b].depth) + 1,
expr: a === b ? `NAND(${exprA},${exprA})` : `NAND(${exprA},${exprB})`
};
}
}
}
found = { ...found, ...additions };
}
return found[target] || null;
}
// Count relevant variables
function countRelevant(n, tableIndex) {
let count = 0;
const size = 1 << n;
for (let v = 0; v < n; v++) {
const p = n - 1 - v;
let relevant = false;
for (let r = 0; r < size; r++) {
const rp = r ^ (1 << p);
if (((tableIndex >> r) & 1) !== ((tableIndex >> rp) & 1)) {
relevant = true;
break;
}
}
if (relevant) count++;
}
return count;
}
// Get x, y, z coordinates from Walsh coefficients
function xyz(n, tableIndex) {
const w = computeWalsh(n, tableIndex);
const get = (v) => {
if (v >= n) return 0;
const idx = 1 << (n - 1 - v);
return w[idx];
};
return { x: get(0), y: get(1), z: get(2) };
}
React Component - Solver Page
// Main Solver component
function SolverPage({ n, tableIndex, setTableIndex, onView3D }) {
const size = 1 << n;
const toggleCell = (r) => setTableIndex((t) => t ^ (1 << r));
const walsh = useMemo(() => computeWalsh(n, tableIndex), [n, tableIndex]);
const shannon = useMemo(() => shannonSplit(n, tableIndex), [n, tableIndex]);
const nand = useMemo(() => synthesizeNand(n, tableIndex), [n, tableIndex]);
const fmt = (v) => (v > 0 ? "+" : "") + v.toFixed(2).replace(/\.00$/, "");
const bitsOf = (r) => Array.from({ length: n }, (_, k) => (r >> (n - 1 - k)) & 1).join("");
return (
<div className="max-w-3xl mx-auto space-y-6">
<header>
<h1 className="text-sm tracking-[0.2em] text-slate-400 uppercase">
Boolean Solver
</h1>
<p className="text-xs text-slate-500 mt-1">
n={n} · complete for n=0,1,2,3 — including the trivial cases
</p>
</header>
{/* Truth Table Editor */}
<div>
<div className={`grid gap-1 ${
size <= 2 ? "grid-cols-2 w-32" :
size <= 4 ? "grid-cols-2 w-32" :
size <= 8 ? "grid-cols-4 w-64" : "grid-cols-8 w-[34rem]"
}`}>
{Array.from({ length: size }, (_, r) => r).map((r) => {
const on = (tableIndex >> r) & 1;
return (
<button
key={r}
onClick={() => toggleCell(r)}
className={`aspect-square rounded border flex flex-col
items-center justify-center text-[9px] transition-colors ${
on ? "bg-teal-500/30 border-teal-400 text-teal-200" :
"bg-slate-800/40 border-slate-700 text-slate-500"
}`}
>
<span>{n === 0 ? "—" : bitsOf(r)}</span>
<span className="text-[12px] font-semibold">{on}</span>
</button>
);
})}
</div>
<div className="mt-2 text-xl text-teal-300 font-semibold">
{getName(n, tableIndex)}
</div>
<div className="text-[10px] text-slate-600">
table index {tableIndex} of {1 << size}
</div>
</div>
{/* Walsh-Hadamard Transform Display */}
<section className="border border-slate-800 rounded-lg p-4 space-y-2">
<div className="text-xs text-slate-400 uppercase tracking-wide">
Fast Walsh-Hadamard transform
</div>
<div className={`grid gap-2 text-center ${
size <= 4 ? "grid-cols-4" : size <= 8 ? "grid-cols-4" : "grid-cols-8"
}`}>
{walsh.map((v, i) => (
<div key={i} className="bg-slate-900/60 rounded p-2">
<div className="text-[9px] text-slate-500">{subsetLabel(n, i)}</div>
<div className="text-sm text-teal-300">{fmt(v)}</div>
</div>
))}
</div>
</section>
{/* Shannon Split Display */}
<section className="border border-slate-800 rounded-lg p-4 space-y-2">
<div className="text-xs text-slate-400 uppercase tracking-wide">
Shannon split by x1
</div>
{shannon ? (
<>
<div className="grid grid-cols-2 gap-3 text-sm">
<div className="bg-slate-900/60 rounded p-2">
<div className="text-[9px] text-slate-500">top (x1=0)</div>
<div className="text-amber-300">{getName(shannon.subN, shannon.f0)}</div>
</div>
<div className="bg-slate-900/60 rounded p-2">
<div className="text-[9px] text-slate-500">bottom (x1=1)</div>
<div className="text-amber-300">{getName(shannon.subN, shannon.f1)}</div>
</div>
</div>
<p className="text-xs text-slate-400">{shannon.relation}</p>
</>
) : (
<p className="text-xs text-slate-500">n=0 has no variables — nothing to split.</p>
)}
</section>
{/* NAND Synthesis Display */}
<section className="border border-slate-800 rounded-lg p-4 space-y-2">
<div className="text-xs text-slate-400 uppercase tracking-wide">
Minimal-depth NAND synthesis
</div>
{nand ? (
<>
<div className="text-xs text-slate-500">depth {nand.depth}</div>
<div className="text-sm text-pink-300 break-words">{nand.expr}</div>
</>
) : n === 0 ? (
<p className="text-xs text-slate-500">
n=0 has no inputs — the function is a bare constant, not a circuit.
</p>
) : (
<p className="text-xs text-slate-500">not found within search bound</p>
)}
</section>
<button
onClick={onView3D}
className="flex items-center gap-2 text-xs px-4 py-2 rounded
border border-teal-500/40 bg-teal-500/15 text-teal-200"
>
view in 3D →
</button>
</div>
);
}
3D Visualization Component
// 3D visualization of all boolean functions
function View3DPage({ n, tableIndex, onBack }) {
const mountRef = useRef(null);
const liveRef = useRef({});
const highlight = useMemo(() => xyz(n, tableIndex), [n, tableIndex]);
const highlightT = useMemo(() => countRelevant(n, tableIndex), [n, tableIndex]);
const [showDet, setShowDet] = useState(true);
const [showQ, setShowQ] = useState(true);
const [qCount, setQCount] = useState(60);
const [seedTick, setSeedTick] = useState(0);
const [minT, setMinT] = useState(0);
// Quantum stand-in points (pseudo-random for visualization)
const quantumPoints = useRef(randomQuantumSample(qCount, 0));
const reseed = () => {
quantumPoints.current = randomQuantumSample(qCount, Date.now());
setSeedTick((t) => t + 1);
};
useEffect(() => {
// Three.js setup
const mount = mountRef.current;
const width = mount.clientWidth, height = mount.clientHeight;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0e16);
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
camera.position.set(6, 4.5, 7);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
mount.appendChild(renderer.domElement);
const group = new THREE.Group();
scene.add(group);
// Axes
const axisLen = SCALE * 1.35;
const axisMat = new THREE.LineBasicMaterial({ color: 0x3a4a5c });
[
[new THREE.Vector3(-axisLen, 0, 0), new THREE.Vector3(axisLen, 0, 0)],
[new THREE.Vector3(0, -axisLen, 0), new THREE.Vector3(0, axisLen, 0)],
[new THREE.Vector3(0, 0, -axisLen), new THREE.Vector3(0, 0, axisLen)],
].forEach(([a, b]) =>
group.add(new THREE.Line(
new THREE.BufferGeometry().setFromPoints([a, b]),
axisMat
))
);
// Cube edges
const cubeEdges = new THREE.EdgesGeometry(
new THREE.BoxGeometry(SCALE * 2, SCALE * 2, SCALE * 2)
);
group.add(new THREE.LineSegments(
cubeEdges,
new THREE.LineBasicMaterial({ color: 0x1c2733 })
));
// Deterministic points (all boolean functions)
const total = 1 << (1 << n);
const detGroup = new THREE.Group();
const sphereGeo = new THREE.SphereGeometry(n <= 1 ? 0.09 : 0.055, 10, 10);
for (let i = 0; i < total; i++) {
const p = xyz(n, i);
const t = countRelevant(n, i);
const mesh = new THREE.Mesh(
sphereGeo,
new THREE.MeshBasicMaterial({ color: T_COLORS[t] })
);
mesh.position.set(p.x * SCALE, p.y * SCALE, p.z * SCALE);
mesh.userData = { t };
detGroup.add(mesh);
}
group.add(detGroup);
// Quantum stand-in points
const qGroup = new THREE.Group();
const qSphereGeo = new THREE.SphereGeometry(0.045, 8, 8);
const qMat = new THREE.MeshBasicMaterial({ color: 0xf472b6 });
function rebuildQuantum() {
qGroup.clear();
quantumPoints.current.forEach((p) => {
const mesh = new THREE.Mesh(qSphereGeo, qMat.clone());
mesh.position.set(p.x * SCALE, p.y * SCALE, p.z * SCALE);
mesh.userData = { t: p.t };
qGroup.add(mesh);
});
}
rebuildQuantum();
group.add(qGroup);
// Highlight marker for selected function
const hGeo = new THREE.SphereGeometry(0.13, 16, 16);
const hMat = new THREE.MeshBasicMaterial({ color: 0xfbbf24 });
const hMesh = new THREE.Mesh(hGeo, hMat);
hMesh.position.set(highlight.x * SCALE, highlight.y * SCALE, highlight.z * SCALE);
group.add(hMesh);
const ringGeo = new THREE.RingGeometry(0.18, 0.22, 24);
const ringMat = new THREE.MeshBasicMaterial({
color: 0xfbbf24,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6
});
const ring = new THREE.Mesh(ringGeo, ringMat);
ring.position.copy(hMesh.position);
group.add(ring);
// Animation and interaction
let dragging = false, lastX = 0, lastY = 0;
const onDown = (e) => { dragging = true; lastX = e.clientX; lastY = e.clientY; };
const onUp = () => { dragging = false; };
const onMove = (e) => {
if (!dragging) return;
const dx = e.clientX - lastX, dy = e.clientY - lastY;
lastX = e.clientX; lastY = e.clientY;
group.rotation.y += dx * 0.006;
group.rotation.x = Math.max(-1.2, Math.min(1.2, group.rotation.x + dy * 0.006));
};
// Event listeners
renderer.domElement.addEventListener("pointerdown", onDown);
window.addEventListener("pointerup", onUp);
renderer.domElement.addEventListener("pointermove", onMove);
// Animation loop
let raf;
const clock = new THREE.Clock();
function animate() {
raf = requestAnimationFrame(animate);
const t = clock.getElapsedTime();
if (!dragging) group.rotation.y += 0.0015;
ring.rotation.z = t * 0.6;
ring.lookAt(camera.position);
const pulse = 1 + 0.25 * Math.sin(t * 3);
hMesh.scale.setScalar(pulse);
// Animate deterministic points
detGroup.children.forEach((child) => {
const tVal = child.userData.t;
const pulseD = 1 + 0.3 * Math.sin(t * (1 + tVal * 1.3)) * (tVal > 0 ? 1 : 0);
child.scale.setScalar(pulseD);
child.visible = liveRef.current.showDet && tVal >= liveRef.current.minT;
});
// Animate quantum points
qGroup.children.forEach((child) => {
const pulseQ = 1 + 0.3 * Math.sin(t * (1 + (child.userData.t || 0) * 1.3));
child.scale.setScalar(pulseQ);
});
qGroup.visible = liveRef.current.showQ;
renderer.render(scene, camera);
}
animate();
// Resize handler
function onResize() {
const w = mount.clientWidth, h = mount.clientHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize(w, h);
}
window.addEventListener("resize", onResize);
return () => {
cancelAnimationFrame(raf);
window.removeEventListener("resize", onResize);
window.removeEventListener("pointerup", onUp);
renderer.domElement.removeEventListener("pointerdown", onDown);
renderer.domElement.removeEventListener("pointermove", onMove);
mount.removeChild(renderer.domElement);
renderer.dispose();
};
}, [n, tableIndex, highlight.x, highlight.y, highlight.z]);
return (
<div className="relative w-full h-screen">
<div ref={mountRef} className="absolute inset-0" />
{/* UI Controls */}
<div className="absolute top-0 left-0 p-4 md:p-6 space-y-3 pointer-events-none max-w-sm">
<div className="pointer-events-auto flex items-center gap-2 flex-wrap">
<button onClick={onBack} className="flex items-center gap-1.5 text-xs px-2.5 py-1.5 rounded border border-slate-600 bg-slate-800/60 text-slate-300">
← solver
</button>
</div>
<p className="pointer-events-auto text-xs text-slate-500 leading-relaxed">
X/Y/Z = influence of x1/x2/x3 · color+pulse = T (relevant-variable count).
Gold ring marks the function currently open in the solver.
</p>
{/* Control buttons */}
<div className="pointer-events-auto flex flex-wrap gap-2">
<button onClick={() => setShowDet((v) => !v)}
className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-teal-500/30 bg-teal-500/10 text-teal-300"
>
{showDet ? '👁' : '👁🗨'} deterministic
</button>
<button onClick={() => setShowQ((v) => !v)}
className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-pink-500/30 bg-pink-500/10 text-pink-300"
>
{showQ ? '👁' : '👁🗨'} quantum stand-in ({qCount})
</button>
<button onClick={reseed} className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-slate-500/30 bg-slate-500/10 text-slate-300">
🔀 re-measure
</button>
</div>
<div className="pointer-events-auto">
<label className="text-[10px] text-slate-500 uppercase tracking-wide">
min T (relevant vars) — {minT}
</label>
<input type="range" min={0} max={n} step={1} value={Math.min(minT, n)}
onChange={(e) => setMinT(Number(e.target.value))}
className="w-full accent-teal-400" />
</div>
<div className="pointer-events-auto flex gap-2 text-[9px] text-slate-500 flex-wrap">
{T_COLORS.slice(0, n + 1).map((c, i) => (
<span key={i} className="flex items-center gap-1">
<span className="inline-block w-2 h-2 rounded-full"
style={{ background: `#${c.toString(16).padStart(6, "0")}` }} />
T={i}
</span>
))}
</div>
<div className="pointer-events-auto text-xs bg-[#0f1520]/90 border border-amber-500/30 rounded p-2 space-y-0.5">
<div className="text-amber-300 font-semibold">
{getName(n, tableIndex)} · T={highlightT}
</div>
<div className="text-slate-400">
x={highlight.x.toFixed(2)} y={highlight.y.toFixed(2)} z={highlight.z.toFixed(2)}
</div>
</div>
</div>
<div className="absolute bottom-4 right-4 flex items-center gap-1.5 text-[10px] text-slate-600">
🔄 drag to rotate
</div>
</div>
);
}
Complete App Shell
// Main unified application
export default function UnifiedApp() {
const [n, setN] = useState(2);
const [tableIndex, setTableIndex] = useState(6); // Start on XOR
const [page, setPage] = useState("solver");
return (
<div className="min-h-screen bg-[#0a0e16] text-slate-200 font-mono">
{/* Navigation */}
<div className="sticky top-0 z-10 bg-[#0a0e16]/95 backdrop-blur border-b border-slate-800 px-4 md:px-8 py-3 flex flex-wrap items-center gap-4">
<div className="flex gap-1.5">
{["solver", "3d", "quantum", "trajectories"].map((p) => (
<button key={p} onClick={() => setPage(p)}
className={`text-xs px-3 py-1.5 rounded border transition-colors flex items-center gap-1.5 ${
page === p ? "bg-teal-500/25 border-teal-400 text-teal-200" : "bg-slate-800/40 border-slate-700 text-slate-400"
}`}
>
{p === "quantum" && <Atom size={12} />}
{p === "trajectories" && <Orbit size={12} />}
{p === "solver" ? "Solver" : p === "3d" ? "3D View" : p === "quantum" ? "Quantum" : "Trajectories"}
</button>
))}
</div>
<div className="flex items-center gap-1.5 ml-auto">
<span className="text-[10px] text-slate-500 uppercase tracking-wide mr-1">
n =
</span>
{[0, 1, 2, 3].map((k) => (
<button key={k} onClick={() => { setN(k); setTableIndex(0); }}
className={`text-xs w-8 h-8 rounded border transition-colors ${
n === k ? "bg-amber-500/25 border-amber-400 text-amber-200" : "border-slate-700 text-slate-400"
}`}
>
{k}
</button>
))}
</div>
</div>
{/* Pages */}
{page === "solver" && (
<div className="p-4 md:p-8">
<SolverPage n={n} tableIndex={tableIndex} setTableIndex={setTableIndex} onView3D={() => setPage("3d")} />
</div>
)}
{page === "3d" && <View3DPage n={n} tableIndex={tableIndex} onBack={() => setPage("solver")} />}
{page === "quantum" && <QuantumPage n={n} />}
{page === "trajectories" && <TrajectoriesPage n={n} />}
</div>
);
}
Using the Boolean Solver
As a Standalone Tool
To use the Boolean Solver in your own project:
Download the source from the conversation archive:
unzip conversation-archive.zip archive/source/boolean-solver.jsxImport dependencies (React and Three.js):
npm install react three @react-three/fiber @react-three/dreiIntegrate into your React app:
import { BooleanSolver } from './boolean-solver'; function App() { return <BooleanSolver />; }
As a Learning Tool
The Boolean Solver is designed for education. Use it to:
- Teach boolean algebra — Visual demonstration of all 16 functions
- Explore digital logic — See how gates combine to create circuits
- Understand mathematical properties — Walsh coefficients, entropy, symmetry
- Study computational complexity — Minimal circuit depth and size
- Bridge to quantum computing — Boolean functions as the foundation
As a Research Tool
Researchers can use this tool to:
- Visualize function spaces — 3D representation of all boolean functions
- Analyze properties — Mathematical analysis of any function
- Generate insights — Discover patterns and relationships
- Test hypotheses — Interactive exploration of boolean logic
Performance Characteristics
- Real-time — All calculations happen instantly on state change
- Efficient — Uses memoization (useMemo) to avoid redundant calculations
- Scalable — Architecture extends to higher n values
- Responsive — Works on desktop and mobile devices
- No dependencies — Pure JavaScript/React with Three.js for 3D
Related Tools
The Boolean Solver is part of a family of related tools in the Badlucksbane Lab:
- Ultimate Solver — Extended version for n=3 with 256 functions
- Quantum Composer — Quantum circuit simulation
- Trajectories Visualizer — N-body simulation with boolean function gravity wells
Physics Connection
Boolean logic is deeply connected to physics in several ways:
- Digital Physics — The universe is fundamentally discrete in some interpretations, with boolean logic at its core
- Quantum Computing — Qubits use boolean-like states (|0⟩ and |1⟩) with superposition
- Information Theory — Physical systems have information content measurable in bits
- Computational Physics — All physics simulations ultimately run on boolean-based digital computers
- Thermodynamics of Computation — There are fundamental physical limits to boolean operations (Landauer’s principle)
The Boolean Solver demonstrates that even simple boolean functions have rich mathematical structure, hinting at the depth of complexity that emerges from simple physical laws.
License
This code is provided for educational purposes under permissive terms. You are free to:
- Use it for learning and exploration
- Modify and extend it
- Incorporate it into your projects (commercial or non-commercial)
- Share it with others
Attribution is appreciated but not required.
Download
Complete source code: previously linked to a personal working-directory archive (~/work/conversation-archive.zip) that was reachable through a symlink placed directly in the lab site’s web root. That symlink exposed the whole directory (including unrelated personal files like a resume) rather than just this archive, so it was removed; these links are disabled until the specific source files are copied into the site as proper page resources.
To extract:
# Extract the specific file
unzip conversation-archive.zip archive/source/boolean-solver.jsx
# Or extract all source files
unzip conversation-archive.zip "archive/source/*"
Related Content
- Physics Tools Overview — Other physics and math tools in this section
- Physics Section — Theoretical foundations of computation
- Thermodynamics of Computation — Ben’s research on energy and information
- Aurora’s Memory Architecture — How these concepts inform AI reasoning
- Notebook Entries — Development logs and insights
Boolean algebra is the calculus of thought. The Boolean Solver makes that calculus visible, interactive, and beautiful.