Maybe create a data structure that contains the same information as the following Python class.
class Variable:
def __init__(self):
self.name = "v1" #str
self.size = 10 #int
self.initialized = True #bool
Have three different fields of different types.
If the fields were the same type, e.g. "str
", I could just use z3.Array('a', StringSort(), StringSort())
. Kind of use it like a mapping.
What do I do in the situation of fields with different type like the one shown in the python code?
I looked into Datatype
, and read the example in the z3py guide about how they created a List
. However, I could not fully understand exactly what's going on. I think maybe the terms used in the z3 documentation are a little different than what's commonly used in OO programming languages like Java, Python? I am having a really hard time to grasp some of the terms and examples...
*** A more tricky part, how do you store this kind of variable in a z3 Array? Such as I want to find the index of a Variable object in an array that has size > 10, using z3 constraint solving.
A datatype is a structure that can have multiple constructors: Like a tree (leaf, or branch), or a list (nil, or a cons), or any other generally tree-like structure.
From your description, it appears you don't actually want a datatype but rather a straight record value. (The terminology is confusing. What OO people call as datatype is most of the time just a struct/record, and what functional programming or SMT folks call datatype is something much richer with many constructors that are recursive like a list. This is unfortunate, but something you learn once and is easy to remember.)
There's no one size fits all, obviously; and your question description is rather vague. But I'm guessing you want to represent some notion of a Variable
that has an associated fixed-name, size, and some sort initialized field. What you want is a mere Python class where you can rely on flexible typing to either use it as concrete variables, or as symbolic ones that z3 can manipulate. Based on this, I'd be inclined to code your problem like this:
from z3 import *
class Variable:
def __init__(self, nm):
self.name = nm
self.size = Int(nm + '_size')
self.initialized = Bool(nm + '_initialized')
def __str__(self):
return "<Name: %s, Size: %s, Initialized: %s>" % (self.name, self.size, self.initialized)
# Helper function to grab a variable from a z3 model
def getVar(m, v):
var = Variable(v.name)
var.size = m[v.size]
var.initialized = m[v.initialized]
return var
# Declare a few vars
myVar1 = Variable('myVar1')
myVar2 = Variable('myVar2')
# Add some constraints
s = Solver()
s.add(myVar1.size == 12)
s.add(myVar2.initialized == True);
s.add(myVar1.size > myVar2.size)
s.add(myVar1.initialized == Not(myVar2.initialized))
# Get a satisfying model
if s.check() == sat:
m = s.model()
print getVar(m, myVar1)
print getVar(m, myVar2)
I use the class Variable
to represent both a regular value as you would in Python, but also something that can store symbolic size (via Int(nm + '_size')
) and symbolic initialized info (via Bool(nm + '_initialized')
). Syntax might look a bit confusing, but if you go through the program I'm sure you'll see the logic. The function getVar
is a helper to acquire the value of one of these variables after a call to check
, to access the model values.
I added a few constraints to the program to make it interesting; obviously that's the part where you'll code your original problem. When I run this program, I get:
$ python a.py
<Name: myVar1, Size: 12, Initialized: False>
<Name: myVar2, Size: 11, Initialized: True>
which gives me a nice model that satisfy all the constraints I specified.
Hope that helps!