0

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.

Jack Feng
  • 895
  • 2
  • 9
  • 24

2 Answers2

3

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!

alias
  • 28,120
  • 2
  • 23
  • 40
  • Thank you so much for the reply! I see why this was vague to you, I am specifically want to create a data structure in z3 that can accomplish this because I am trying to store this type of objects in a z3 array to do some constraint solving. Since the z3 array must have a type_to. e.g. z3.Array('a', z3.StringSort(), VariableSort()). So i can maybe solve a problem like find the index of a variable in array "a" that has a.size > 10. – Jack Feng Jan 28 '20 at 18:31
  • 2
    I doubt a z3 array would help you with this problem. A Z3 array is really not like a traditional "programming language" array. In particular, an array indexed by the type `Int` has an infinite number of elements in Z3, one for each integer value. And reasoning with arrays is usually undecidable as you end up needing quantifiers. If your array size is fixed, you might want to use a regular Python array (i.e., concrete) and just make the elements symbolic. But of course, it all depends on what exactly you're trying to do. Asking a separate specific question and showing what you tried would help. – alias Jan 28 '20 at 18:36
0

I am in a situation like you, but I will try to answer your question the best that I could.

I could just use z3.Array('a', StringSort(), StringSort()). What do I do in this kind of situation?

Yes, you should to implementate it, but remember that Array in Z3 (and in SMT) are of unbounded size, if you want a fixed array you could it:

vec = IntVector('vec', 10)

Respect your other question, I was in a similar situation with you because I had a lot of difficulties with understanding correctly Z3. I adapt the List like if you work in Haskell (for try to do it more understanding)

def funList(sort):
    List = Datatype('List')
    #Constructor insert: (Int, List) -> List
    List.declare('insert', ('head', sort), ('tail', List)) 
    List.declare('nil') #declaración de nil, así permito la opción de tener una lista vacía
    return List.create() #creo la lista

Kokoro
  • 13
  • 3
  • The question is rather vague, but I think the OP is going for a straight record like structure as opposed to a recursive datatype. There's a conflation of what functional-programming people call a 'datatype' and what OO people call it. This seems to be a straight application of good old container with simple fields. – alias Jan 28 '20 at 16:55