model record by datatype in z3
if two record datatype have the same field, e.g.,
UNI_MSG : record
Cmd : UNI_CMD;
Proc : NODE;
HomeProc : boolean;
Data : DATA;
end;
INV_CMD : enum {INV_None, INV_Inv, INV_InvAck};
INV_MSG : record
Cmd : INV_CMD;
end;
RP_CMD : enum {RP_None, RP_Replace};
RP_MSG : record
Cmd : RP_CMD;
end;
both UNI_MSG and RP_MSG have the fields Cmd.
when I use the Cmd field of a UNI_MSG record variable, I don't know how to
use it because an RP_CMD variable also has the Cmd field.
z3 code is as follows:
; This example illustrates basic arithmetic and
; uninterpreted functions
(declare-datatypes () ((CACHE_STATE CACHE_I CACHE_S CACHE_E)))
(declare-datatypes () ((NODE_CMD NODE_None NODE_Get NODE_GetX)))
(declare-datatypes () ((UNI_CMD UNI_None UNI_Get UNI_GetX UNI_Put UNI_PutX UNI_Nak)))
(declare-datatypes () ((INV_CMD INV_None INV_Inv INV_InvAck)))
(declare-datatypes () ((RP_CMD RP_None RP_Replace)))
(declare-datatypes () ((WB_CMD WB_None WB_Wb)))
(declare-datatypes () ((SHWB_CMD SHWB_None SHWB_ShWb SHWB_FAck)))
(declare-datatypes () ((NAKC_CMD NAKC_None NAKC_Nakc)))
(define-sort NODE () Int)
(define-sort DATA () Int)
(define-sort boolean () Bool)
(declare-datatypes () ((Record_0 (mk-Record_0 (Cmd NAKC_CMD)))))
(declare-datatypes () ((Record_1 (mk-Record_1 (Data DATA)
(HomeProc boolean)
(Proc NODE)
(Cmd SHWB_CMD)))))
(declare-datatypes () ((Record_2 (mk-Record_2 (HomeInvSet boolean)
(InvSet (Array NODE boolean))
(HomeShrSet boolean)
(ShrSet (Array NODE boolean))
(ShrVld boolean)
(HomeHeadPtr boolean)
(HeadPtr NODE)
(HeadVld boolean)
(Dirty boolean)
(Local boolean)
(Pending boolean)))))
(declare-datatypes () ((Record_3 (mk-Record_3 (CacheData DATA)
(CacheState CACHE_STATE)
(InvMarked boolean)
(ProcCmd NODE_CMD)))))
(declare-datatypes () ((Record_4 (mk-Record_4 (CurrData DATA)
( NakcMsg ( Record_0))
( ShWbMsg ( Record_1))
( WbMsg ( Record_1))
( HomeRpMsg ( Record_0))
( RpMsg (Array NODE Record_0))
( HomeInvMsg ( Record_0))
( InvMsg (Array NODE Record_0))
( HomeUniMsg ( Record_1))
( UniMsg (Array NODE Record_1))
(MemData DATA)
( Dir ( Record_2))
( HomeProc ( Record_3))
( Proc (Array NODE Record_3))))))
(declare-const Sta ( Record_4))
(assert (= (Cmd (select (UniMsg Sta) 1 )) UNI_Nak))
(check-sat)
The error is caused by both record_0 and record_1 having field Cmd.
You can work around this by renaming them to Cmd0, Cmd1 etc.
SMTLib actually allows the same name to be used in fields with other types, but the type system is too weak and requires you to put ascriptions to work around it. If you really want to keep the name, post a (much!) smaller version of this problem so we can show you how to do that. But in practice, renaming is the best (and simplest!) way to go.
Related
Suppose I have a Sort T and I declare an array indexed by T, what is the sort of mapping over it?
e.g
(declare-datatypes ()
((T ....))) ; some index, may be finite or infinite (as in Int)
(declare-const a (Array T Int))
(declare-const b (Array Int Int))
(define-fun foo ((x Int)) Int)
(define-fun bar ((y Int)) Bool)
What is the sort of mapping foo on a? And the sort of mapping foo on b? Is there any way to mess up with the indexes type and obtain from an array indexed by T an array indexed by another sort, say e.g. Int?
Usual sort-matching rules apply. That is, to map a function f : A -> B on an array, the array must have its range type A, and it'll turn it into a B, preserving the type of its domain.
Regarding your example: Regardless of what your T is, you'll simply have Array T Int as the final sort if you map foo, and Array T Bool as the result if you map bar. The following script type-checks without any issues:
(declare-datatypes ((T 0)) ((i Int)))
(declare-const a (Array T Int))
(declare-const b (Array Int Int))
(declare-fun foo (Int) Int)
(declare-fun bar (Int) Bool)
(define-fun e1 () (Array T Int) ((_ map foo) a))
(define-fun e2 () (Array T Bool) ((_ map bar) a))
(define-fun e3 () (Array Int Int) ((_ map foo) b))
(define-fun e4 () (Array Int Bool) ((_ map bar) b))
Note that you cannot change the type of the domain (which is what you mean by index I presume) by mapping a function over an array. It only changes the range type.
In z3, one can declare a fully-uninterpreted const like so:
(declare-const x Int)
Similarly, one can define a fully-interpreted one like this:
(define-fun y () Int 3)
; y == 3
Given an algebraic datatype, one can have a fully interpreted tuple like the following:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(define-fun z () Item (mk-item 3 4))
; z == Item(size=3, weight=4)
... Or a non-interpreted one like below:
(declare-const i1 (Item Int Int))
Now is it possible to have a partially-interpreted data type, so that, based on the previous example, weight would be fixed for each item and size could vary?
; (bad syntax, but I hope you get the idea)
; in this case the size is varying, but weight is fixed to 5
(declare-const i2 (Item Int 5))
You should simply declare it with declare-fun and assert an equality for the portions that you know:
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(declare-fun x () Item)
(assert (= (weight x) 5))
(check-sat)
(get-model)
This produces:
sat
(model
(define-fun x () Item
(mk-item 0 5))
)
I tried around a some time to get a rather simple requirement done:
I declared a new datatype
(declare-datatypes () ((A (mk_A (key Int) (var1 Int) (var2 Int)))))
where key should act like a primary key in a database, i.e., each different instance of A should have a different key value.
The container of the different instances (functions) looks like the following:
(declare-const A_instances (Array Int A))
So far so good. I tried to create an assertion, such that all instances in A_instances have a different key field. Thus, for each index i in A_instances (key (select A_instances i)) should be distinct. However it returns unknown.
Someone has any suggestions?
One possible solution is
(declare-datatypes () ((A (mk_A (key Int) (var1 Int) (var2 Int)))))
(declare-const A_instances (Array Int A))
(declare-fun j () Int)
(assert (forall ((i Int)) (implies (distinct i j)
(distinct (key (select A_instances i))
(key (select A_instances j))) ) ))
(check-sat)
and the corresponding output is
sat
I am using z3 with the C++ API for the example:
context c;
sort I = c.int_sort();
sort B = c.bool_sort();
expr x = c.int_const("x");
expr x1 = c.int_const("x1");
func_decl p1 = function("p1", I, B);
func_decl p2 = function("p2", I, B);
solver s(c);
s.add(forall(x, (implies(p1(x), ((p2(x)))))));
s.add(p1(x1));
The generated model is:
sat
(define-fun x1 () Int
0)
(define-fun p1 ((x!1 Int)) Bool
true)
(define-fun p2 ((x!1 Int)) Bool
true)
The imagined to have the model p1(x1) and p2(x1). I tried also with the options:
p.set("mbqi", true);
p.set("smt.mbqi.max_iterations", "10000000");
p.set("auto-config", true);
But, I have the same result. Am I missing something?
Thank you.
Z3 produces a correct model, so I'm not exactly sure what the problem is. I can only imagine that there is some confusion about the argument names of the functions.
Per declaration, p1 is a function that takes an int and returns a Boolean. When Z3 builds an interpretation for this function, it names the first argument x!1 which has nothing to do with the constant function x1 (no bang). The model returned states
(define-fun x1 () Int
0)
(define-fun p1 ((x!1 Int)) Bool
true)
which means x1 is a constant function that always returns zero, i.e., x1() := 0. Additionally, p1 is a function with one argument (called x!1) and which returns true regardless of the input, i.e., for all x!1, p1(x!1) := true.
I've this problem:
(set-option :print-success true)
(declare-datatypes () (( Data nil (cons (giorno Int) (mese Int)(anno Int) ))))
(declare-datatypes () (( Eta (cons1 (data Data) (io Int)))))
(assert (forall ( (e Eta) )
(and (< 0 ((giorno data) e)) (> 0 ((giorno data) e))
) ) )
(check-sat)
and z3 return me this:
Z3(7, 12): ERROR: invalid qualified/indexed identifier, '_' or 'as' expected
how can i resolve this?
I think that the correct code is
(set-option :print-success true)
(declare-datatypes () (( Data nil (cons (giorno Int) (mese Int)(anno Int) ))))
(declare-datatypes () (( Eta (cons1 (data Data) (io Int)))))
(assert (forall ( (e Eta) )
(and (< 0 (giorno (data e))) (> 0 (giorno (data e))))))
(check-sat)
and the output is
success
success
success
success
unsat