mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 00:55:31 +00:00
add rc2 sample
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
7016d94d59
commit
37ef3cbeb2
2 changed files with 91 additions and 1 deletions
84
examples/python/rc2.py
Normal file
84
examples/python/rc2.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
# RC2 algorithm
|
||||
# basic version without optimizations
|
||||
# See also https://github.com/pysathq/pysat and papers in CP 2014, JSAT 2015.
|
||||
|
||||
from z3 import *
|
||||
|
||||
def tt(s, f):
|
||||
return is_true(s.model().eval(f))
|
||||
|
||||
|
||||
def add(Ws, f, w):
|
||||
Ws[f] = w + (Ws[f] if f in Ws else 0)
|
||||
|
||||
def sub(Ws, f, w):
|
||||
w1 = Ws[f]
|
||||
if w1 > w:
|
||||
Ws[f] = w1 - w
|
||||
else:
|
||||
del(Ws[f])
|
||||
|
||||
class RC2:
|
||||
def __init__(self, s):
|
||||
self.bounds = {}
|
||||
self.solver = s
|
||||
self.solver.set("sat.cardinality.solver", True)
|
||||
self.solver.set("sat.core.minimize", True)
|
||||
self.solver.set("sat.core.minimize_partial", True)
|
||||
|
||||
def at_most(self, S, k):
|
||||
fml = AtMost(S + [k])
|
||||
name = Bool("%s" % fml)
|
||||
self.solver.add(Implies(name, fml))
|
||||
self.bounds[name] = (S, k)
|
||||
return name
|
||||
|
||||
# Ws are weighted soft constraints
|
||||
# Whenever there is an unsatisfiable core over ws
|
||||
# increase the limit of each soft constraint from a bound
|
||||
# and create a soft constraint that limits the number of
|
||||
# increased bounds to be at most one.
|
||||
def maxsat(self, Ws):
|
||||
cost = 0
|
||||
Ws0 = Ws.copy()
|
||||
while unsat == self.solver.check([f for f in Ws]):
|
||||
core = list(self.solver.unsat_core())
|
||||
print (self.solver.statistics())
|
||||
print("Core", core)
|
||||
if not core:
|
||||
return unsat
|
||||
w = min([Ws[c] for c in core])
|
||||
cost += w
|
||||
for f in core:
|
||||
sub(Ws, f, w)
|
||||
for f in core:
|
||||
if f in self.bounds:
|
||||
S, k = self.bounds[f]
|
||||
if k + 1 < len(S):
|
||||
add(Ws, self.at_most(S, k + 1), w)
|
||||
add(Ws, self.at_most([mk_not(f) for f in core], 1), w)
|
||||
|
||||
return cost, { f for f in Ws0 if tt(self.solver, f) }
|
||||
|
||||
def from_file(self, file):
|
||||
opt = Optimize()
|
||||
opt.from_file(file)
|
||||
self.solver.add(opt.assertions())
|
||||
obj = opt.objectives()[0]
|
||||
Ws = {}
|
||||
for f in obj.children():
|
||||
assert(f.arg(1).as_long() == 0)
|
||||
add(Ws, f.arg(0), f.arg(2).as_long())
|
||||
return self.maxsat(Ws)
|
||||
|
||||
|
||||
def main(file):
|
||||
s = SolverFor("QF_FD")
|
||||
rc2 = RC2(s)
|
||||
set_param(verbose=0)
|
||||
cost, trues = rc2.from_file(file)
|
||||
print(cost)
|
||||
print(s.statistics())
|
||||
|
||||
# main(<myfile>)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue