Z3中的回溯增加了求解器找到答案的时间

Z3中的回溯增加了求解器找到答案的时间,z3,Z3,我有一个用Java实现的工具。 我们已经使用JavaJNI与Z3SAT解算器C-API接口。 我使用的是Z3版本4.1 鉴于这种情况,我做了以下实验- 实验1- 我在解算器中声明一些约束 我检查结果是sat还是unsat 实验2- 我在解算器中断言相同约束的子集 我使用Z3\u solver\u push() 我断言剩余的约束 我检查结果是sat还是unsat 我做实验2的原因是需要回溯 现在在实验1中,我得到了查询所需的时间始终少于5秒。到目前为止,我已经检查了大约20-30次。有时甚至不到2

我有一个用Java实现的工具。 我们已经使用
JavaJNI
与Z3SAT解算器C-API接口。 我使用的是Z3版本4.1

鉴于这种情况,我做了以下实验-

实验1-

  • 我在解算器中声明一些约束
  • 我检查结果是sat还是unsat
  • 实验2-

  • 我在解算器中断言相同约束的子集
  • 我使用
    Z3\u solver\u push()
  • 我断言剩余的约束
  • 我检查结果是sat还是unsat
  • 我做实验2的原因是需要回溯

    现在在实验1中,我得到了查询所需的时间始终少于5秒。到目前为止,我已经检查了大约20-30次。有时甚至不到2秒

    现在进行实验2,注意到约束条件完全相同,我得到的查询时间有时是5秒,有时是10秒,有时是50秒。我还看到查询是“超时”,超时时间为60秒

    为了消除一些疑虑,我在命令行中执行了相同的实验。 在实验1中,我发现查询时间总是在2.3-2.7秒之间。 然而,在实验2中,(我手动输入了一个
    push
    语句),时间变了,如前所述。它在10-60秒之间变化

    我想知道,按下上下文是否会导致查询中的这种变化? 理想情况下,它不应该这样做。但是有机会吗

    我们如何避免这种随机性并获得类似于无
    push
    语句的稳定行为

    更新

    我已经添加了示例约束,我想知道应该使用哪种策略。 请注意,它不能重现实验中提到的问题。然而,我们使用多个这样的约束,如下面给出的,这可以重现问题-

    (set-option :produce-models true) ; enable model generation
    (set-option :print-success false)
    (declare-const goal1 Int)
    (declare-const goal2 Int)
    (declare-const goal3 Int)
    (declare-const kmax Int)
    (declare-const ordA0_A0 Bool)
    (declare-const ordA0_B0 Bool)
    (declare-const ordB0_B0 Bool)
    (declare-const ordB0_A0 Bool)
    (declare-const stA0 Int)
    (declare-const stB0 Int)
    (declare-const stPA_0 Int)
    (declare-const enPA_0 Int)
    (declare-const stPB_0 Int)
    (declare-const enPB_0 Int)
    (declare-const kstA0 Int)
    (declare-const kyA_0 Int)
    (declare-const kstB0 Int)
    (declare-const kyB_0 Int)
    (declare-const resA_0 Int)
    (declare-const resB_0 Int)
    
    (assert (if (>= stPA_0 enPA_0) (= ordA0_A0 true) (= ordA0_A0 false)))
    (assert (if (>= stPB_0 enPB_0) (= ordB0_B0 true) (= ordB0_B0 false)))
    (assert (if (>= stPA_0 enPB_0) (= ordB0_A0 true) (= ordB0_A0 false)))
    (assert (if (>= stPB_0 enPA_0) (= ordA0_B0 true) (= ordA0_B0 false)))
    
    (assert (and (>= stA0 0) (<= stA0 goal2)))
    (assert (and (>= stB0 0) (<= stB0 goal2)))
    (assert (or (= stA0 0) (= stB0 0)))
    (assert (>= stB0 (+ stA0 1)))
    (assert (=> (and (= resA_0 resB_0) (= ordA0_A0 false) (= ordB0_B0 false)) (or (= ordA0_B0 true) (= ordB0_A0 true))))
    (assert (=> (and (= resA_0 resB_0) (or (= ordA0_A0 true) (= ordB0_B0 true))) (and (= ordA0_B0 true) (= ordB0_A0 true))))
    
    (assert (and (>= resA_0 0) (< resA_0 goal3)))
    (assert (and (>= resB_0 0) (< resB_0 goal3)))
    
    (assert (=> (= resA_0 resB_0) (or (= ordA0_A0 false) (= ordB0_B0 false))))
    
    (assert (= stPA_0 (- stA0 (* goal1 kstA0))))
    (assert (= enPA_0 (- (+ stA0 1) (* goal1 kyA_0))))
    (assert (= stPB_0 (- stB0 (* goal1 kstB0))))
    (assert (= enPB_0 (- (+ stB0 2) (* goal1 kyB_0))))
    (assert (= kstA0 (div stA0 goal1)))
    (assert (= kyA_0 (div (+ stA0 1) goal1)))
    (assert (= kstB0 (div stB0 goal1)))
    (assert (= kyB_0 (div (+ stB0 2) goal1)))
    (assert (= goal2 (+ stB0 1)))
    (assert (>= goal1 1))
    (assert (<= goal2 6))
    (assert (= kmax (div 6 goal1)))
    (assert (<= goal2 6))
    (assert (<= goal3 5))
    (assert (= goal1 3))
    
    (check-sat)
    (get-model)
    
    (设置选项:生成模型为真);启用模型生成
    (设置选项:打印成功为false)
    (声明const goal1 Int)
    (声明const goal2 Int)
    (声明const goal3 Int)
    (声明常数kmax Int)
    (宣布常数或值)
    (声明常数或布尔值)
    (声明常量或布尔值)
    (声明常量ordB0_A0布尔)
    (声明常数stA0 Int)
    (声明常量stB0 Int)
    (声明常数stPA_0 Int)
    (声明const enPA_0 Int)
    (声明常数stPB_0 Int)
    (声明常量enPB_0 Int)
    (声明常量kstA0 Int)
    (声明const kyA_0 Int)
    (声明常量kstB0 Int)
    (声明const kyB_0 Int)
    (声明const resA_0 Int)
    (声明常量resB_0 Int)
    (断言(如果(>=stPA_0 enPA_0)(=ordA0_A0 true)(=ordA0_A0 false)))
    (断言(如果(>=stPB_0 enPB_0)(=ordB0_B0 true)(=ordB0_B0 false)))
    (断言(如果(>=stPA_0 enPB_0)(=ordB0_A0 true)(=ordB0_A0 false)))
    (断言(如果(>=stPB_0 enPA_0)(=ordA0_B0 true)(=ordA0_B0 false)))
    (断言(和(>=stA0)(=STB00)(=stB0(+STA01)))
    (断言(=>(和(=resA_0 resB_0)(=ordA0_A0 false)(=ordB0_B0 false))(或(=ordA0_B0 true)(=ordB0_A0 true)))
    (断言(=>(和(=resA_0 resB_0)(或(=ordA0_A0 true)(=ordB0_B0 true)))(和(=ordA0_B0 true)(=ordB0_A0 true)))
    (断言(和(>=resA_0 0)(=resB_0)((=resA_0 resB_0)(或(=ordA0_A0 false)(=ordB0_B0 false)))
    (断言(=stPA_0(-stA0(*goal1 kstA0)))
    (断言(=enPA_0(-stA0 1)(*goal1 kyA_0)))
    (断言(=stPB_0(-stB0(*goal1 kstB0)))
    (断言(=enPB_0(-stB0 2)(*goal1 kyB_0)))
    (断言(=kstA0(div stA0 goal1)))
    (断言(=kyA_0(部门(+stA0 1)目标)))
    (断言(=kstB0(分区stB0目标1)))
    (断言(=kyB_0(部门(+stB0 2)目标1)))
    (断言(=目标2(+stB0 1)))
    (断言(>=目标1))
    
    (assert(Z3是解算器的集合。默认解算器对象是解算器的组合。组合中并非每个解算器都是增量的。只要使用
    Z3_solver_push()
    ,它将使用通用增量解算器。此通用解算器的效率可能远低于非增量解算器。即使在
    Z3_solver_push()时,您也可以强制Z3使用非增量解算器使用了
    。但是,Z3将从零开始执行每一次
    检查
    ,并且不会重用以前的
    检查
    查询中的任何工作


    用于创建非增量解算器的主要API是
    Z3_mk_solver_from_tractic

    Z3是解算器的集合。默认解算器对象是解算器的组合。并非组合中的每个解算器都是增量的。只要使用
    Z3_solver_push()
    ,它将使用通用增量解算器。此通用解算器的效率可能远低于非增量解算器。即使在
    Z3_solver_push()时,您也可以强制Z3使用非增量解算器使用了
    。但是,Z3将从零开始执行每一次
    检查
    ,并且不会重用以前的
    检查
    查询中的任何工作


    创建非增量解算器的主要API是
    Z3_mk_solver\u from_tractic

    但是在这种情况下应该使用哪种策略?我尝试使用
    simplify
    策略,它为该查询返回
    UNKNOWN
    simplify
    只是一个预处理器,它只能决定非常简单的公式。其思想是组合使用组合器将策略组合在一起。理想的组合取决于问题。您可以在此处找到更多信息:如何找到我们必须使用的策略组合?在查询没有
    Z3_solver_push()的解算器时,是否可以确定解算器使用的策略
    ?但在这种情况下应该使用哪种策略?我尝试使用
    simplify
    策略,它为该查询返回
    UNKNOWN
    simplify
    只是一个预处理器,它只能决定非常简单的公式。其思想是组合策略