One way to do this for the integers is with is_int
and is_int_value
:
x = Int('x')
print "x types"
print is_int(x) # true, is of sort int
print is_int_value(x) # false, not a "value"
x_ = IntVal(7)
print "x_ types"
print is_int(x_) # true, is also of sort int
print is_int_value(x_) # true, is a value
For reals, you can do this using is_real
to check the variable sort, and use (the disjunction of) is_algebraic_value
and is_rational_value
for the values (I didn't see a function like is_real_value
in the API, but I think this disjunct will do it). For bitvectors, you can use is_bv_value
for values, and is_bv
to check the variable sort.
The .NET API has Expr.IsNumeral
, and you can see how these are implemented in the API here (e.g., Expr.IsIntNum
[the equivalent of the Python is_int_value
] checks if both Expr.IsNumeral
and Expr.IsInt
are true): http://research.microsoft.com/en-us/um/redmond/projects/z3/_expr_8cs_source.html
I did not immediately see a way to do this for custom-defined enumeration sorts. As one alternative, you could encode your enum using bitvectors and compare variables / values using is_bv_value
. As a better workaround though, you appear to need to use the more general algebraic datatypes and their automatically created "recognizers". The Python API does not seem to properly create the recognizers if you declare them as enum sorts. Here's one way to do it for what's effectively an enum sort (but declared as the more general datatype).
Z3Py encoding of the following: http://rise4fun.com/Z3Py/ELtn
ColorVal = Datatype('ColorVal')
ColorVal.declare('white')
ColorVal.declare('black')
ColorVal = ColorVal.create()
mycolor = Const("mycolor", ColorVal)
print ColorVal.recognizer(0) # is_white
print ColorVal.recognizer(1) # is_black
print simplify(ColorVal.is_white(mycolor)) # returns is_white(mycolor)
print simplify(ColorVal.is_black(mycolor)) # returns is_black(mycolor)
mycolorVal = ColorVal.white # set to value white
print simplify(ColorVal.is_white(mycolorVal)) # true
print simplify(ColorVal.is_black(mycolorVal)) # false
# compare "variable" versus "value" with return of is_white, is_black, etc.: if it gives a boolean value, it's a value, if not, it's a variable
print "var vs. value"
x = simplify(ColorVal.is_white(mycolor))
print is_true(x) or is_false(x) # returns false, since x is is_white(mycolor)
y = simplify(ColorVal.is_white(mycolorVal))
print is_true(y) or is_false(y) # true
ColorValEnum, (whiteEnum,blackEnum) = EnumSort("ColorValEnum",["whiteEnum","blackEnum"])
mycolorEnum = Const("mycolorEnum",ColorValEnum)
print ColorValEnum.recognizer(0) # is_whiteEnum
print ColorValEnum.recognizer(1) # is_blackEnum
# it appears that declaring an enum does not properly create the recognizers in the Python API:
#print simplify(ColorValEnum.is_whiteEnum(mycolorEnum)) # error: gives DatatypeSortRef instance has no attribute 'is_whiteEnum'
#print simplify(ColorValEnum.is_blackEnum(mycolorEnum)) # error: gives DatatypeSortRef instance has no attribute 'is_blackEnum'