Getting proof from z3py

醉酒当歌 提交于 2021-02-08 02:26:13

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!