我正在尝试学习z3,这是我写的第一个程序。
在本练习中,我试图确定x是否为素数。如果x是素数,则返回SAT,否则,返回UNSAT及其两个因子。
这是我到目前为止所拥有的 http://rise4fun.com/Z3/STlX
我的问题是我认为代码现在没有做任何事情。无论我做什么,它都会返回SAT。即如果我断言7是素数,则返回SAT,如果断言7不是素数,则返回SAT。
我不确定递归是如何在z3中起作用的,但我已经看到了一些例子,我试图模仿它们如何进行递归。
如果你们能够看一看并告诉我哪里出错了,我会非常感激。
答案 0 :(得分:1)
我已经习惯于递归思考,在篡改了几个小时后,我找到了另一种方法来实现它。对于任何有兴趣的人,这是我的实施。
答案 1 :(得分:0)
以下公式未达到您的评论指定的内容:
; recursively call divides on y++
;; as long as y < x
;; Change later to y < sqrt(x)
(declare-fun hasFactors (Int Int) Bool)
(assert
(and (and (not (divides x y))
(not (hasFactors x (+ y 1)))) (< y x))
)
第一个问题是x,y是免费的。它们之前被声明为常量。 你的评论说你想递归调用divides,递增y直到达到x。 您可以使用量化公式来指定满足此属性的关系。 你必须写下以下内容:
(assert (forall ((x Int) (y Int)) (iff (hasFactors x y) (and (< y x) (or (divides y x) (hasFactors x (+ y 1))))))
在调用check-sat之前,您还必须指定要检查的公式。 使用SMT求解器查找素数当然不会是实用的,但会说明当Z3实例化量词时所获得的一些行为,这取决于 问题域和编码可以快速或非常昂贵。
答案 2 :(得分:0)
感谢部分解决方案! isPrime的完整解决方案是:
(define-fun isPrime ((x Int)) Bool
(and
(> x 1)
(not (exists ((z Int) (y Int))
(and (< y x) (< z x) (> y 1) (> z 1) (= x (* y z)))))))
告诉我的不仅仅是我愿意承认要做对。