I have the following SMT code that I wrote in order to generate a random sudoku. More specifically, it generates a filled sudoku given an empty 9x9 matrix. It was the most simple example I could come up with to try it on Z3 to learn how it works.
sudoku.smt:
; 9x9 cells 1 to 9
(declare-const cell_1_1 Int)(assert (<= 1 cell_1_1))(assert (<= cell_1_1 9))
(declare-const cell_1_2 Int)(assert (<= 1 cell_1_2))(assert (<= cell_1_2 9))
(declare-const cell_1_3 Int)(assert (<= 1 cell_1_3))(assert (<= cell_1_3 9))
(declare-const cell_1_4 Int)(assert (<= 1 cell_1_4))(assert (<= cell_1_4 9))
(declare-const cell_1_5 Int)(assert (<= 1 cell_1_5))(assert (<= cell_1_5 9))
(declare-const cell_1_6 Int)(assert (<= 1 cell_1_6))(assert (<= cell_1_6 9))
(declare-const cell_1_7 Int)(assert (<= 1 cell_1_7))(assert (<= cell_1_7 9))
(declare-const cell_1_8 Int)(assert (<= 1 cell_1_8))(assert (<= cell_1_8 9))
(declare-const cell_1_9 Int)(assert (<= 1 cell_1_9))(assert (<= cell_1_9 9))
(declare-const cell_2_1 Int)(assert (<= 1 cell_2_1))(assert (<= cell_2_1 9))
(declare-const cell_2_2 Int)(assert (<= 1 cell_2_2))(assert (<= cell_2_2 9))
(declare-const cell_2_3 Int)(assert (<= 1 cell_2_3))(assert (<= cell_2_3 9))
(declare-const cell_2_4 Int)(assert (<= 1 cell_2_4))(assert (<= cell_2_4 9))
(declare-const cell_2_5 Int)(assert (<= 1 cell_2_5))(assert (<= cell_2_5 9))
(declare-const cell_2_6 Int)(assert (<= 1 cell_2_6))(assert (<= cell_2_6 9))
(declare-const cell_2_7 Int)(assert (<= 1 cell_2_7))(assert (<= cell_2_7 9))
(declare-const cell_2_8 Int)(assert (<= 1 cell_2_8))(assert (<= cell_2_8 9))
(declare-const cell_2_9 Int)(assert (<= 1 cell_2_9))(assert (<= cell_2_9 9))
(declare-const cell_3_1 Int)(assert (<= 1 cell_3_1))(assert (<= cell_3_1 9))
(declare-const cell_3_2 Int)(assert (<= 1 cell_3_2))(assert (<= cell_3_2 9))
(declare-const cell_3_3 Int)(assert (<= 1 cell_3_3))(assert (<= cell_3_3 9))
(declare-const cell_3_4 Int)(assert (<= 1 cell_3_4))(assert (<= cell_3_4 9))
(declare-const cell_3_5 Int)(assert (<= 1 cell_3_5))(assert (<= cell_3_5 9))
(declare-const cell_3_6 Int)(assert (<= 1 cell_3_6))(assert (<= cell_3_6 9))
(declare-const cell_3_7 Int)(assert (<= 1 cell_3_7))(assert (<= cell_3_7 9))
(declare-const cell_3_8 Int)(assert (<= 1 cell_3_8))(assert (<= cell_3_8 9))
(declare-const cell_3_9 Int)(assert (<= 1 cell_3_9))(assert (<= cell_3_9 9))
(declare-const cell_4_1 Int)(assert (<= 1 cell_4_1))(assert (<= cell_4_1 9))
(declare-const cell_4_2 Int)(assert (<= 1 cell_4_2))(assert (<= cell_4_2 9))
(declare-const cell_4_3 Int)(assert (<= 1 cell_4_3))(assert (<= cell_4_3 9))
(declare-const cell_4_4 Int)(assert (<= 1 cell_4_4))(assert (<= cell_4_4 9))
(declare-const cell_4_5 Int)(assert (<= 1 cell_4_5))(assert (<= cell_4_5 9))
(declare-const cell_4_6 Int)(assert (<= 1 cell_4_6))(assert (<= cell_4_6 9))
(declare-const cell_4_7 Int)(assert (<= 1 cell_4_7))(assert (<= cell_4_7 9))
(declare-const cell_4_8 Int)(assert (<= 1 cell_4_8))(assert (<= cell_4_8 9))
(declare-const cell_4_9 Int)(assert (<= 1 cell_4_9))(assert (<= cell_4_9 9))
(declare-const cell_5_1 Int)(assert (<= 1 cell_5_1))(assert (<= cell_5_1 9))
(declare-const cell_5_2 Int)(assert (<= 1 cell_5_2))(assert (<= cell_5_2 9))
(declare-const cell_5_3 Int)(assert (<= 1 cell_5_3))(assert (<= cell_5_3 9))
(declare-const cell_5_4 Int)(assert (<= 1 cell_5_4))(assert (<= cell_5_4 9))
(declare-const cell_5_5 Int)(assert (<= 1 cell_5_5))(assert (<= cell_5_5 9))
(declare-const cell_5_6 Int)(assert (<= 1 cell_5_6))(assert (<= cell_5_6 9))
(declare-const cell_5_7 Int)(assert (<= 1 cell_5_7))(assert (<= cell_5_7 9))
(declare-const cell_5_8 Int)(assert (<= 1 cell_5_8))(assert (<= cell_5_8 9))
(declare-const cell_5_9 Int)(assert (<= 1 cell_5_9))(assert (<= cell_5_9 9))
(declare-const cell_6_1 Int)(assert (<= 1 cell_6_1))(assert (<= cell_6_1 9))
(declare-const cell_6_2 Int)(assert (<= 1 cell_6_2))(assert (<= cell_6_2 9))
(declare-const cell_6_3 Int)(assert (<= 1 cell_6_3))(assert (<= cell_6_3 9))
(declare-const cell_6_4 Int)(assert (<= 1 cell_6_4))(assert (<= cell_6_4 9))
(declare-const cell_6_5 Int)(assert (<= 1 cell_6_5))(assert (<= cell_6_5 9))
(declare-const cell_6_6 Int)(assert (<= 1 cell_6_6))(assert (<= cell_6_6 9))
(declare-const cell_6_7 Int)(assert (<= 1 cell_6_7))(assert (<= cell_6_7 9))
(declare-const cell_6_8 Int)(assert (<= 1 cell_6_8))(assert (<= cell_6_8 9))
(declare-const cell_6_9 Int)(assert (<= 1 cell_6_9))(assert (<= cell_6_9 9))
(declare-const cell_7_1 Int)(assert (<= 1 cell_7_1))(assert (<= cell_7_1 9))
(declare-const cell_7_2 Int)(assert (<= 1 cell_7_2))(assert (<= cell_7_2 9))
(declare-const cell_7_3 Int)(assert (<= 1 cell_7_3))(assert (<= cell_7_3 9))
(declare-const cell_7_4 Int)(assert (<= 1 cell_7_4))(assert (<= cell_7_4 9))
(declare-const cell_7_5 Int)(assert (<= 1 cell_7_5))(assert (<= cell_7_5 9))
(declare-const cell_7_6 Int)(assert (<= 1 cell_7_6))(assert (<= cell_7_6 9))
(declare-const cell_7_7 Int)(assert (<= 1 cell_7_7))(assert (<= cell_7_7 9))
(declare-const cell_7_8 Int)(assert (<= 1 cell_7_8))(assert (<= cell_7_8 9))
(declare-const cell_7_9 Int)(assert (<= 1 cell_7_9))(assert (<= cell_7_9 9))
(declare-const cell_8_1 Int)(assert (<= 1 cell_8_1))(assert (<= cell_8_1 9))
(declare-const cell_8_2 Int)(assert (<= 1 cell_8_2))(assert (<= cell_8_2 9))
(declare-const cell_8_3 Int)(assert (<= 1 cell_8_3))(assert (<= cell_8_3 9))
(declare-const cell_8_4 Int)(assert (<= 1 cell_8_4))(assert (<= cell_8_4 9))
(declare-const cell_8_5 Int)(assert (<= 1 cell_8_5))(assert (<= cell_8_5 9))
(declare-const cell_8_6 Int)(assert (<= 1 cell_8_6))(assert (<= cell_8_6 9))
(declare-const cell_8_7 Int)(assert (<= 1 cell_8_7))(assert (<= cell_8_7 9))
(declare-const cell_8_8 Int)(assert (<= 1 cell_8_8))(assert (<= cell_8_8 9))
(declare-const cell_8_9 Int)(assert (<= 1 cell_8_9))(assert (<= cell_8_9 9))
(declare-const cell_9_1 Int)(assert (<= 1 cell_9_1))(assert (<= cell_9_1 9))
(declare-const cell_9_2 Int)(assert (<= 1 cell_9_2))(assert (<= cell_9_2 9))
(declare-const cell_9_3 Int)(assert (<= 1 cell_9_3))(assert (<= cell_9_3 9))
(declare-const cell_9_4 Int)(assert (<= 1 cell_9_4))(assert (<= cell_9_4 9))
(declare-const cell_9_5 Int)(assert (<= 1 cell_9_5))(assert (<= cell_9_5 9))
(declare-const cell_9_6 Int)(assert (<= 1 cell_9_6))(assert (<= cell_9_6 9))
(declare-const cell_9_7 Int)(assert (<= 1 cell_9_7))(assert (<= cell_9_7 9))
(declare-const cell_9_8 Int)(assert (<= 1 cell_9_8))(assert (<= cell_9_8 9))
(declare-const cell_9_9 Int)(assert (<= 1 cell_9_9))(assert (<= cell_9_9 9))
; distinct values in rows
(assert (distinct cell_1_1 cell_1_2 cell_1_3 cell_1_4 cell_1_5 cell_1_6 cell_1_7 cell_1_8 cell_1_9))
(assert (distinct cell_2_1 cell_2_2 cell_2_3 cell_2_4 cell_2_5 cell_2_6 cell_2_7 cell_2_8 cell_2_9))
(assert (distinct cell_3_1 cell_3_2 cell_3_3 cell_3_4 cell_3_5 cell_3_6 cell_3_7 cell_3_8 cell_3_9))
(assert (distinct cell_4_1 cell_4_2 cell_4_3 cell_4_4 cell_4_5 cell_4_6 cell_4_7 cell_4_8 cell_4_9))
(assert (distinct cell_5_1 cell_5_2 cell_5_3 cell_5_4 cell_5_5 cell_5_6 cell_5_7 cell_5_8 cell_5_9))
(assert (distinct cell_6_1 cell_6_2 cell_6_3 cell_6_4 cell_6_5 cell_6_6 cell_6_7 cell_6_8 cell_6_9))
(assert (distinct cell_7_1 cell_7_2 cell_7_3 cell_7_4 cell_7_5 cell_7_6 cell_7_7 cell_7_8 cell_7_9))
(assert (distinct cell_8_1 cell_8_2 cell_8_3 cell_8_4 cell_8_5 cell_8_6 cell_8_7 cell_8_8 cell_8_9))
(assert (distinct cell_9_1 cell_9_2 cell_9_3 cell_9_4 cell_9_5 cell_9_6 cell_9_7 cell_9_8 cell_9_9))
; distinct values in cells
(assert (distinct cell_1_1 cell_2_1 cell_3_1 cell_4_1 cell_5_1 cell_6_1 cell_7_1 cell_8_1 cell_9_1))
(assert (distinct cell_1_2 cell_2_2 cell_3_2 cell_4_2 cell_5_2 cell_6_2 cell_7_2 cell_8_2 cell_9_2))
(assert (distinct cell_1_3 cell_2_3 cell_3_3 cell_4_3 cell_5_3 cell_6_3 cell_7_3 cell_8_3 cell_9_3))
(assert (distinct cell_1_4 cell_2_4 cell_3_4 cell_4_4 cell_5_4 cell_6_4 cell_7_4 cell_8_4 cell_9_4))
(assert (distinct cell_1_5 cell_2_5 cell_3_5 cell_4_5 cell_5_5 cell_6_5 cell_7_5 cell_8_5 cell_9_5))
(assert (distinct cell_1_6 cell_2_6 cell_3_6 cell_4_6 cell_5_6 cell_6_6 cell_7_6 cell_8_6 cell_9_6))
(assert (distinct cell_1_7 cell_2_7 cell_3_7 cell_4_7 cell_5_7 cell_6_7 cell_7_7 cell_8_7 cell_9_7))
(assert (distinct cell_1_8 cell_2_8 cell_3_8 cell_4_8 cell_5_8 cell_6_8 cell_7_8 cell_8_8 cell_9_8))
(assert (distinct cell_1_9 cell_2_9 cell_3_9 cell_4_9 cell_5_9 cell_6_9 cell_7_9 cell_8_9 cell_9_9))
; distinct values in squares
(assert (distinct cell_1_1 cell_1_2 cell_1_3 cell_2_1 cell_2_2 cell_2_3 cell_3_1 cell_3_2 cell_3_3))
(assert (distinct cell_1_4 cell_1_5 cell_1_6 cell_2_4 cell_2_5 cell_2_6 cell_3_4 cell_3_5 cell_3_6))
(assert (distinct cell_1_7 cell_1_8 cell_1_9 cell_2_7 cell_2_8 cell_2_9 cell_3_7 cell_3_8 cell_3_9))
(assert (distinct cell_4_1 cell_4_2 cell_4_3 cell_5_1 cell_5_2 cell_5_3 cell_6_1 cell_6_2 cell_6_3))
(assert (distinct cell_4_4 cell_4_5 cell_4_6 cell_5_4 cell_5_5 cell_5_6 cell_6_4 cell_6_5 cell_6_6))
(assert (distinct cell_4_7 cell_4_8 cell_4_9 cell_5_7 cell_5_8 cell_5_9 cell_6_7 cell_6_8 cell_6_9))
(assert (distinct cell_7_1 cell_7_2 cell_7_3 cell_8_1 cell_8_2 cell_8_3 cell_9_1 cell_9_2 cell_9_3))
(assert (distinct cell_7_4 cell_7_5 cell_7_6 cell_8_4 cell_8_5 cell_8_6 cell_9_4 cell_9_5 cell_9_6))
(assert (distinct cell_7_7 cell_7_8 cell_7_9 cell_8_7 cell_8_8 cell_8_9 cell_9_7 cell_9_8 cell_9_9))
; generate one for me, please
(check-sat)
(get-model)
I execute it via:
z3 sudoku.smt
And as a result, I get a generated sudoku:
(model
(define-fun cell_2_9 () Int
8)
(define-fun cell_3_9 () Int
9)
(define-fun cell_7_6 () Int
7)
(define-fun cell_7_7 () Int
1)
(define-fun cell_7_4 () Int
5)
(define-fun cell_5_3 () Int
1)
(define-fun cell_3_7 () Int
2)
(define-fun cell_9_7 () Int
9)
(define-fun cell_1_8 () Int
3)
(define-fun cell_4_4 () Int
8)
(define-fun cell_9_4 () Int
1)
(define-fun cell_2_1 () Int
9)
(define-fun cell_2_2 () Int
1)
(define-fun cell_4_1 () Int
6)
(define-fun cell_5_5 () Int
3)
(define-fun cell_1_2 () Int
6)
(define-fun cell_3_5 () Int
1)
(define-fun cell_1_3 () Int
4)
(define-fun cell_1_4 () Int
7)
(define-fun cell_9_8 () Int
7)
(define-fun cell_8_8 () Int
8)
(define-fun cell_3_3 () Int
5)
(define-fun cell_2_3 () Int
2)
(define-fun cell_6_8 () Int
9)
(define-fun cell_7_3 () Int
6)
(define-fun cell_9_1 () Int
2)
(define-fun cell_5_7 () Int
8)
(define-fun cell_5_9 () Int
4)
(define-fun cell_3_4 () Int
6)
(define-fun cell_6_7 () Int
6)
(define-fun cell_2_5 () Int
5)
(define-fun cell_6_2 () Int
3)
(define-fun cell_8_2 () Int
9)
(define-fun cell_6_4 () Int
2)
(define-fun cell_2_4 () Int
4)
(define-fun cell_2_7 () Int
7)
(define-fun cell_4_5 () Int
7)
(define-fun cell_3_2 () Int
7)
(define-fun cell_4_9 () Int
2)
(define-fun cell_9_2 () Int
5)
(define-fun cell_6_9 () Int
7)
(define-fun cell_1_9 () Int
1)
(define-fun cell_7_5 () Int
9)
(define-fun cell_9_5 () Int
8)
(define-fun cell_9_3 () Int
3)
(define-fun cell_8_7 () Int
4)
(define-fun cell_5_1 () Int
7)
(define-fun cell_4_7 () Int
3)
(define-fun cell_3_8 () Int
4)
(define-fun cell_9_9 () Int
6)
(define-fun cell_8_1 () Int
1)
(define-fun cell_4_2 () Int
4)
(define-fun cell_4_3 () Int
9)
(define-fun cell_7_2 () Int
8)
(define-fun cell_8_9 () Int
5)
(define-fun cell_1_5 () Int
2)
(define-fun cell_1_1 () Int
8)
(define-fun cell_2_6 () Int
3)
(define-fun cell_6_6 () Int
1)
(define-fun cell_5_8 () Int
5)
(define-fun cell_5_4 () Int
9)
(define-fun cell_9_6 () Int
4)
(define-fun cell_6_1 () Int
5)
(define-fun cell_3_6 () Int
8)
(define-fun cell_6_3 () Int
8)
(define-fun cell_8_6 () Int
2)
(define-fun cell_7_9 () Int
3)
(define-fun cell_5_2 () Int
2)
(define-fun cell_4_6 () Int
5)
(define-fun cell_7_1 () Int
4)
(define-fun cell_8_4 () Int
3)
(define-fun cell_4_8 () Int
1)
(define-fun cell_1_7 () Int
5)
(define-fun cell_6_5 () Int
4)
(define-fun cell_7_8 () Int
2)
(define-fun cell_1_6 () Int
9)
(define-fun cell_2_8 () Int
6)
(define-fun cell_8_3 () Int
7)
(define-fun cell_3_1 () Int
3)
(define-fun cell_8_5 () Int
6)
(define-fun cell_5_6 () Int
6)
)
However, I have two issues with this:
It takes quite a long time to finish, about 25 seconds on my machine.
It generates the same sudoku every time I run it.
This makes me wonder that I'm doing something wrong. What I'd expect is a very fast result that's different every time. How can I achieve that?
To be honest, I'm struggling a bit with the documentation resources regarding Z3. I'm trying to follow https://rise4fun.com/Z3/tutorial/guide, but everything is explained very briefly, and I cannot find any detailed manual. So any resources/recommendations/links are welcome. Thanks.
Int is a bad domain to choose for this problem. Instead, use a bit-vector instead. That is, replace your declarations with:
(declare-const cell_1_1 (_ BitVec 4))
(assert (bvule #x1 cell_1_1))
(assert (bvule cell_1_1 #x9))
Once you make this change for all the variables, you'll see that z3 solves the problem much more quickly. (In my test, almost instantly.)
Regarding randomness: You can play around with random-seed settings, but it's unlikely an SMT solver will generate different solutions for you; they are tuned for solving constraints, not exploring the possible search space in any meaningful way (random or otherwise.) A practical solution would be to randomly generate a few of the cell values (using some other program) and hard-code them: That is, assert that cell_3_4 is 5, and some other cell is 9 etc. So long as you assert a few of these randomly (~10 or so), you should get good sudoku instances. (Unless it becomes unsat of course.)
After studying z3 tactics a bit more, I came up with a possibly better solution than the answer from #alias (thank you for the answer anyway, it lead me in the right direction).
Performance
Instead of using (check-sat) in my code, it's possible to use (check-sat-using ...) and further specify tactics to be applied.
The default tactic is smt which is slow in my case. After studying the help from (help-tactics), I found out there's a tactic nla2bv that can be used.
Quoting from the (help-tactics):
nla2bv converts a nonlinear arithmetic problem into a bit-vector problem, in most cases, the resultant goal is an under approximation and is useful for finding models.
In code, this means:
(check-sat-using (then nla2bv smt))
Randomness
Regarding randomness, it's possible to provide a random seed to the smt tactic via the :random-seed parameter. If I provide different seed, I get a different output model.
In code, this looks like:
(check-sat-using (then nla2bv (using-params smt :random-seed 999)))
Although, as #alias pointed out in the answer, this gives only very limited options to control the output.
After these changes, I'm able to get from ~25 seconds to less than 1 second. For more performance gain, I'm sure it's possible to tweak the used tactics even more.
Related
I want to use z3 to find the result of the following expression after quantifier elimination. What is the correct syntax?
(declare-fun n () Int)
(declare-fun X () Int)
(declare-fun X_1_ () Int)
(declare-fun X_0_ () Int)
(assert (exists ((R__0 Int) (R__1 Int)(R_0_0 Int) (R_1_0 Int)) (and (>= n 3)
(= X n)
(=(+ X_0_ X_1_) X)
(>= X_0_ 0)
(<= R_0_0 X_0_)
(>= R_0_0 0)
(<= R_0_0 R__0)
(>= X_1_ 0)
(<= R_1_0 X_1_)
(>= R_1_0 0)
(<= R_1_0 R__0)
(<= R__0 X)
(<= R__1 X)
(= (+ R_1_0 R_0_0) R__0)
(> (* 3 R__0) (* 2 n))
(>= R_0_0 R_1_0)
(<= (* 3 R_0_0) (* 2 n))
(<= (* 3 R__1) (* 2 n)))))
(apply (using-params qe :qe-nonlinear true))
Use the qe_rec tactic. Changing your last line to:
(apply qe_rec)
produces:
(goals
(goal
(>= X_1_ 0)
(>= X_0_ 0)
(= (+ X_0_ X_1_) X)
(= X n)
(>= n 3)
(<= (+ (* (- 2) n) (* 3 X_1_)) 0)
(>= (* 9 X_1_) 7)
(<= (+ (* 2 n) (* (- 6) X_0_)) (- 1))
:precision precise :depth 1)
)
How do I extract an element in a Sequence to the base type, so that the following will work?
(define-sort ISeq () (Seq Int))
(define-const x ISeq (seq.unit 5))
(define-const y ISeq (seq.unit 6))
(assert (>= (seq.at x 0) (seq.at y 0)))
Until a suitable function is implemented (or its existence is revealed to us), you could use the following work-around:
(define-sort ISeq () (Seq Int))
(define-const x ISeq (seq.unit 5))
(define-const y ISeq (seq.unit 6))
(declare-const e1 Int)
(declare-const e2 Int)
(push)
(assert (= (seq.unit e1) (seq.at x 0)))
(assert (= (seq.unit e2) (seq.at y 0)))
(assert (not (>= e2 e1)))
(check-sat)
(pop)
(push) ;; or alternatively
(assert (not
(implies
(and
(= (seq.unit e1) (seq.at x 0))
(= (seq.unit e2) (seq.at y 0)))
(>= e2 e1))))
(check-sat)
(pop)
See the relevant discussion at the Z3 issue tracker: https://github.com/Z3Prover/z3/issues/1302
It seems a workaround is indeed possible, but due to quantifiers it's unlikely to give you an effective method. An explicit encoding like Malte suggests might be the most practical approach here in the meantime.
You're looking for nth. Here is a simple example of it:
(define-sort ISeq () (Seq Int))
(declare-const x ISeq)
(declare-const y ISeq)
(assert (= (seq.len x) 4))
(assert (= (seq.len y) 3))
(assert (< (seq.nth x 3) (seq.nth y 1)))
(check-sat)
(get-value (x y))
And z3 answers immediately with a correct answer (1237 > 1236):
sat
((x (seq.++ (seq.unit 6)
(seq.++ (seq.unit 7) (seq.++ (seq.unit 8) (seq.unit 1236)))))
(y (seq.++ (seq.unit 9) (seq.++ (seq.unit 1237) (seq.unit 12)))))
We look for a number of the form efghiihgfe which is the product of two numbers of the form 999ab and 99qcd.
We use the following code
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
(declare-const e Int)
(declare-const f Int)
(declare-const g Int)
(declare-const h Int)
(declare-const i Int)
(declare-const p Int)
(declare-const q Int)
(assert (and (>= a 0) (<= a 9)))
(assert (and (>= b 0) (<= b 9)))
(assert (and (>= c 0) (<= c 9)))
(assert (and (>= d 0) (<= d 9)))
(assert (and (>= e 0) (<= e 9)))
(assert (and (>= f 0) (<= f 9)))
(assert (and (>= g 0) (<= g 9)))
(assert (and (>= h 0) (<= h 9)))
(assert (and (>= i 0) (<= i 9)))
(assert (and (>= p 0) (<= p 9)))
(assert (and (>= q 0) (<= q 9)))
(assert (= (* (+ 99900 (* 10 a) b ) (+ 99000 (* 100 q) (* 10 c) d ))
(+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) ) )
(check-sat)
(get-model)
(eval (+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e))
and the output is
(model
(define-fun q () Int
6)
(define-fun p () Int
0)
(define-fun i () Int
0)
(define-fun h () Int
6)
(define-fun g () Int
6)
(define-fun f () Int
9)
(define-fun e () Int
9)
(define-fun d () Int
1)
(define-fun c () Int
8)
(define-fun b () Int
9)
(define-fun a () Int
7)
)
9966006699
To verify that 9966006699 is the maxim we run the code
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Int)
(declare-const e Int)
(declare-const f Int)
(declare-const g Int)
(declare-const h Int)
(declare-const i Int)
(declare-const p Int)
(declare-const q Int)
(assert (and (>= a 0) (<= a 9)))
(assert (and (>= b 0) (<= b 9)))
(assert (and (>= c 0) (<= c 9)))
(assert (and (>= d 0) (<= d 9)))
(assert (and (>= e 0) (<= e 9)))
(assert (and (>= f 0) (<= f 9)))
(assert (and (>= g 0) (<= g 9)))
(assert (and (>= h 0) (<= h 9)))
(assert (and (>= i 0) (<= i 9)))
(assert (and (>= p 0) (<= p 9)))
(assert (and (>= q 0) (<= q 9)))
(assert (= (* (+ 99900 (* 10 a) b ) (+ 99000 (* 100 q) (* 10 c) d ))
(+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) ) )
(assert (> (+ (* (^ 10 9) e) (* (^ 10 8) f) (* (^ 10 7) g) (* (^ 10 6) h) (* (^ 10 5) i)
(* (^ 10 4) i) (* 1000 h ) (* 100 g) (* 10 f) e) 9966006699 ))
(check-sat)
and the output is
unsat
Please let me know if there is a more efficient program with Z3 to solve the problem.
Thank you, maybe use bit-vectors to force using finite domains instead of ILP.
I am getting timeout on the following example.
http://rise4fun.com/Z3/zbOcW
Is there any trick to make this work (eg.by reformulating the problem or using triggers)?
For this example, the macro finder will be useful (I think often with forall quantifiers with implications), you can enable it with:
(set-option :macro-finder true)
Here's your updated example that gets sat quickly (rise4fun link: http://rise4fun.com/Z3/Ux7gN ):
(set-option :macro-finder true)
(declare-const a (Array Int Bool))
(declare-const sz Int)
(declare-const n Int)
(declare-const d Int)
(declare-const r Bool)
(declare-const x Int)
(declare-const y Int)
;;ttff
(declare-fun ttff (Int Int Int) Bool)
(assert
(forall ((x1 Int) (y1 Int) (n1 Int))
(= (ttff x1 y1 n1)
(and
(forall ((i Int))
(=> (and (<= x1 i) (< i y1))
(= (select a i) true)))
(forall ((i Int))
(=> (and (<= y1 i) (< i n1))
(= (select a i) false)))))))
;; A1
(assert (and (<= 0 n) (<= n sz)))
;; A2
(assert (< 0 d))
;; A3
(assert (and (and (<= 0 x) (<= x y)) (<= y n)))
;; A4
(assert (ttff x y n))
;; A6
(assert
(=> (< 0 y)
(= (select a (- y 1)) true)))
;; A7
(assert
(=> (< 0 x)
(= (select a (- x 1)) false)))
;;G
(assert
(not
(iff
(and (<= (* 2 d) (+ n 1)) (ttff (- (+ n 1) (* 2 d)) (- (+ n 1) d) (+ n 1)))
(and (= (- (+ n 1) y) d) (<= d (- y x))))))
(check-sat)
(get-model)
I'm trying to understand how to use solve-eq, I expected Z3 to solve this
(declare-const mem (Array Int Int))
(declare-const adr_a Int)
(declare-const a Int)
(assert (= (select mem adr_a) a))
(assert (<= 0 (select mem adr_a)))
(apply solve-eqs)
into
(<= 0 a)
but I get instead
(<= 0 (select mem adr_a))
can I specify what varibales should be simplified? any other tactique could do the job?
Simple example:
(declare-const a Int)
(declare-const b Int)
(assert (= b a))
(assert (<= 0 b))
(apply solve-eqs)
the output is:
(goals (goal (<= 0 a) :precision precise :depth 1) )