Assuming the use of several built-in and user defined Z3 sorts, e.g. Int, Bool, S1, S2, …, is there a way of writing a generic sort-wrapping and -unwrapping function that kind of casts from sort A to sort B and back? For example
(declare-const a S1)
(declare-const b S2)
(declare-const c Int)
(WRAP[S1] b) ; Expression is of sort S1
(WRAP[S1] c) ; Expression is of sort S1
(WRAP[Int] (WRAP[S1] c)) ; Expression is of sort Int
I currently cover each case manually, e.g.
(declare-fun $boolToInt (Bool) Int)
(declare-fun $intToBool (Int) Bool)
(assert (forall ((x Int))
(= x ($boolToInt($intToBool x)))))
(assert (forall ((x Bool))
(= x ($intToBool($boolToInt x)))))
Such wrappers could be created automatically from a given set of sorts, but I would prefer a generic solution of possible.
You can use datatypes to encode “union types”.
Here is an example:
You can find more information about datatypes in the Z3 guide. The datatype
S1-S2-Inthas three constructors:WRAP-S1,WRAP-S2andWRAP-Int. Z3 automatically generates the recognizer predicates:is-WRAP-S1,is-WRAP-S2andis-WRAP-Int. The accessorsS1-Value,S2-ValueandInt-Valueare used to “deconstruct” aS1-S2-Intvalue. For example, for alla,(S1-Value (WRAP-S1 a)) = a. The value of(S1-Value (WRAP-S2 b))is underspecified. In this case, Z3 treatsS1-Valueas a uninterpreted function.BTW, the axiom
is equivalent to false. It is essentially trying to inject the integers into the Booleans.