z3pythonapi中的扩展欧几里德算法

z3pythonapi中的扩展欧几里德算法,python,z3,smt,Python,Z3,Smt,我试图在Z3中对扩展的欧几里德算法建模,但遇到了无限循环 def extended_euclid(a, b): d = If(b == 0, a, extended_euclid(b, a % b)[0]) x1 = If(b == 0, 1, extended_euclid(b, a % b)[1]) y1 = If(b == 0, 0, extended_euclid(b, a % b)[2]) q = If(b == 0, 1, a // b) x = If

我试图在Z3中对扩展的欧几里德算法建模,但遇到了无限循环

def extended_euclid(a, b):
   d = If(b == 0, a, extended_euclid(b, a % b)[0])
   x1 = If(b == 0, 1, extended_euclid(b, a % b)[1])
   y1 = If(b == 0, 0, extended_euclid(b, a % b)[2])

   q = If(b == 0, 1, a // b)
   x = If(b == 0, 1, y1)
   y = If(b == 0, 0, x1-y1*q)
   return d, x, y


a = Int('a')
b = Int('b')

s = Solver()
s.add(extended_euclid(a, b)[0] == 1)
print s.sexpr()
print s.check()
欢迎提出建议和意见

第一个函数是用Python编写的,仅供参考

第二个函数是z3分析它时遇到无限循环的函数

在我如何将常规Python函数映射到相应的Z3语法时,您是否看到任何错误

'''
Returns d, x, y such that a*x + b*y = d
d = gcd(a, b)
'''
def extended_euclid_rec(a, b):
    if b == 0:
       d = a; x = 1; y = 0 # y can be any int
       return d, x, y
    else:
       d, x1, y1 = extended_euclid_rec(b, a % b)
       q = a // b
       x = y1
       y  = x1-y1*q
       assert a*x + b*y == d
       return d, x, y
这个函数进入一个无限循环

def extended_euclid(a, b):
   d = If(b == 0, a, extended_euclid(b, a % b)[0])
   x1 = If(b == 0, 1, extended_euclid(b, a % b)[1])
   y1 = If(b == 0, 0, extended_euclid(b, a % b)[2])

   q = If(b == 0, 1, a // b)
   x = If(b == 0, 1, y1)
   y = If(b == 0, 0, x1-y1*q)
   return d, x, y


a = Int('a')
b = Int('b')

s = Solver()
s.add(extended_euclid(a, b)[0] == 1)
print s.sexpr()
print s.check()

这里的问题是,您使用符号输入运行函数,因此递归永远不会停止。您不能直接使用Python函数对这样的递归函数建模,除非您保证递归将具体停止

一个经典的技巧是向函数传递一个额外的计数器,它将是一个正则整数(不是z3符号整数!),在每次递归调用中递减。只要计数足够大,就可以通过这种方式进行验证。但是,确定计数的大小取决于要建模的算法,可能很难确定

另一种选择是使用z3的递归函数定义功能,在这里,您可以将函数作为z3py函数(而不是Python函数)递归地编写。然而,这也是相当棘手的,因为大多数递归函数需要归纳证明,而SMT解算器不做归纳


总之,z3(或任何其他SMT解算器)并不是为此类递归程序建模的正确工具。相反,使用适当的定理证明程序,如Isabelle、ACL2、Coq、Lean等;所有这些都支持这种开箱即用的递归定义。虽然这些工具不是按钮式的,但它们提供了大量的自动化证明来帮助您。

好吧,您的函数无条件地调用自己,因此它具有无限递归。你真的需要对这个算法的过程建模,还是只需要表示两个整数互质的约束?谢谢。我需要对这个算法的过程进行建模。如果b==0,那么递归应该停止,这是Python中第一个运行良好的函数的情况——假设递归的深度设置正确。
b
是一个形式变量,在调用函数时它不能等于零,因为当时它没有值。如果实际上没有分支,那么您的函数将无条件地调用自己。非常感谢您的评论。