CircuitSAT -> SpinGlass
In this tutorial, we will demonstrate how to use the Spinglass model to solve the circuit satisfiability problem.
We first define a simple Circuit
using the @circuit
macro. And then we convert the circuit to a CircuitSAT
problem.
julia> using ProblemReductions
julia> circuit = @circuit begin c = x ∧ y d = x ∨ (¬c ∧ ¬z) end
Circuit: | c = ∧(x, y) | d = ∨(x, ∧(¬(c), ¬(z)))
julia> circuitsat = CircuitSAT(circuit)
CircuitSAT: | c = ∧(x, y) | ##var#230 = ¬(c) | ##var#231 = ¬(z) | ##var#229 = ∧(##var#230, ##var#231) | d = ∨(x, ##var#229) Symbols: [:c, :x, :y, Symbol("##var#230"), Symbol("##var#231"), :z, Symbol("##var#229"), :d]
julia> variables(circuitsat)
8-element Vector{Int64}: 1 2 3 4 5 6 7 8
julia> circuitsat.symbols
8-element Vector{Symbol}: :c :x :y Symbol("##var#230") Symbol("##var#231") :z Symbol("##var#229") :d
The resulting circuitsat
expands the expression to a list of simple clauses. The variables are mapped to integers that pointing to the symbols that stored in the symbols
field.
The we can convert the circuit to a SpinGlass
problem using the reduceto
function.
julia> result = reduceto(SpinGlass, circuitsat)
ReductionCircuitToSpinGlass{HyperGraph, Vector{Int64}}(8, SpinGlass{HyperGraph, Vector{Int64}}(HyperGraph(8, [[1, 2], [1, 3], [2, 3], [1], [2], [3], [3, 4], [4], [5, 6], [5], [6], [4, 6], [4, 7], [6, 7], [7], [1, 7], [1, 8], [7, 8], [8]]), [1, -2, -2, 0, 1, -2, 1, 1, 1, 0, 1, 1, -2, -2, -3, 1, -2, -2, 2]), [3, 1, 2, 4, 6, 5, 7, 8])
The resulting result
is a ReductionCircuitToSpinGlass
instance that contains the spin glass problem.
With the result
instance, we can define a logic gadget that maps the spin glass variables to the circuit variables.
julia> indexof(x) = findfirst(==(findfirst(==(x), circuitsat.symbols)), result.variables)
indexof (generic function with 1 method)
julia> gadget = LogicGadget(result.spinglass, indexof.([:x, :y, :z]), [indexof(:d)])
LogicGadget: | Problem: SpinGlass{HyperGraph, Vector{Int64}}(HyperGraph(8, [[1, 2], [1, 3], [2, 3], [1], [2], [3], [3, 4], [4], [5, 6], [5], [6], [4, 6], [4, 7], [6, 7], [7], [1, 7], [1, 8], [7, 8], [8]]), [1, -2, -2, 0, 1, -2, 1, 1, 1, 0, 1, 1, -2, -2, -3, 1, -2, -2, 2]) | Inputs: [3, 1, 5] | Outputs: [8]
julia> tb = truth_table(gadget; variables=circuitsat.symbols[result.variables])
ERROR: AssertionError: length(d) == 2 ^ ni
The gadget
is a LogicGadget
instance that maps the spin glass variables to the circuit variables. The truth_table
function generates the truth table of the gadget.