سؤال

I am working with the Python API of Z3 in an attempt to include support for it in a research tool that I am writing. I have a question regarding extracting the unsatisfiable core using the Python interface.

I have the following simple query:

(set-option :produce-unsat-cores true)
(assert (! (not (= (_ bv0 32) (_ bv0 32))) :named __constraint0))
(check-sat)
(get-unsat-core)
(exit)

Running this query through the z3 executable (for Z3 4.1), I receive the expected result:

unsat
(__constraint0)

For Z3 4.3, I obtain a segmentation fault:

unsat
Segmentation fault

That isn't the main question, although that was an intriguing observation. I then modified the query (inside a file) as

(assert (! (not (= (_ bv0 32) (_ bv0 32))) :named __constraint0))
(exit)

Using a file handler, I passed the contents of this file (in a variable `queryStr') to the following Python code:

import z3
...
solver = z3.Solver()
solver.reset()
solver.add(z3.parse_smt2_string(queryStr))
querySatResult = solver.check()
if querySatResult == z3.sat:
    ...
elif querySatResult == z3.unsat:
    print solver.unsat_core()

I receive the empty list from the `unsat_core' function: []. Am I using this function incorrectly? The docstring for the function suggests that I should instead be doing something similar to

solver.add(z3.Implies(p1, z3.Not(0 == 0)))

However, I was wondering if it were still possible to use the query as is, since it conforms to SMT-LIB v2.0 standards (I believe), and whether I was missing something obvious.

هل كانت مفيدة؟

المحلول

The crash you observed has been fixed, and the fix will be available in the next release. If you try the "unstable" (work-in-progress) branch, you should get the expected behavior. You can retrieve the unstable branch using

git clone https://git01.codeplex.com/z3 -b unstable

The API parse_smt2_string provides only basic support for parsing formulas in SMT 2.0 format. It does not keep the annotations :named. We will address this and other limitations in future versions. In the meantime, we should use "answer literals" such as p1 and assertions of the form:

solver.add(z3.Implies(p1, z3.Not(0 == 0)))

In the "unstable" branch, we also support the following new API. It "simulates" the :named assertions used in the SMT 2.0 standard.

def assert_and_track(self, a, p):
    """Assert constraint `a` and track it in the unsat core using the Boolean constant `p`.

    If `p` is a string, it will be automatically converted into a Boolean constant.

    >>> x = Int('x')
    >>> p3 = Bool('p3')
    >>> s = Solver()
    >>> s.set(unsat_core=True)
    >>> s.assert_and_track(x > 0,  'p1')
    >>> s.assert_and_track(x != 1, 'p2')
    >>> s.assert_and_track(x < 0,  p3)
    >>> print(s.check())
    unsat
    >>> c = s.unsat_core()
    >>> len(c)
    2
    >>> Bool('p1') in c
    True
    >>> Bool('p2') in c
    False
    >>> p3 in c
    True
    """
    ...
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top