codecogs equations
torsdag 11 februari 2021
SAT for developers 1: What is SAT?
måndag 8 februari 2021
SAT: Some Constraints
In this post, I present four constraints that I have implemented for my satisfiability package SugarRush. It is based on PySAT [1].
Parity
from sugarrush.solver import SugarRush | |
solver = SugarRush() | |
x = [solver.var() for _ in range(10)] | |
t, cnf = solver.parity(x) | |
solver.add(cnf) | |
solver.add([t]) # if you want the sum of x to be odd | |
# solver.add([-t]) # if you want the sum of x to be even |
This constraint is much much better to use than the method used in sat: disjunction operator.
Naive / general way, with disjunction (for 10 elements):
Special purpose encoding of parity constraint (for 10 elements):
Less / Leq
from sugarrush.solver import SugarRush | |
""" Constrain | |
a < b or | |
a <= b | |
where a and b are N-bit binary numbers. | |
The leftmost bit is the highest. | |
""" | |
solver = SugarRush() | |
N = 8 | |
a = [solver.var() for _ in range(N)] | |
b = [solver.var() for _ in range(N)] | |
t, cnf = solver.less(a, b) # a < b | |
# t, cnf = solver.leq(a, b) # a <= b | |
solver.add(cnf) | |
solver.add([t]) # t <=> a < b |
A natural question is: why is the t returned separately from the rest of the constraint? The reason is that this way, one can easily encode such constraints as "a is either less than b, or less than c", or "a is less than either b or c, but not both". An example usage here is to constrain two intervals to be non-overlapping:
from sugarrush.solver import SugarRush | |
""" Given two intervals [a0, a1], [b0, b1], | |
constrain that they have no overlap. | |
""" | |
solver = SugarRush() | |
N = 8 | |
a0 = [solver.var() for _ in range(N)] | |
a1 = [solver.var() for _ in range(N)] | |
b0 = [solver.var() for _ in range(N)] | |
b1 = [solver.var() for _ in range(N)] | |
a0_less_a1, cnfa = solver.leq(a0, a1) # a0 <= a1 | |
b0_less_b1, cnfb = solver.leq(b0, b1) # b0 <= b1 | |
a1_less_b0, cnf0 = solver.less(a1, b0) | |
b1_less_a1, cnf1 = solver.less(b1, a1) | |
b1_less_a0, cnf2 = solver.less(b1, a0) | |
a1_less_b1, cnf3 = solver.less(a1, b1) | |
# add the bindings | |
solver.add(cnf0 + cnf1 + cnf2 + cnf3 + cnfa + cnfb) | |
# constrain the order of a0,a1 and b0,b1 | |
solver.add([a0_less_a1]) | |
solver.add([b0_less_b1]) | |
# the main constraint: | |
# (a1 must not be inside [b0, b1]) AND (b1 must not be inside [a0, a1]) | |
solver.add([[b1_less_a1, a1_less_b0], [a1_less_b1, b1_less_a0]]) |
Plus
from sugarrush.solver import SugarRush | |
"""Given three N-bit binary numbers a, b, z | |
constrain so that | |
a + b = z % 2**N | |
(unsigned N-bit integer addition) | |
""" | |
solver = SugarRush() | |
N = 8 | |
a = [solver.var() for _ in range(N)] | |
b = [solver.var() for _ in range(N)] | |
z = [solver.var() for _ in range(N)] | |
cnf = solver.plus(a, b, z) | |
# cnf = solver.plus(a, z, b) # to get b - a! | |
solver.add(cnf) |
Element
from sugarrush.solver import SugarRush | |
"""Constrain | |
z = v[a] | |
where a is uintK, | |
z is uintN, | |
v is a vector of at most 2**K uintN | |
""" | |
def to_binary(N, n, a): | |
n = n % 2**N | |
b = "{1:0{0:d}b}".format(N, n) | |
return [ap if bp == '1' else -ap for bp, ap in zip(b, a)] | |
solver = SugarRush() | |
N = 8 | |
K = 4 | |
a = [solver.var() for _ in range(K)] | |
z = [solver.var() for _ in range(N)] | |
v = [[solver.var() for _ in range(N)] for _ in range(2**K)] | |
# v[i] = 2 + 3*i | |
v0_assumptions = to_binary(N, 2, v[0]) | |
for v0, v1 in zip(v, v[1:]): | |
solver.add(solver.plus(v0, 3, v1)) | |
solver.add(solver.element(v, a, z)) | |
a_int = 3 | |
a_assumptions = to_binary(K, a_int, a) | |
solver.solve(assumptions= v0_assumptions + a_assumptions) | |
z_solve = [(solver.solution_value(zp) > 0)*1 for zp in z] | |
z_int = sum([2**i * zp for i, zp in enumerate(z_solve[::-1])]) | |
print("v[{0:d}] = {1:d}".format(a_int, z_int)) |
[1] Ignatiev, Alexey, Antonio Morgado, and Joao Marques-Silva. "PySAT: A Python toolkit for prototyping with SAT oracles." International Conference on Theory and Applications of Satisfiability Testing. Springer, Cham, 2018.