问题
I've been skimming through the documentation of Z3Py and for the likes of me have not been able to figure out how to get the proof from a Solver (E.g. if I start from an instance of De Morgan's Laws how can I extract the proof from Z3Py of the instance, step by step). The only reference I saw was for proof(self)
in the Solver
class which supposedly gets the proof of the last check if proof construction is enabled, but I keep getting back the very vague error:
Traceback (most recent call last):
File "example.py", line 36, in <module>
prove(prop)
File "example.py", line 15, in prove
print(s.proof())
File "src/api/python/z3.py", line 5851, in proof
File "src/api/python/z3core.py", line 3770, in Z3_solver_get_proof
z3types.Z3Exception: 'invalid usage'`
So I figure proof construction is disabled by default (probably because of an overhead concern). How do I enable it? Or does this not even achieve what I think it should, by showing a derivation of a proof, step-by-step, from axioms as simple as Idempotency, etc?
Update: Actually, upon trying it, (and believe me, I made sure my version was the latest from the Microsoft Research Website, and even rebuilt it and all) set_param
is undefined:
>>> from z3 import *
>>> print [s for s in dir(z3) if 'set_param' in s]
['Z3_fixedpoint_set_params', 'Z3_set_param_value', 'Z3_solver_set_params']
>>> set_param
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'set_param' is not defined
I subsequently tried using Z3_set_param_value
, Z3_solver_set_params
, and then set_option(proof=True)
(because it was listed as an alias for set_param` in the reference) to no avail:
>>> set_option(proof=True)
Error setting 'PROOF', reason: unknown option.
terminate called after throwing an instance of 'z3_error'
Aborted (core dumped)
回答1:
Yes, you have to set proof=True to enable proofs. Moreover, all expressions have to be created in a mode where proofs are enabled. One way to do this is as follows:
>>> set_param(proof=True)
>>> ctx = Context()
>>> s = Solver(ctx=ctx)
>>> x = Int('x', ctx=ctx)
>>> s.add(x > 0)
>>> s.add(x == 0)
>>> s.check()
unsat
>>> s.proof()
mp(mp(asserted(x > 0),
rewrite((x > 0) == Not(x <= 0)),
Not(x <= 0)),
trans(monotonicity(trans(monotonicity(asserted(x == 0),
(x <= 0) == (0 <= 0)),
rewrite((0 <= 0) == True),
(x <= 0) == True),
Not(x <= 0) == Not(True)),
rewrite(Not(True) == False),
Not(x <= 0) == False),
False)
In this example, I set the proof mode globally true. Then create a reference context that is passed everywhere expressions or solvers are created.
If you make sure to set the proof mode to True before any other calls into Z3, then you don't have to carry your own context. In other words, the following also works:
python.exe
>>> from z3 import *
>>> set_param(proof=True)
>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0)
>>> s.add(x == 0)
>>> s.check()
unsat
>>> s.proof()
mp(mp(asserted(x > 0),
rewrite((x > 0) == Not(x <= 0)),
Not(x <= 0)),
trans(monotonicity(trans(monotonicity(asserted(x == 0),
(x <= 0) == (0 <= 0)),
rewrite((0 <= 0) == True),
(x <= 0) == True),
Not(x <= 0) == Not(True)),
rewrite(Not(True) == False),
Not(x <= 0) == False),
False)
来源:https://stackoverflow.com/questions/29577754/getting-proof-from-z3py