I'm trying to collect all the variables in a formula (quantified formula in Z3py). A small example
w, x, y, z = Bools('w x y z')
fml = And( ForAll(x, ForAll(y, And(x, y))), ForAll(z, ForAll(w, And(z, w))) )
varSet = traverse( fml )
The code i use to traverse is
def traverse(e):
r = set()
def collect(e):
if is_quantifier(e):
# Lets assume there is only one type of quantifier
if e.is_forall():
collect(e.body())
else:
if ( is_and(e) ):
n = e.num_args()
for i in range(n):
collect( e.arg(i) )
if ( is_or(e) ):
n = e.num_args()
for i in range(n):
collect( e.arg(i) )
if ( is_not(e) ):
collect( e.arg(0) )
if ( is_var(e) ):
r.add( e )
collect(e)
return r
And I'm getting: set( [Var(0), Var(1)] ). As i understand this is due to Z3 uses De Bruijn index. Is it possible to avoid this and get the desired set: set( [Var(0), Var(1), Var(2), Var(3)] ).
Your code is correct; there is no Var(2)
or Var(3)
in this example. There are two top-level quantifiers and the de-Bruijn indices in each of them are 0 and 1. Those two quantifiers do not appear within the body of another quantifier, so there can be no confusion.