3

Following this example in (found here: z3py) I can compare c to e.g. Color.green.

Color = Datatype('Color')
Color.declare('red')
Color.declare('green')
Color.declare('blue')
Color = Color.create()

# Let c be a constant of sort Color
c = Const('c', Color)
# Then, c must be red, green or blue
prove(Or(c == Color.green, 
         c == Color.blue,
         c == Color.red))

In my application I have to compare c to a python-string: I would like something like this:

c = Const('c', Color)
solve(c == "green") # this doesn't work, but it works with Color.green

The approach works e.g. for IntSort (see below), but not for my own Datatype.

i = Int("i")
solve(i < 10)
stklik
  • 834
  • 1
  • 8
  • 19

2 Answers2

2

One solution that worked for me (comparing Datatypes/Enums to strings) was to add a cast routine to class DatatypeSortRef(SortRef) in z3.py. It will try to find a constructor that matches the given string and use it, otherwise continue with existing behaviour (super().cast(val))

Here's the code that I used:

def cast(self, val):
    """This is so we can cast a string to a Z3 DatatypeRef. This is useful if we want to compare strings with a Datatype/Enum to a String.

    >>> Color = Datatype("Color")
    >>> Color.declare("red")
    >>> Color.declare("green")
    >>> Color.declare("blue")
    >>> Color = Color.create()

    >>> x = Const("x", Color)
    >>> solve(x != "red", x != "blue")
    [x = green]
    """
    if type(val) == str:
        for i in range(self.num_constructors()):
            if self.constructor(i).name() == val:
                return self.constructor(i)()
    return super().cast(val)

Note: I did not pay attention to general correctness. This approach works for me, but might cause problems with your code.

stklik
  • 834
  • 1
  • 8
  • 19
1

The Z3 python interface does very limited overloading for strings. You can use string literals for the type 'String'. Otherwise strings are not going to be coerced to other types. Furthermore, the approach of using strings also doesn't work for integers, e.g.,

 I = Int("I") 
 solve(I < "10")

will throw an error.

Note that you can use Color.red already or declare your own shorthand:

red = Color.red
Nikolaj Bjorner
  • 8,229
  • 14
  • 15
  • I thought about creating a global mapping of names to values (similar to your "shorthand") but I was hoping that there is some way "official" way. Do you think it is possible to implement something like this with some reasonable effort? – stklik Aug 15 '17 at 14:51
  • see my (potential) solution below. I did not find any python tests to run, so I don't want to create a pull-request yet. @Nikolaj-Bjorner – stklik Aug 16 '17 at 14:10