I am wondering if this should return unsat? It doesn't return after running for 30 mins on both z3 and cvc5.
; asserts that l1 = l2 up to index len
(define-fun-rec list-eq ( (l1 (Array Int Int)) (l2 (Array Int Int)) (len Int) ) Bool
(ite (< len 0)
true
(ite (= len 0)
(= (select l1 0) (select l2 0))
(list-eq l1 l2 (- len 1)))))
(assert
(not
(=> (list-eq out in i)
(list-eq (store out i (select in i)) in i)
)))
There're a few problems here, let me address them separately.
First, your definition of
list-eqis not really checking if two arrays are equal at all. All it's doing is checking if the given arrays store the same value at index0. Note that your call toselectalways uses0as the argument; otherwise it simply recurses down; which isn't comparing the corresponding elements. You probably meant something like:But making this change isn't going to help; because recursive functions are hard for SMT solvers to deal with. (You typically need induction to prove things about recursive functions, and SMT solvers don't do induction.) Instead, use something like:
Now, quantifiers are hard for SMT solvers too; but they can deal with them better compared to recursive definitions. So, our entire program becomes:
And you'll see that both cvc5 and z3 can answer
unsatfairly quickly for this version of the problem.I should add that heavy use of quantifiers will again lead the solvers to never-ending loops; but in general they handle quantifiers much better than they handle recursive definitions.