My goal is to define a queue as a z3 datatype (in z3py) so that I can perform operations on the queue as constraints. Is there any way to do this, and what is it if there is?
My first instinct, since the three tutorials I'm aware of mentioned them, was to use Algebraic Data Types (ADTs) for this, by means of recursive function definitions like ones frequent in OCaml or Haskell. I found some posts from a while ago discussing ADTs in z3, such as list concat in z3. Some answers on other posts claimed that z3 did not support recursion, but the accepted answer to that one defined a function very similar in style to what I wanted, so I don't know what the right/up-to-date answer is.
def queuegen(sort):
Queue = Datatype('Queue_of_%s' % sort.name())
Queue.declare('enqueue', ('last', sort), ('rest', Queue))
Queue.declare('empty')
Queue = Queue.create()
x = Const('x',sort)
q = Const('q', Queue)
enqueue = Queue.enqueue
dequeue = Function('dequeue', Queue, Queue)
peek = Function('peek', Queue, sort)
size = Function('size', Queue, IntSort())
# just showing my attempted recursive definition for size(q),
# since no sense in worrying about the other functions if I can't do this
sizedef = ForAll(q,If(q == Queue.empty, size(q) == 0,\
size(q) == 1 + size(Queue.rest(q))))
return Queue, [enqueue,dequeue,peek,size], sizedef
z3 does not finish when I add the sizedef constraint I produce to a solver and attempt to check it.