Representations Guide
BooFun supports 10+ representations of Boolean functions with automatic conversion between them.
Bit-Ordering Convention
BooFun uses LSB = x₀ (least significant bit is variable 0):
# Truth table index i corresponds to:
# x₀ = (i >> 0) & 1
# x₁ = (i >> 1) & 1
# x₂ = (i >> 2) & 1
# ...
# Example: index 5 = 0b101 means x₀=1, x₁=0, x₂=1
import boofun as bf
# Dictator x₀ has truth table [0,1,0,1,0,1,0,1]
# because x₀=1 for odd indices (where bit 0 is set)
x0 = bf.dictator(3, 0)
print(list(x0.get_representation("truth_table")))
# [0, 1, 0, 1, 0, 1, 0, 1]
# Dictator x₂ has truth table [0,0,0,0,1,1,1,1]
# because x₂=1 for indices 4-7 (where bit 2 is set)
x2 = bf.dictator(3, 2)
print(list(x2.get_representation("truth_table")))
# [0, 0, 0, 0, 1, 1, 1, 1]
This convention is consistent across all functions, including weighted majority:
# weights[0] applies to x₀, weights[1] applies to x₁, etc.
f = bf.weighted_majority([5, 1, 1, 1, 1])
print(f.influences())
# x₀ has highest influence because it has highest weight
Overview
Boolean functions can be represented in many ways, each suited for different tasks:
Representation |
Best For |
|---|---|
Truth table |
Fast evaluation, small n |
Fourier expansion |
Spectral analysis |
ANF |
Algebraic analysis, cryptography |
DNF/CNF |
Logic, SAT solving |
BDD |
Compact storage, verification |
Circuit |
Complexity analysis |
LTF |
Weighted voting, learning |
Available Representations
Truth Tables
Dense array of function outputs.
Name |
Description |
Memory |
Access |
|---|---|---|---|
|
Dense NumPy array |
O(2^n) |
O(1) |
|
Only true inputs |
O(k) |
O(1) |
|
Bit-packed array |
O(2^n / 8) |
O(1) |
import boofun as bf
# Dense truth table (default)
f = bf.create([0, 1, 1, 0])
# Access truth table
tt = f.get_representation("truth_table")
print(f"Truth table: {tt}")
# For large sparse functions
sparse_f = bf.create({(0, 1), (1, 0)}, n=2) # Only true inputs
sparse_tt = sparse_f.get_representation("sparse_truth_table")
Fourier Expansion
Fourier coefficients over the Boolean hypercube.
f = bf.majority(5)
# Get Fourier expansion
fourier = f.get_representation("fourier_expansion")
# Access coefficients
print(f"f̂(∅) = {f.fourier_coefficient(frozenset()):.4f}")
print(f"f̂({{0}}) = {f.fourier_coefficient(frozenset([0])):.4f}")
Algebraic Normal Form (ANF)
Polynomial over GF(2) - XOR of AND terms.
f = bf.create([0, 0, 0, 1]) # AND function
anf = f.get_representation("anf")
print(f"ANF: {anf}")
# Output: x0 ∧ x1 (or similar notation)
# Algebraic degree
from boofun.analysis import cryptographic
deg = cryptographic.algebraic_degree(f)
print(f"Algebraic degree: {deg}")
Real Polynomial
Polynomial over the reals (multilinear).
f = bf.majority(3)
poly = f.get_representation("polynomial")
# Represents f as sum of monomials with real coefficients
DNF/CNF
Disjunctive/Conjunctive Normal Forms.
f = bf.create([0, 0, 0, 1, 0, 1, 1, 1]) # Threshold function
# Get DNF (OR of ANDs)
dnf = f.get_representation("dnf")
# Get CNF (AND of ORs)
cnf = f.get_representation("cnf")
Binary Decision Diagram (BDD)
Compact graph representation.
f = bf.tribes(2, 4)
bdd = f.get_representation("bdd")
print(f"BDD nodes: {bdd.node_count()}")
Circuit
Boolean circuit representation.
f = bf.majority(5)
circuit = f.get_representation("circuit")
print(f"Circuit depth: {circuit.depth()}")
print(f"Circuit size: {circuit.size()}")
Linear Threshold Function (LTF)
Weighted voting representation: f(x) = sign(w·x - θ).
# Create weighted majority
weights = [3, 2, 1, 1, 1]
f = bf.weighted_majority(weights)
ltf = f.get_representation("ltf")
print(f"Weights: {ltf.weights}")
print(f"Threshold: {ltf.threshold}")
Symbolic
Human-readable string expression.
f = bf.create("x0 and (x1 or not x2)", n=3)
symbolic = f.get_representation("symbolic")
print(f"Expression: {symbolic}")
Automatic Conversion
BooFun automatically converts between representations as needed.
Getting Any Representation
f = bf.majority(5)
# Get any representation - auto-converts if needed
fourier = f.get_representation("fourier_expansion")
anf = f.get_representation("anf")
dnf = f.get_representation("dnf")
# Converted representations are cached
Convert In Place
f = bf.create([0, 1, 1, 0])
# Convert to different representation
f.convert_to("fourier_expansion")
# Now Fourier is the primary representation
Check Conversion Paths
from boofun.core.conversion_graph import get_conversion_path, can_convert
# Check if conversion is possible
if can_convert("truth_table", "bdd"):
path = get_conversion_path("truth_table", "bdd")
print(f"Conversion path: {' -> '.join(path)}")
Storage Hints
For large functions, specify storage format hints.
Packed Truth Tables
8x memory savings for large n.
# Create with packed storage
f = bf.create(large_truth_table, storage="packed")
# Or hint during creation
from boofun import create
f = create(data, storage="packed")
Sparse Storage
Efficient when few inputs are true.
# For functions with <30% true inputs
f = bf.create(sparse_data, storage="sparse")
# Auto-detection
f = bf.create(data, storage="auto") # Chooses best format
Memory Comparison
from boofun.core.representations.packed_truth_table import memory_comparison
# Compare memory usage for n=20
comparison = memory_comparison(20)
print(comparison)
# packed_bitarray: 131,072 bytes (128.0 KB)
# numpy_bool: 1,048,576 bytes (1024.0 KB)
# savings: 8x
Conversion Graph
The conversion graph shows all possible paths between representations.
truth_table
/ | \
fourier bdd sparse
| |
anf circuit
|
dnf/cnf
Direct Conversions
From |
To |
Method |
|---|---|---|
truth_table |
fourier |
Walsh-Hadamard Transform |
fourier |
truth_table |
Inverse WHT |
truth_table |
anf |
Möbius transform |
anf |
truth_table |
Inverse Möbius |
truth_table |
bdd |
Shannon expansion |
any |
symbolic |
String formatting |
Choosing Representations
For Evaluation
Small n (≤ 14):
truth_tableLarge n, sparse:
sparse_truth_tableLarge n, dense:
packed_truth_table
For Analysis
Spectral analysis:
fourier_expansionAlgebraic analysis:
anfComplexity:
circuit,bddCryptography:
anf,truth_table
For Storage
Compact:
bdd,sparse_truth_tableFast load:
truth_tableHuman-readable:
symbolic
Creating from Different Sources
From Truth Table
# List
f = bf.create([0, 1, 1, 0])
# NumPy array
import numpy as np
f = bf.create(np.array([0, 1, 1, 0]))
From Callable
f = bf.create(lambda x: x[0] ^ x[1], n=2)
From True Inputs
# Set of inputs where f=1
f = bf.create({(0, 1), (1, 0)}, n=2)
From Polynomial
# Dict mapping monomials to coefficients
f = bf.create({
frozenset(): 0, # constant term
frozenset([0]): 1, # x0
frozenset([1]): 1, # x1
frozenset([0, 1]): -2 # -2·x0·x1
}, n=2)
From String
f = bf.create("x0 and x1", n=2)
f = bf.create("x0 XOR x1", n=2)
f = bf.create("(x0 | x1) & ~x2", n=3)
From Existing Functions
Combine functions using Boolean operators:
and3 = bf.AND(3)
or3 = bf.OR(3)
f = and3 ^ or3 # XOR
g = and3 & ~or3 # AND with NOT
h = and3 | or3 # OR
See the Operations Guide for full details on &, |, ^, ~ and other transformations.
From File
f = bf.load("function.json") # JSON format
f = bf.load("function.bf") # Aaronson format
f = bf.load("function.cnf") # DIMACS CNF
Saving Functions
f = bf.majority(5)
# Save to various formats
bf.save(f, "maj5.json") # JSON with metadata
bf.save(f, "maj5.bf") # Aaronson format
See Also
Operations Guide - Combining functions with Boolean operators
Spectral Analysis Guide - Fourier representation
Cryptographic Guide - ANF and algebraic analysis
Performance Guide - Memory optimization