I created this file which is supposed to represent Dekker's algorithm
Given a variable Turn of type proc and two arrays want and crit mapping proc to bools
The initial state is want[p] = false and crit[p] = false for all proc p
I can non deterministically take one of the three transitions below :
req : if there exists a proc p such that want[p] = false then want'[p] = true
enter : if there exists a proc p such that want[p] = true and turn = p then crit'[p] = true
exit : if there exists a proc p such that crit[p] = true then want'[p] = false, crit'[p] = false and turn = ? (? represent the fact that any proc p' can be attributed to turn).
A state is unsafe if there exists two proc p1 and p2 such that crit[p1] = crit[p2] = true
I represented it like this :
(set-logic HORN)
(define-sort proc () Int)
(define-sort myarray () (Array proc Bool))
(declare-var turn proc)
(declare-var want myarray)
(declare-var crit myarray)
(declare-fun reachable (proc myarray myarray) Bool)
;; Init
(rule
(=>
(forall ((z proc))
(and
(= (select want z) false)
(= (select crit z) false)
)
)
(reachable turn want crit)
)
)
;; Unsafe
(assert
(exists ((z1 proc) (z2 proc))
(=>
(and
(not (= z1 z2))
(= (select want z1) true)
(= (select want z2) true)
)
(reachable turn want crit)
)
)
)
;; Req
(assert
(exists ((z proc))
(=>
(and
(= (select want z) false)
(reachable turn want crit)
)
(reachable turn (store want z true) crit)
)
)
)
;; Enter
(assert
(exists ((z proc))
(=>
(and
(= (select want z) true)
(= turn z)
(reachable turn want crit)
)
(reachable turn want (store crit z true))
)
)
)
;; Exit
(assert
(exists ((z1 proc)
(z2 proc)
)
(=>
(and
(= (select crit z1) true)
(reachable turn want crit)
)
(and
(reachable
z2
(store want z1 false)
(store crit z1 false)
)
)
)
)
)
(check-sat)
But when I call z3 dekker.smt2 it gives me unknown as an answer.
If I try to do it like this :
(set-logic HORN)
(declare-fun reachable (Int
(Array Int Bool)
(Array Int Bool)) Bool)
;; Init
(assert
(forall ((Turn Int)
(Want (Array Int Bool))
(Crit (Array Int Bool))
)
(=>
(forall ((z Int))
(and
(= (select Want z) false)
(= (select Crit z) false)
))
(reachable Turn Want Crit)
)))
;; Unsafe
(assert
(forall ((Turn Int)
(Want (Array Int Bool))
(Crit (Array Int Bool))
)
(=>
(reachable Turn Want Crit)
(not
(exists ((z1 Int) (z2 Int))
(and (not (= z1 z2))
(= (select Crit z1) true)
(= (select Crit z2) true)
)
)
)
)
)
)
;; Transitions
(assert
(forall (
(Turn Int)
(Want (Array Int Bool))
(Crit (Array Int Bool))
(Turn_ Int)
(Want_ (Array Int Bool))
(Crit_ (Array Int Bool))
)
(=>
(and
(reachable Turn Want Crit)
(or
;;req
(exists ((n Int))
(and (= (select Want n) false)
(= Turn_ Turn)
(= Want_ (store Want n true))
(= Crit_ Crit)
)
)
;;req
(exists ((n Int))
(and (= (select Want n) true)
(= Turn n)
(= Turn_ Turn)
(= Want_ Want)
(= Crit_ (store Crit n true))
)
)
;;req
(exists ((n Int) (n2 Int))
(and (= (select Crit n) true)
(= Turn_ n2)
(= Want_ (store Want n false))
(= Crit_ (store Crit n false))
)
)
)
)
(reachable Turn_ Want_ Crit_)
)
)
)
(check-sat)
I get this answer :
PDR cannot solve non-ground tails: (let ((a!1 (forall ((z Int))
(and (= (select reachable_1_n z) false)
(= (select reachable_2_n z) false)))))
(= a!1 true))
unknown
Related
I am having trouble attempting to prove this fairly simple Z3 query.
(set-option :smt.auto-config false) ; disable automatic self configuration
(set-option :smt.mbqi false) ; disable model-based quantifier instantiation
(declare-fun sum (Int) Int)
(declare-fun list () (Array Int Int))
(declare-fun i0 () Int)
(declare-fun s0 () Int)
(declare-fun i1 () Int)
(declare-fun s1 () Int)
(assert (forall ((n Int))
(! (or (not (<= n 0)) (= (sum n) 0))
:pattern ((sum n)))))
(assert (forall ((n Int))
(! (let ((a1 (= (sum n)
(+ (select list (- n 1))
(sum (- n 1))))))
(or (<= n 0) a1))
:pattern ((sum n)))))
(assert (>= i0 0))
(assert (= s0 (sum i0)))
(assert (= i1 (+ 1 i0)))
(assert (= s1 (+ 1 s0 (select list i0))))
(assert (not (= s1 (sum i1))))
(check-sat)
Seems to me that the final assertion should instantiate the second quantified statement for i1 while the assert involving s0 should instantiate the quantifiers for i0. These two should should easily lead to UNSAT.
However, Z3 returns unknown. What am I missing?
Never mind, there was an silly error in my query.
This code:
(assert (= s1 (+ 1 s0 (select list i0))))
should have been:
(assert (= s1 (+ s0 (select list i0))))
The problem in relational algebra REL051+1.p reads
File : REL051+1 : TPTP v6.1.0. Released v4.0.0.
% Domain : Relation Algebra
% Problem : Dense linear ordering
Using TPTP syntax with fof the corresponding code is
fof(f01,axiom,(
! [A] : o(A,A) )).
fof(f02,axiom,(
! [A,B] :
( ( A != B
& o(A,B) )
=> ~ o(B,A) ) )).
fof(f03,axiom,(
! [A,B,C] :
( ( o(A,B)
& o(B,C) )
=> o(A,C) ) )).
fof(f04,axiom,(
! [A,B] :
( ( A != B
& o(A,B) )
=> ( o(A,f(A,B))
& o(f(A,B),B) ) ) )).
fof(f05,axiom,(
! [A,B] :
( f(A,B) != A
& f(A,B) != B ) )).
fof(f06,axiom,(
! [A,B] :
( o(A,B)
| o(B,A) ) )).
As you can see in TPTP all ATPs are unable to prove such problem.
This theorem was refuted with Z3 using the following SMT-LIB
(declare-sort S)
(declare-fun o (S S) Bool)
(declare-fun f (S S) S)
(assert (forall ((A S)) (o A A) ))
(assert (forall ((A S) (B S)) (implies (and (distinct A B) (o A B))
(not (o B A))) ) )
(assert (forall ((A S) (B S) (C S)) (implies (and (o A B) (o B C))
(o A C)) ) )
(assert (forall ((A S) (B S)) (implies (and (distinct A B) (o A B))
(and (o A (f A B)) (o (f A B) B))) ) )
(declare-fun B () S)
(assert (forall ((A S)) (and (distinct (f A B) A)
(distinct (f A B) B)) ) )
(assert (not (forall ((A S)) (or (o A B) (o B A)) ) ))
(check-sat)
(get-model)
and the corresponding output is
sat
(model
;; universe for S:
;; S!val!0 S!val!3 S!val!1 S!val!2
;; -----------
;; definitions for universe elements:
(declare-fun S!val!0 () S)
(declare-fun S!val!3 () S)
(declare-fun S!val!1 () S)
(declare-fun S!val!2 () S)
;; cardinality constraint:
(forall ((x S)) (or (= x S!val!0) (= x S!val!3) (= x S!val!1) (= x S!val!2)))
;; -----------
(define-fun B () S
S!val!1)
(define-fun A!0 () S
S!val!0)
(define-fun f!47 ((x!1 S) (x!2 S)) S
(ite (and (= x!1 S!val!2) (= x!2 S!val!1)) S!val!3
S!val!2))
(define-fun k!46 ((x!1 S)) S
(ite (= x!1 S!val!2) S!val!2
(ite (= x!1 S!val!0) S!val!0
(ite (= x!1 S!val!3) S!val!3
S!val!1))))
(define-fun f ((x!1 S) (x!2 S)) S
(f!47 (k!46 x!1) (k!46 x!2)))
(define-fun o!48 ((x!1 S) (x!2 S)) Bool
(ite (and (= x!1 S!val!1) (= x!2 S!val!1)) true
(ite (and (= x!1 S!val!0) (= x!2 S!val!0)) true
(ite (and (= x!1 S!val!2) (= x!2 S!val!2)) true
(ite (and (= x!1 S!val!3) (= x!2 S!val!3)) true
false)))))
(define-fun o ((x!1 S) (x!2 S)) Bool
(o!48 (k!46 x!1) (k!46 x!2)))
)
Please run this example online here
My question is: This refutation with Z3 is correct?
Another question from a Z3 newbie. Can options change the behavior of Z3? I might expect them to affect termination, or change sat or unsat into unknown but not sat into unsat or vice versa.
This example:
(set-option :smt.macro-finder true)
(declare-datatypes () ((Option (none) (some (Data Int)))))
(define-sort Set () (Array Option Option))
(declare-fun filter1 (Option) Option)
(declare-fun filter2 (Option) Option)
(declare-var s1 Set)
(declare-var s2 Set)
(declare-var x1 Option)
(declare-var x2 Option)
(declare-var x3 Option)
(declare-var x4 Option)
(assert (not (= x1 none)))
(assert (not (= x2 none)))
(assert (not (= x3 none)))
(assert (not (= x4 none)))
(assert (= (select s1 x1) x2))
(assert (= (select s2 x3) x4))
(assert (forall ((x Option)) (= (filter1 x) (ite (or (= none x) (= (Data x) 1)) x none))))
(assert (forall ((x Option)) (= (filter2 x) (ite (or (= none x) (= (Data x) 2)) x none))))
(assert (= ((_ map filter1) s1) s2))
(assert (= ((_ map filter2) s1) s2))
(check-sat)
(get-model)
returns sat with the first line and unsat without it.
Is this a bug or am I missing something fundamental?
This is a bug. The two quantifiers are essentially providing "definitions" for filter1 and filter2.
The option smt.macro-finder is used to eliminate functions symbols by expanding these definitions. It is essentially performing "macro expansion". However, there is a bug in the macro expander. It does not expand the occurrences of filter1 and filter2 in the map constructs: (_ map filter1) and (_ map filter2).
This bug will be fixed.
In the meantime, we should not use the map construct and smt.macro-finder option simultaneously.
To create a Sets of 3 elements (1,2,3) in Z3, I am using the follows code:
(define-sort Set () ( Array Int Bool ) )
(declare-const s Set )
( assert ( and ( = ( select s 1 ) true ) ( = ( select s 2 ) true )
( = ( select s 3 ) true ) ) )
The Model I am getting is as follows :
(model
(define-fun s () (Array Int Bool)
(_ as-array k!0))
(define-fun k!0 ((x!1 Int)) Bool
(ite (= x!1 2) true
(ite (= x!1 3) true
(ite (= x!1 1) true
true))))
)
But instead how can I get a model of the form :
(model (define-fun s () (Array Int Bool)
(_ as-array k!0)) (define-fun k!0 ((x!1 Int)) Bool
(ite (= x!1 2) true
(ite (= x!1 3) true
(ite (= x!1 1) true
false)))) )
So that elements other than the set members are not included in the set.
You can achieve this by starting from the empty set, i.e. the array that is defined to be false everywhere.
Here is an example:
(declare-const s1 (Array Int Bool))
(assert (= s1
(store
(store
(store
((as const (Array Int Bool)) false)
1 true)
2 true)
3 true)
))
(check-sat)
(get-model)
I'm a new guy to work with the Z3.
Would like to know how I can calculate the maximum value of a set and two different sets.
For example:
[1, 6, 5] - The greater is 6
[1, 6, 5] e [10, 7, 2] - The greater is 6
I use the following code to set:
(declare-sort Set 0)
(declare-fun contains (Set Int) bool)
( declare-const set Set )
( declare-const distinct_set Set )
( declare-const A Int )
( declare-const B Int )
( declare-const C Int )
( assert ( = A 0 ) )
( assert ( = B 1 ) )
( assert ( = C 2 ) )
( assert ( distinct A C) )
( assert ( distinct set distinct_set ) )
(assert
(forall ((x Int))
(= (contains set x) (or (= x A) (= x C)))))
And now would like to know how can I calculate the largest value in the set (set) and the largest value in sets (set and distinct_set).
If it was for all integers was only because it was easy to do:
(define-fun max ((x Int) (y Int)) Int
(ite (< x y) y x))
But I can not leave with sets by their integers, ie, get the values that have set.
Can you help me?
Thanks
Is the following encoding reasonable for your purposes? It is also available online here.
; We Enconde each set S of integers as a function S : Int -> Bool
(declare-fun S1 (Int) Bool)
; To assert that A and C are elements of S1, we just assert (S1 A) and (S1 C)
(declare-const A Int)
(declare-const C Int)
(assert (S1 A))
(assert (S1 C))
; To say that B is not an element of S1, we just assert (not (S1 B))
(declare-const B Int)
(assert (not (S1 B)))
; Now, let max_S1 be the max value in S1
(declare-const max_S1 Int)
; Then, we now that max_S1 is an element of S1, that is
(assert (S1 max_S1))
; All elements in S1 are smaller than or equal to max_S1
(assert (forall ((x Int)) (=> (S1 x) (not (>= x (+ max_S1 1))))))
; Now, let us define a set S2 and S3
(declare-fun S2 (Int) Bool)
(declare-fun S3 (Int) Bool)
; To assert that S3 is equal to the union of S1 and S2, we just assert
(assert (forall ((x Int)) (= (S3 x) (or (S1 x) (S2 x)))))
; To assert that S3 is not equal to S1 we assert
(assert (exists ((x Int)) (not (= (S3 x) (S1 x)))))
(check-sat)
; Now let max_S3 be the maximal value of S3
(declare-const max_S3 Int)
(assert (S3 max_S3))
(assert (forall ((x Int)) (=> (S3 x) (not (>= x (+ max_S3 1))))))
; the set of constraints is still satisfiable
(check-sat)
; Now, let us assert that max_S3 < max_S1.
; It should be unsat, since S3 is a super set of S1
(assert (< max_S3 max_S1))
(check-sat)