Z3 Theorem Prover: Pythagorean Theorem (Non-Linear

2019-01-26 19:45发布

问题:

Wherefore?

The usecase context in which my problem occures

I define 3 random item of a triangle. Microsoft Z3 should output:

  • Are the constraints satisfiabe or are there invalid input values?
  • A model for all the other triangle items where all the variables are assigned to concrete values.

In order to constrain the items i need to assert triangle equalities - i wanted to start out with the Pythagorean Theorem ((h_c² + p² = b²) ^ (h_c² + q² = a²)).

The Problem

I know that Microsoft Z3 has only limited capabilities to solve non-linear arithematic problems. But even some hand calculators are able to solve a very simplified version like this:

(set-option :print-success true)
(set-option :produce-proofs true)
(declare-const a Real)
(declare-const b Real)
(assert (= a 1.0))
(assert (= b 1.0))
(assert
    (exists
        ((c Real))
        (=
            (+
                (* a a)
                (* b b)
            )
            (* c c)
        )
    )
)
(check-sat)
(get-model)

The Question

  • Is there a way to get Microsoft Z3 to solve the Pythagorean Theorem if two values are given?
  • Or: Is there another theorem prover which is able to handle these case of non-linear arithmetic?

Thanks for your help concerning that - If anything is unclear, please comment.

回答1:

Z3 has a new solver (nlsat) for nonlinear arithmetic. It is more efficient than other solvers (see this article). The new solver is complete for quantifier-free problems. However, the new solver does not support proof generation. If we disable proof generation, then Z3 will use nlsat and easily solve the problem. Based on your question, it seems you are really looking for solutions, thus disabling proof generation does not seem to be an issue.

Moreover, Z3 does not produce approximate solutions (like hand calculators). It uses a precise representation for real algebraic numbers. We can also ask Z3 to display the result in decimal notation (option :pp-decimal). Here is your example online.

In this example, when precise representation is used, Z3 will display the following result for c.

(root-obj (+ (^ x 2) (- 2)) 1)

It is saying that c is the first root of the polynomial x^2 - 2. When we use (set-option :pp-decimal true), it will display

(- 1.4142135623?)

The question mark is used to indicate the result is truncated. Note that, the result is negative. However, it is indeed a solution for the problem you posted. Since, you are looking for triangles, you should assert that the constants are all > 0.

BTW, you do not need the existential quantifier. We can simply use a constant c. Here is an example (also available online at rise4fun):

(set-option :pp-decimal true)
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (= a 1.0))
(assert (= b 1.0))
(assert (> c 0))
(assert (= (+ (* a a) (* b b)) (* c c)))
(check-sat)
(get-model)

Here is another example that does not have a solution (also available online at rise4fun):

(set-option :pp-decimal true)
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
(assert (> c 0))
(assert (> a c))
(assert (= (+ (* a a) (* b b)) (* c c)))
(check-sat)

BTW, you should consider the Python interface for Z3. It is much more user friendly. The tutorial that I linked has examples in Kinematics. They also use nonlinear arithmetic to encode simple high-school physics problems.