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!