Search code examples
listfunctiongenericsz3axiom

Length function for generic lists


This post shows how to axiomatise a length function for Z3's built-in lists. However, the function is sort-specific (here Int) and not applicable to lists of bools or custom sorts.

; declare len as an uninterpreted function
(declare-fun len ((List Int)) Int)

; assert defining equations for len as an axiom
(assert (forall ((xs (List Int)))
  (ite (= nil xs)
    (= 0 (len xs))
    (= (+ 1 (len (tail xs))) (len xs)))))

What would be the smartest way of encoding sort-generic list functions? (If I remember correctly, functions cannot be generic per se).


Solution

  • The SMT 2.0 format or Z3 do not support parametric axioms in SMT 2.0 scripts. One alternative is to use the programmatic APIs. You can create functions that create the len axiom for a given sort. Here is an example on how to do it using the Python API.

    http://rise4fun.com/Z3Py/vNa

    from z3 import *
    def MkList(sort):
        List = Datatype('List')
        List.declare('insert', ('head', sort), ('tail', List))
        List.declare('nil')
        return List.create()
    
    
    def MkLen(sort):
        List = MkList(sort)
        Len  = Function('len', List, IntSort())
        x    = Const('x', List)
        Ax   = ForAll(x, If(x == List.nil, Len(x) == 0, Len(x) == 1 + Len(List.tail(x))))
        return (Len, [Ax])
    
    IntList = MkList(IntSort())
    IntLen,  IntLenAxioms = MkLen(IntSort())
    print IntLenAxioms
    s = Solver()
    l1 = Const('l1', IntList)
    s.add(IntLenAxioms)
    s.add(IntLen(l1) == 0)
    s.add(l1 == IntList.insert(10, IntList.nil))
    print s.check()