如何计算api中smtlib2文件中的总约束数

时间:2013-07-11 10:52:07

标签: z3

我使用Z3_ast fs = Z3_parse_smtlib2_file(ctx,arg[1],0,0,0,0,0,0)来读取文件。

此外,要使用expr F = to_expr(ctx,fs)然后s.add(F)添加到求解器中。

我的问题是如何获得每个实例中的总约束数?

我也试过了F.num_args(),但是在某些情况下它的大小是错误的。

有没有办法计算总约束?

1 个答案:

答案 0 :(得分:1)

在将Goal.size()添加到某个目标后,使用F可能会执行您想要的操作。这是Python API描述的链接,我相信您可以在C / C ++ API中找到相应的内容:http://research.microsoft.com/en-us/um/redmond/projects/z3/z3.html#Goal-size

expr F表示抽象语法树,因此F.num_args()返回F所拥有的(一步)子项的数量,这可能就是为什么你一直在尝试的永远不会工作。例如,假设F = a + b,然后F.num_args() = 2。但是,如果F = a + b*c,那么F.num_args() = 2,孩子将在ab*c(假设通常的操作顺序)。因此,要计算约束的数量(如果您的定义与Goal.size()产生的不同),您可以使用遍历树的递归方法。

我在下面添加了一个示例,突出显示所有这些内容(此处为z3py链接:http://rise4fun.com/Z3Py/It5E)。

例如,我对约束的定义(或者说某种意义上的表达式的复杂性)可能是叶子的数量或表达式的深度。您可以根据需要获得详细信息,例如,计算不同类型的操作数以适应您对约束的定义,因为您的问题并不完全清楚。例如,您可以将约束定义为表达式中出现的等式和/或不等式的数量。这可能需要修改以适用于具有量词,数组或未解释函数的公式。另请注意,Z3可能会自动简化操作(例如,1 - 1在以下示例中简化为0

a, b, c = Reals('a b c')

F = a + b
print F.num_args() # 2

F = a + b * c
print F.num_args() # 2

print F.children() # [a,b*c]

g = Goal()
g.add(F == 0)
print g.size() # number of constraints = 1

g.add(Or(F == 0, F == 1, F == 2, F == 3))
print g.size() # number of constraints = 2
print g

g.add(And(F == 0, F == 1, F == 2, F == 3))
print g.size() # number of constraints = 6
print g

def count_constraints(c,d,f):
  print 'depth: ' + str(d) + ' expr: ' + str(f)
  if f.num_args() == 0:
    return c + 1
  else:
    d += 1
    for a in f.children():
      c += count_constraints(0, d, a)
    return c

exp = a + b * c + a + c * c
print count_constraints(0,0,exp)

exp = And(a == b, b == c, a == 0, c == 0, b == 1 - 1)
print count_constraints(0,0,exp)

q, r, s = Bools('q r s')
exp = And(q, r, s)
print count_constraints(0,0,exp)