0

I'd like to automatically prove the following statement about arbitrary size integers:

forall base a b c d,
0 <= a < base ->
0 <= b < base ->
0 <= c < base ->
0 <= d < base ->
base * a + b = base * c + d ->
b = d

This should be equivalent to the claim that the following is unsat (assuming that the crazy hacks which generated this are correct):

(declare-const a Int)
(declare-const a0 Int)
(declare-const a1 Int)
(declare-const a2 Int)
(declare-const a3 Int)
(assert (not (or (not (and (<= 0 a0) (< a0 a)))
              (or (not (and (<= 0 a1) (< a1 a))) 
               (or (not (and (<= 0 a2) (< a2 a))) 
                (or (not (and (<= 0 a3) (< a3 a))) 
                 (or (not (= (+ ( * a a0) a1)
                             (+ ( * a a2) a3))) 
                     (= a1 a3))))))))
(check-sat)

If I feed this to Z3, it returns unknown, even though this looks like a very simple input.

So my question is: What's the right way to prove this automatically? Are there configuration options for Z3 which will make it work? Should I do a different preprocessing? Or does this problem belong to a class of problems outside Z3's "area of expertise" and I should use another tool?

Update: Here's a more readable version of the same query, using (implies A B) instead of (or (not A) B):

(declare-const a Int)
(declare-const a0 Int)
(declare-const a1 Int)
(declare-const a2 Int)
(declare-const a3 Int)
(assert (not (implies (and (<= 0 a0) (< a0 a))
              (implies (and (<= 0 a1) (< a1 a))
               (implies (and (<= 0 a2) (< a2 a))
                (implies (and (<= 0 a3) (< a3 a))
                 (implies (= (+ ( * a a0) a1) (+ ( * a a2) a3)) (= a1 a3))))))))
(check-sat)
Samuel Gruetter
  • 1,713
  • 12
  • 11

1 Answers1

1

Since you're doing multiplication, the problem is non-linear; and SMT solvers usually cannot deal with non-linear arithmetic. (Z3 has an nonlinear reasoning engine, but it certainly isn't capable of solving arbitrary problems due to undecidability.)

If you fix base to be given values, z3 can handle your problem rather easily. For instance, adding:

(assert (= a 10))

makes z3 respond unsat in no time.

Also the input looks unnecessarily complicated; remember that SMTLib has an implies operator, instead of (or (not X) Y) you can just write (implies X Y) That would make your code a lot easier to read.

alias
  • 28,120
  • 2
  • 23
  • 40
  • I know that non-linear integer arithmetic is undecidable, and I'm not looking for a complete decider, but for a tool implementing a large collection of heuristics. Is there any other tool than Z3 I should consider? – Samuel Gruetter Aug 24 '18 at 17:33
  • 1
    If you're looking for a push-button SMT solver, then z3 is pretty much the best out there. If you're open to doing manual theorem proving, then HOL Light, Isabelle, and Coq all have extensive numeric libraries that you can put to use. – alias Aug 24 '18 at 18:33