我刚刚开始研究Z3的定点求解器,并且我编写了一个示例,该示例在使用乘法时挂起,但是在将乘法定义为一系列加法时完成。由于我刚开始使用Horn子句,因此可能有些我不了解的内容。是否有理由说“本机”乘法如此缓慢,而定义为一系列加法的乘法却会在合理的时间范围内产生令人满意的结果?谢谢!
def test_mseq_hangs():
mul = Function('mul', IntSort(), IntSort(), IntSort(), BoolSort())
mc = Function('mc', IntSort(), IntSort(), BoolSort())
n, m, p = Ints('m n p')
fp = Fixedpoint()
fp.declare_var(n,m,p)
fp.register_relation(mc, mul)
fp.fact(mul(m, n, m * n))
fp.rule(mc(m, 1), m <= 1)
fp.rule(mc(m, n), [m > 1 , mc(m-1, p), mul(m, p, n)])
assert fp.query(And(mc(m,n),n < 1)) == unsat
assert fp.query(And(mc(m,n),n < 2)) == sat
assert fp.query(And(mc(m,n),n > 100 )) == sat
assert fp.query(mc(5,120)) == sat
assert fp.query(mc(5,24)) == unsat
def test_mseq():
mul = Function('mul', IntSort(), IntSort(), IntSort(), BoolSort())
add = Function('add', IntSort(), IntSort(), IntSort(), BoolSort())
neg = Function('neg', IntSort(), IntSort(), BoolSort())
mc = Function('mc', IntSort(), IntSort(), BoolSort())
n, m, p, o = Ints('m n p o')
fp = Fixedpoint()
fp.declare_var(n,m,p,o)
fp.register_relation(mc, add, mul, neg)
fp.fact(add(m, n, m + n))
fp.fact(neg(m, -m))
fp.rule(mul(m, n, 0), n == 0)
fp.rule(mul(m, n, m), n == 1)
fp.rule(mul(m, n, o), [n < 0, mul(m,n,p), neg(p,o)])
fp.rule(mul(m, n, o), [n > 1, mul(m,n-1,p), add(m,p,o)])
fp.rule(mc(m, 1), m <= 1)
fp.rule(mc(m, n), [m > 1 , mc(m-1, p), mul(m, p, n)])
assert fp.query(And(mc(m,n),n < 1)) == unsat
assert fp.query(And(mc(m,n),n < 2)) == sat
assert fp.query(And(mc(m,n),n > 100 )) == sat
assert fp.query(mc(5,120)) == sat
assert fp.query(mc(5,24)) == unsat
答案 0 :(得分:1)
这并不奇怪,因为变量相乘会导致非线性算术,而重复加法则将其留在线性片段中。非线性算术是不可确定的,而线性片段有有效的决策程序(如Presburger)。
我不确定在这里定点引擎如何发挥作用,但是上面的内容适用于一般查询;我猜想同样的道理也适用。
话虽如此,Z3 确实具有一个称为nlsat
的非线性算术求解器。您可能想尝试一下,尽管我不会屏住呼吸。有关如何触发此问题的信息,请参见以下问题:(check-sat) then (check-sat-using qfnra-nlsat)
NB 。我不确定是否可以通过Python使用来自FixedPoint引擎的nlsat
引擎,因此您可能需要做一些挖掘工作才能找出如果可以的话,应该是正确的咒语。