z3 icon indicating copy to clipboard operation
z3 copied to clipboard

Instable Java API in comparison to commandline-tool

Open facferreira opened this issue 7 years ago • 5 comments

Hi, I attempted to run solver.check() using the Java API and (check-sat) in commandline-tool to compare the runtimes. I understand that the Java API may be slightly slower than commandline-tool, however the results I obtained do not seem so much expected. While with (check-sat) I found some stability as well being fast (given a flag is enabled as I explain below), with Java API I noticed instability (ranging from slow to extremely slow to timeout) and being much slower than (check-sat). Is this expected?

To benchmark both, I run the corresponding check function 10 times. Note that configured timeout is 20s, thus several attempts with Java API ended in timeout. To test with Java API I run:

Context context1 = new Context();
Solver solver1 = context1.mkSolver();
Params params = context1.mkParams();
params.add("candidate_models", true);
params.add("fail_if_inconclusive", false);
solver1.setParameters(params);
BoolExpr assertions = context1.parseSMTLIB2File("<path to file>.z3",null, null, null, null);
solver1.add(assertions);
for (int i = 0; i < 10; i++) {
    long start = System.currentTimeMillis();
    solver1.check();
    long diff = System.currentTimeMillis() - start;
    System.out.println(diff + "ms");
}

The measured times were:

  • 10328ms
  • 6590ms
  • 20733ms
  • 8091ms
  • 20832ms
  • 6793ms
  • 20920ms
  • 9347ms
  • 20864ms
  • 20869ms

With the commandline-tool I tried by two ways: with (set-option :produce-proofs true) and without (set-option :produce-proofs true). With (set-option :produce-proofs true) I got always a result after ~2.1-2.4s. Without (set-option :produce-proofs true) I got timeout every time.

So, my question is why the difference in runtime between solver.check() (including why there may be instability with it) and the commandline-tool with (set-option :produce-proofs true)? Besides that, why in the commandline-tool the line (set-option :produce-proofs true) produces such a radical difference?

The file I used was

(set-info :smt-lib-version 2.0)

(set-option :auto_config false)
(set-option :smt.mbqi false)
;(set-option :produce-proofs true)

(set-option :model_evaluator.completion false)
(set-option :model.v1 true)
(set-option :smt.phase_selection 0)
(set-option :smt.restart_strategy 0)
(set-option :smt.restart_factor 1.5)
(set-option :nnf.sk_hack true)
(set-option :smt.qi.eager_threshold 100.0)
(set-option :smt.arith.random_initial_value true)
(set-option :smt.case_split 3)
(set-option :smt.delay_units true)
(set-option :smt.delay_units_threshold 16)
(set-option :type_check true)
(set-option :smt.bv.reflect true)
(set-option :smt.timeout 20000)


(declare-datatypes () ((General (G_Boolean (of_G_Boolean Bool)) (G_Integer (of_G_Integer Int)) (G_String (of_G_String String)) (G_Null))))
(declare-sort SVMap)
(declare-sort IVMap)
(declare-datatypes () ((Value (G (out_G General)) (E (out_E SVMap)) (C (out_C IVMap)) (R (id Int) (type String) (identifiers Value)))))
(declare-datatypes () ((ValueOption (NoValue) (SomeValue (of_SomeValue Value)))))
(declare-fun r_resourceidof (Value Value) Value)
(declare-fun v_contains (Value Value) Value)
(declare-fun Good_R (Value) Bool)
(declare-fun In_String (Value) Bool)
(declare-fun v_nth (Value Value) Value)
(declare-fun v_integer (Int) Value)
(declare-fun v_length (Value) Value)
(declare-fun Good_C (Value) Bool)
(declare-fun r_representationof (Value Value) Value)
(declare-fun v_ff () Value)
(declare-fun v_tt () Value)
(declare-fun alphai (IVMap) (Array Int ValueOption))
(declare-fun In_Integer (Value) Bool)
(declare-fun betai ((Array Int ValueOption)) IVMap)
(declare-fun v_dot (String Value) Value)
(declare-fun alphas (SVMap) (Array String ValueOption))
(declare-fun v_has_field (String Value) Bool)
(declare-fun betas ((Array String ValueOption)) SVMap)
(declare-fun v_string (String) Value)
(declare-fun O_LE (Value Value) Value)
(declare-fun O_LT (Value Value) Value)
(declare-fun O_GT (Value Value) Value)
(declare-fun O_GE (Value Value) Value)
(declare-fun O_Or (Value Value) Value)
(declare-fun O_And (Value Value) Value)
(declare-fun O_Minus (Value) Value)
(declare-fun O_Not (Value) Value)
(declare-fun O_NE (Value Value) Value)
(declare-fun O_EQ (Value Value) Value)
(declare-fun O_Mult (Value Value) Value)
(declare-fun O_Sub (Value Value) Value)
(declare-fun O_Sum (Value Value) Value)
(declare-fun In_Boolean (Value) Bool)
(declare-fun v_boolean (Bool) Value)
(declare-fun v_null () Value)
(declare-fun Good_E (Value) Bool)
(declare-fun maze () Value)
(declare-fun root () Value)
(declare-fun request () Value)
(assert (let ((a!1 (forall ((b Bool))
             (! (= (v_boolean b) (G (G_Boolean b))) :pattern ((v_boolean b)))))
      (a!2 (forall ((i Int))
             (! (= (v_integer i) (G (G_Integer i))) :pattern ((v_integer i)))))
      (a!3 (forall ((s String))
             (! (= (v_string s) (G (G_String s))) :pattern ((v_string s)))))
      (a!4 (forall ((v Value))
             (! (= (In_Boolean v) (and (is-G v) (is-G_Boolean (out_G v))))
                :pattern ((In_Boolean v)))))
      (a!5 (forall ((v Value))
             (! (= (In_Integer v) (and (is-G v) (is-G_Integer (out_G v))))
                :pattern ((In_Integer v)))))
      (a!6 (forall ((v Value))
             (! (= (In_String v) (and (is-G v) (is-G_String (out_G v))))
                :pattern ((In_String v)))))
      (a!7 (forall ((v1 Value) (v2 Value))
             (! (= (O_EQ v1 v2) (ite (= v1 v2) v_tt v_ff))
                :pattern ((O_EQ v1 v2)))))
      (a!8 (forall ((v1 Value) (v2 Value))
             (! (= (O_NE v1 v2) (ite (= v1 v2) v_ff v_tt))
                :pattern ((O_NE v1 v2)))))
      (a!9 (forall ((v Value))
             (! (= (O_Not v) (ite (not (= v v_tt)) v_tt v_ff))
                :pattern ((O_Not v)))))
      (a!10 (forall ((v1 Value) (v2 Value))
              (! (= (O_And v1 v2) (ite (and (= v1 v_tt) (= v2 v_tt)) v_tt v_ff))
                 :pattern ((O_And v1 v2)))))
      (a!11 (forall ((v1 Value) (v2 Value))
              (! (= (O_Or v1 v2) (ite (or (= v1 v_tt) (= v2 v_tt)) v_tt v_ff))
                 :pattern ((O_Or v1 v2)))))
      (a!12 (forall ((v Value))
              (! (let ((a!1 (= (str.len (of_G_String (out_G v)))
                               (of_G_Integer (out_G (v_length v))))))
                   (=> (and (is-G v) (is-G_String (out_G v))) a!1))
                 :pattern ((v_length v)))))
      (a!13 (forall ((v1 Value) (v2 Value))
              (! (let ((a!1 (ite (str.contains (of_G_String (out_G v1))
                                               (of_G_String (out_G v2)))
                                 v_tt
                                 v_ff)))
                   (=> (and (is-G v1)
                            (is-G_String (out_G v1))
                            (is-G v2)
                            (is-G_String (out_G v2)))
                       (= (v_contains v1 v2) a!1)))
                 :pattern ((v_contains v1 v2)))))
      (a!14 (forall ((v Value) (i Int))
              (! (let ((a!1 (v_string (str.at (of_G_String (out_G v)) i))))
                   (=> (and (is-G v) (is-G_String (out_G v)))
                       (= (v_nth v (v_integer i)) a!1)))
                 :pattern ((v_nth v (v_integer i))))))
      (a!15 (forall ((am (Array String ValueOption)))
              (= (alphas (betas am)) am)))
      (a!16 (forall ((svm SVMap)) (= (betas (alphas svm)) svm)))
      (a!17 (forall ((l String) (svm SVMap))
              (! (let ((a!1 (not (= (select (alphas svm) l) NoValue))))
                   (= (v_has_field l (E svm)) a!1))
                 :pattern ((v_has_field l (E svm))))))
      (a!18 (forall ((l String) (svm SVMap))
              (! (= (v_dot l (E svm)) (of_SomeValue (select (alphas svm) l)))
                 :pattern ((v_dot l (E svm))))))
      (a!19 (forall ((am (Array Int ValueOption))) (= (alphai (betai am)) am)))
      (a!20 (forall ((ivm IVMap)) (= (betai (alphai ivm)) ivm)))
      (a!21 (forall ((v Value))
              (! (let ((a!1 (>= (of_G_Integer (out_G (v_length v))) 0)))
                   (=> (Good_C v) (and (In_Integer (v_length v)) a!1)))
                 :pattern ((Good_C v)))))
      (a!22 (forall ((v Value) (i Int))
              (! (let ((a!1 (of_SomeValue (select (alphai (out_C v)) i))))
                   (=> (Good_C v) (= (v_nth v (v_integer i)) a!1)))
                 :pattern ((Good_C v) (v_nth v (v_integer i))))))
      (a!23 (forall ((v1 Value) (v2 Value))
              (! (let ((a!1 (exists ((i Int))
                              (let ((a!1 (< i
                                            (of_G_Integer (out_G (v_length v1))))))
                                (and (<= 0 i)
                                     a!1
                                     (= (v_nth v1 (v_integer i)) v2))))))
                   (=> (and (is-C v1))
                       (= (v_contains v1 v2) (ite a!1 v_tt v_ff))))
                 :pattern ((v_contains v1 v2)))))
      (a!24 (forall ((r1 Value) (r2 Value))
              (! (= (= r1 r2) (= (id r1) (id r2)))
                 :pattern ((Good_R r1) (Good_R r2)))))
      (a!25 (forall ((v Value) (r Value))
              (! (=> (Good_R r) (=> (is-R v) (= (r_representationof v r) v_ff)))
                 :pattern ((Good_R r) (r_representationof v r)))))
      (a!26 (forall ((r Value))
              (! (let ((a!1 (forall ((i Int))
                              (let ((a!1 (of_G_Integer (out_G (v_length (identifiers r))))))
                                (=> (and (<= 0 i) (< i a!1))
                                    (In_String (v_nth (identifiers r)
                                                      (v_integer i))))))))
                   (=> (Good_R r) (and (Good_C (identifiers r)) a!1)))
                 :pattern ((Good_R r)))))
      (a!27 (forall ((id Value) (r Value))
              (! (=> (and (In_String id) (Good_R r))
                     (= (r_resourceidof id r) (v_contains (identifiers r) id)))
                 :pattern ((r_resourceidof id r)))))
      (a!28 (forall ((|\|\\\\\\\|#18\\\\\\\|\|| Int))
              (let ((a!1 (< |\|\\\\\\\|#18\\\\\\\|\||
                            (of_G_Integer (out_G (v_length maze)))))
                    (a!2 (= (type (v_nth maze
                                         (v_integer |\|\\\\\\\|#18\\\\\\\|\||)))
                            "Maze")))
              (let ((a!3 (and (Good_R (v_nth maze
                                             (v_integer |\|\\\\\\\|#18\\\\\\\|\||)))
                              a!2)))
                (=> (and (<= 0 |\|\\\\\\\|#18\\\\\\\|\||) a!1) (or a!3 a!3 a!3))))))
      (a!29 (= (type (v_nth maze (v_integer 0))) "Maze"))
      (a!31 (= (type (v_nth maze (v_integer 1))) "Maze"))
      (a!33 (= (type (v_nth maze (v_integer 2))) "Maze"))
      (a!36 (forall ((|\|\\\\\\\|#19\\\\\\\|\|| Int))
              (let ((a!1 (< |\|\\\\\\\|#19\\\\\\\|\||
                            (of_G_Integer (out_G (v_length request)))))
                    (a!2 (not (Good_R (v_nth request
                                             (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!3 (Good_R (v_dot "template"
                                        (v_nth request
                                               (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!4 (Good_E (v_dot "template"
                                        (v_nth request
                                               (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!5 (v_has_field "mazeId"
                                      (v_dot "template"
                                             (v_nth request
                                                    (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!6 (v_dot "mazeId"
                                (v_dot "template"
                                       (v_nth request
                                              (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!10 (Good_E (v_dot "header"
                                         (v_nth request
                                                (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!11 (In_String (v_dot "location"
                                            (v_nth request
                                                   (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))))
                    (a!12 (Good_R (v_dot "body"
                                         (v_nth request
                                                (v_integer |\|\\\\\\\|#19\\\\\\\|\||))))))
              (let ((a!7 (v_boolean (and a!4 a!5 (not (Good_R a!6))))))
              (let ((a!8 (O_And (O_And (v_boolean (and a!4))
                                       (v_boolean (and a!4)))
                                (v_boolean (and (not a!3) (= a!7 v_tt))))))
              (let ((a!9 (O_And (O_And a!8 (v_boolean (and a!4)))
                                (v_boolean (and a!4)))))
              (let ((a!13 (and (Good_E (v_nth request
                                              (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))
                               (v_has_field "template"
                                            (v_nth request
                                                   (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))
                               (not a!3)
                               (= a!9 v_tt)
                               (v_has_field "header"
                                            (v_nth request
                                                   (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))
                               a!10
                               (v_has_field "location"
                                            (v_nth request
                                                   (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))
                               a!11
                               (v_has_field "body"
                                            (v_nth request
                                                   (v_integer |\|\\\\\\\|#19\\\\\\\|\||)))
                               (not a!12))))
                (=> (and (<= 0 |\|\\\\\\\|#19\\\\\\\|\||) a!1)
                    (or a!2 a!13 a!2)))))))))
      (a!37 (not (Good_R (v_nth request (v_integer 0)))))
      (a!38 (Good_R (v_dot "template" (v_nth request (v_integer 1)))))
      (a!39 (Good_E (v_dot "template" (v_nth request (v_integer 1)))))
      (a!40 (v_has_field "mazeId"
                         (v_dot "template" (v_nth request (v_integer 1)))))
      (a!41 (v_dot "mazeId" (v_dot "template" (v_nth request (v_integer 1)))))
      (a!45 (Good_E (v_dot "header" (v_nth request (v_integer 1)))))
      (a!46 (In_String (v_dot "location" (v_nth request (v_integer 1)))))
      (a!47 (Good_R (v_dot "body" (v_nth request (v_integer 1)))))
      (a!49 (not (Good_R (v_nth request (v_integer 2)))))
      (a!51 (forall ((|\|\\\\\\\|#20\\\\\\\|\|| Int))
              (let ((a!1 (< |\|\\\\\\\|#20\\\\\\\|\||
                            (of_G_Integer (out_G (v_length root)))))
                    (a!2 (not (Good_R (v_nth root
                                             (v_integer |\|\\\\\\\|#20\\\\\\\|\||))))))
              (let ((a!3 (or a!2
                             (In_String (v_nth root
                                               (v_integer |\|\\\\\\\|#20\\\\\\\|\||)))
                             a!2)))
                (=> (and (<= 0 |\|\\\\\\\|#20\\\\\\\|\||) a!1) a!3)))))
      (a!52 (not (Good_R (v_nth root (v_integer 0)))))
      (a!53 (v_boolean (In_String (v_nth root (v_integer 1)))))
      (a!54 (not (Good_R (v_nth root (v_integer 2)))))
      (a!56 (v_integer (id (v_nth maze (v_integer 1)))))
      (a!57 (Good_E (v_dot "body" (v_nth request (v_integer 1)))))
      (a!58 (v_has_field "name" (v_dot "body" (v_nth request (v_integer 1)))))
      (a!59 (v_dot "name" (v_dot "body" (v_nth request (v_integer 1)))))
      (a!60 (re.union (re.union (re.union (re.range "a" "z") (re.range "A" "Z"))
                                (re.range "0" "9"))
                      (re.union (re.range " " " ")
                                (re.union (re.range "\x09" "\x09")
                                          (re.range "\n" "\n")))))
      (a!66 (= (v_dot "location" (v_nth request (v_integer 0)))
               (v_string "http://mazes-demo.herokuapp.com/rest/v1/mazes")))
      (a!67 (v_has_field "name" (v_dot "body" (v_nth request (v_integer 0)))))
      (a!68 (v_dot "name" (v_dot "body" (v_nth request (v_integer 0)))))
      (a!69 (forall ((|\|\\\\\\\|#23\\\\\\\|\|| String))
              (let ((a!1 (v_has_field |\|\\\\\\\|#23\\\\\\\|\||
                                      (v_dot "body"
                                             (v_nth request (v_integer 0))))))
                (=> (not (= |\|\\\\\\\|#23\\\\\\\|\|| "name")) (not a!1)))))
      (a!70 (forall ((|\|\\\\\\\|#24\\\\\\\|\|| String))
              (let ((a!1 (not (v_has_field |\|\\\\\\\|#24\\\\\\\|\||
                                           (v_nth request (v_integer 0))))))
                (=> (and (not (= |\|\\\\\\\|#24\\\\\\\|\|| "template"))
                         (not (= |\|\\\\\\\|#24\\\\\\\|\|| "header"))
                         (not (= |\|\\\\\\\|#24\\\\\\\|\|| "location"))
                         (not (= |\|\\\\\\\|#24\\\\\\\|\|| "body")))
                    a!1)))))
(let ((a!30 (and (Good_R (v_nth maze (v_integer 0))) a!29))
      (a!32 (and (Good_R (v_nth maze (v_integer 1))) a!31))
      (a!34 (and (Good_R (v_nth maze (v_integer 2))) a!33))
      (a!42 (v_boolean (and a!39 a!40 (not (Good_R a!41)))))
      (a!55 (O_And (O_EQ (v_length root) (v_integer 3))
                   (O_And (O_And (v_boolean a!52) a!53) (v_boolean a!54))))
      (a!61 (and (In_String a!59)
                 (str.in.re (of_G_String (out_G a!59)) ((_ re.loop 3 3) a!60)))))
(let ((a!35 (O_And (O_EQ (v_length maze) (v_integer 3))
                   (O_And (O_And (v_boolean a!30) (v_boolean a!32))
                          (v_boolean a!34))))
      (a!43 (O_And (O_And (v_boolean (and a!39)) (v_boolean (and a!39)))
                   (v_boolean (and (not a!38) (= a!42 v_tt)))))
      (a!62 (v_boolean (and a!57
                            a!58
                            (In_String a!59)
                            (= (ite a!61 v_tt v_ff) v_tt)))))
(let ((a!44 (O_And (O_And a!43 (v_boolean (and a!39))) (v_boolean (and a!39))))
      (a!63 (O_And (O_And (v_boolean (In_Integer a!41)) a!62)
                   (O_EQ (v_integer 5997) a!41))))
(let ((a!48 (and (Good_E (v_nth request (v_integer 1)))
                 (v_has_field "template" (v_nth request (v_integer 1)))
                 (not a!38)
                 (= a!44 v_tt)
                 (v_has_field "header" (v_nth request (v_integer 1)))
                 a!45
                 (v_has_field "location" (v_nth request (v_integer 1)))
                 a!46
                 (v_has_field "body" (v_nth request (v_integer 1)))
                 (not a!47)))
      (a!64 (O_Or (O_Not (O_EQ a!56 (v_integer 1))) a!63)))
(let ((a!50 (O_And (O_EQ (v_length request) (v_integer 3))
                   (O_And (O_And (v_boolean a!37) (v_boolean a!48))
                          (v_boolean a!49))))
      (a!65 (= (O_And (O_EQ a!56 (v_integer 1)) a!64) v_tt)))
  (and (forall ((v Value)) (! (= (Good_C v) (is-C v)) :pattern ((Good_C v))))
       (forall ((v Value)) (! (= (Good_E v) (is-E v)) :pattern ((Good_E v))))
       (forall ((v Value)) (! (= (Good_R v) (is-R v)) :pattern ((Good_R v))))
       (= v_tt (G (G_Boolean true)))
       (= v_ff (G (G_Boolean false)))
       (= v_null (G G_Null))
       a!1
       a!2
       a!3
       a!4
       a!5
       a!6
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (v_integer (+ (of_G_Integer (out_G v1))
                                     (of_G_Integer (out_G v2))))))
              (= (O_Sum v1 v2) a!1))
            :pattern ((O_Sum v1 v2))))
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (v_integer (- (of_G_Integer (out_G v1))
                                     (of_G_Integer (out_G v2))))))
              (= (O_Sub v1 v2) a!1))
            :pattern ((O_Sub v1 v2))))
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (v_integer (* (of_G_Integer (out_G v1))
                                     (of_G_Integer (out_G v2))))))
              (= (O_Mult v1 v2) a!1))
            :pattern ((O_Mult v1 v2))))
       a!7
       a!8
       a!9
       (forall ((v Value))
         (! (let ((a!1 (v_integer (- (of_G_Integer (out_G v))))))
              (= (O_Minus v) a!1))
            :pattern ((O_Minus v))))
       a!10
       a!11
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (ite (>= (of_G_Integer (out_G v1))
                                (of_G_Integer (out_G v2)))
                            v_tt
                            v_ff)))
              (= (O_GE v1 v2) a!1))
            :pattern ((O_GE v1 v2))))
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (ite (> (of_G_Integer (out_G v1))
                               (of_G_Integer (out_G v2)))
                            v_tt
                            v_ff)))
              (= (O_GT v1 v2) a!1))
            :pattern ((O_GT v1 v2))))
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (ite (< (of_G_Integer (out_G v1))
                               (of_G_Integer (out_G v2)))
                            v_tt
                            v_ff)))
              (= (O_LT v1 v2) a!1))
            :pattern ((O_LT v1 v2))))
       (forall ((v1 Value) (v2 Value))
         (! (let ((a!1 (ite (<= (of_G_Integer (out_G v1))
                                (of_G_Integer (out_G v2)))
                            v_tt
                            v_ff)))
              (= (O_LE v1 v2) a!1))
            :pattern ((O_LE v1 v2))))
       a!12
       a!13
       a!14
       a!15
       a!16
       (forall ((svm (Array String ValueOption))) (= (default svm) NoValue))
       a!17
       a!18
       a!19
       a!20
       (forall ((ivm (Array Int ValueOption))) (= (default ivm) NoValue))
       a!21
       (forall ((v Value))
         (! (let ((a!1 (forall ((i Int))
                         (let ((a!1 (< i (of_G_Integer (out_G (v_length v)))))
                               (a!2 (is-SomeValue (select (alphai (out_C v)) i))))
                           (=> (and (<= 0 i) a!1) a!2)))))
              (= (Good_C v) a!1))
            :pattern ((Good_C v))))
       a!22
       a!23
       a!24
       a!25
       a!26
       a!27
       (Good_C maze)
       a!28
       (= a!35 v_tt)
       (Good_C request)
       a!36
       (= a!50 v_tt)
       (Good_C root)
       a!51
       (= a!55 v_tt)
       a!65
       (Good_C request)
       (= (v_length request) (v_integer 3))
       (v_has_field "template" (v_nth request (v_integer 0)))
       (forall ((|\|\\\\\\\|#21\\\\\\\|\|| String))
         (let ((a!1 (v_has_field |\|\\\\\\\|#21\\\\\\\|\||
                                 (v_dot "template"
                                        (v_nth request (v_integer 0))))))
           (=> true (not a!1))))
       (v_has_field "header" (v_nth request (v_integer 0)))
       (forall ((|\|\\\\\\\|#22\\\\\\\|\|| String))
         (let ((a!1 (v_has_field |\|\\\\\\\|#22\\\\\\\|\||
                                 (v_dot "header" (v_nth request (v_integer 0))))))
           (=> true (not a!1))))
       (v_has_field "location" (v_nth request (v_integer 0)))
       a!66
       (v_has_field "body" (v_nth request (v_integer 0)))
       a!67
       (= a!68 (v_string "p  "))
       a!69
       a!70
       true
       true
       (Good_C root)
       (= (v_length root) (v_integer 3))
       (= (v_nth root (v_integer 0)) (v_string ""))
       true
       true
       (Good_C maze)
       (= (v_length maze) (v_integer 3))
       true
       true
       true))))))))

;(check-sat)
;(get-info :reason-unknown)
;(get-model)

Thanks

facferreira avatar Jul 10 '17 13:07 facferreira

I haven't been able to reproduce this so far. I am using the following script:

from z3 import *
s = Solver()
set_option(verbose=1)
s.set(candidate_models=True)
s.set(fail_if_inconclusive=False)
fmls = parse_smt2_file("slow.smt2")
s.add(fmls)
#s.set("smt.random_seed",11)
print s.check()
print s.statistics()
# print s.model()

The results under random seeds seems stable enough. It finishes within the same time as the command-line. The behavior from Java should be the same (they call into the same underlying functions).

NikolajBjorner avatar Jul 12 '17 08:07 NikolajBjorner

I tried a different example with the command-line as well with python and java, and it seems the random seed has a radical effect on it.

In Java, I ran:

import com.microsoft.z3.*;
import java.util.*;

class Z3Attempt {
  public static void main(String[] args) {
    Context context1 = new Context();
    for (int i = 0; i < 10; i++) {
      BoolExpr assertions =
          context1.parseSMTLIB2File("./exp.smt2", null, null, null, null);
      Solver solver1 = context1.mkSolver();
      Params params = context1.mkParams();
      params.add("candidate_models", true);
      params.add("fail_if_inconclusive", false);
      params.add("smt.random_seed", 11);
      solver1.setParameters(params);
      solver1.add(assertions);
      
      long start = System.currentTimeMillis();
      System.out.println(solver1.check());
      long diff = System.currentTimeMillis() - start;
      //System.out.println(solver1.getModel());
      System.out.println(diff + "ms");
    }
  }
}

This measured the following times:

UNKNOWN
643ms
UNKNOWN
21837ms
UNKNOWN
21076ms
UNKNOWN
22159ms
UNKNOWN
21795ms
UNKNOWN
20571ms
UNKNOWN
21603ms
UNKNOWN
21919ms
UNKNOWN
21250ms
UNKNOWN
21106ms

Basically, only the first check() was successful (the others timed out). If I removed the line that is setting the random seed then every check() times out, so the random seed seems to affect here. Besides that, with the random seed set (to 11), if I moved the line initializing context1 to inside the for loop (just before the line parsing the file) then it takes always ~650ms (no exception). So, with this I have two questions:

  1. Should the random seed make such a difference?
  2. Is it expected that we have to create a new context whenever we need to check() with a given random seed?

In python, I ran:

from z3 import *
s = Solver()
set_option(verbose=1)
s.set(candidate_models=True)
s.set(fail_if_inconclusive=False)
fmls = parse_smt2_file("exp.smt2")
s.add(fmls)
s.set("smt.random_seed", 11)
print s.check()
print s.statistics()
#print s.model()
print ""
print s.check()
print s.statistics()
#print s.model()

And this had the same effect of Java, the first check() produced a response quickly (less than 1s) and the second check() timed out. Also, this outputted the following:

(smt.giveup quantifiers)
unknown
(:added-eqs               19837
 :arith-add-rows          1841
 :arith-assert-lower      396
 :arith-assert-upper      396
 :arith-bound-prop        7
 :arith-conflicts         2
 :arith-eq-adapter        357
 :arith-fixed-eqs         516
 :arith-offset-eqs        187
 :arith-pivots            560
 :array-ext-ax            40
 :array-splits            20
 :binary-propagations     446
 :bv-bit2core             974
 :bv-conflicts            53
 :bv-dynamic-diseqs       939
 :bv-dynamic-eqs          1609
 :bv->core-eq             1609
 :conflicts               99
 :datatype-accessor-ax    514
 :datatype-constructor-ax 506
 :datatype-occurs-check   63918
 :datatype-splits         603
 :decisions               12545
 :del-clause              1906
 :final-checks            977
 :interface-eqs           129
 :max-generation          3
 :max-memory              13.23
 :memory                  4.05
 :minimized-lits          57
 :mk-bool-var             31098
 :mk-clause               2920
 :num-allocs              1093919121
 :propagations            2172
 :quant-instantiations    315
 :rlimit-count            256338
 :seq-add-axiom           6995
 :seq-extensionality      862
 :seq-fixed-length        17
 :seq-length-coherence    41
 :seq-num-reductions      1940
 :seq-unfold-def          3)

(smt.restarting :propagations 1706 :decisions 1880 :conflicts 101 :restart 300 :agility 0.0222865)
(smt.restarting :propagations 3367 :decisions 6342 :conflicts 402 :restart 900 :agility 0.026705)
(smt.restarting :propagations 28084 :decisions 98413 :conflicts 1303 :restart 2700 :agility 0.0208057)
unknown
(:added-eqs               1371594
 :arith-add-rows          853997
 :arith-assert-diseq      63695
 :arith-assert-lower      128060
 :arith-assert-upper      111017
 :arith-bound-prop        46500
 :arith-conflicts         771
 :arith-eq-adapter        12066
 :arith-fixed-eqs         186314
 :arith-offset-eqs        180923
 :arith-pivots            4091
 :array-ext-ax            2124
 :array-splits            2068
 :binary-propagations     168671
 :bv-bit2core             1996
 :bv-conflicts            106
 :bv-dynamic-diseqs       1817
 :bv-dynamic-eqs          166313
 :bv->core-eq             166313
 :conflicts               1983
 :datatype-accessor-ax    17609
 :datatype-constructor-ax 15460
 :datatype-occurs-check   258467
 :datatype-splits         22257
 :decisions               1488032
 :del-clause              36302
 :final-checks            5382
 :interface-eqs           726
 :max-generation          6
 :max-memory              60.54
 :memory                  5.85
 :minimized-lits          86323
 :mk-bool-var             1619263
 :mk-clause               42207
 :num-allocs              11258601299.00
 :propagations            467836
 :quant-instantiations    11809
 :restarts                3
 :rlimit-count            420297591
 :seq-add-axiom           21271
 :seq-extensionality      1672
 :seq-fixed-length        486
 :seq-length-coherence    1581
 :seq-num-reductions      355522
 :seq-unfold-def          5)

Talking about the command-line now, I used the Z3 executable and uncommented the line (set-option :produce-proofs true) of the file (setting the parameter to solver "proof" as true in both python/java made no difference). It produced a response in ~1s and the statistics printed were:

(:added-eqs               39374
 :arith-add-rows          1569
 :arith-assert-diseq      474
 :arith-assert-lower      1216
 :arith-assert-upper      2056
 :arith-bound-prop        49
 :arith-conflicts         11
 :arith-eq-adapter        1307
 :arith-fixed-eqs         1518
 :arith-offset-eqs        736
 :arith-pivots            315
 :array-ext-ax            380
 :array-splits            304
 :bv-bit2core             1247
 :bv-conflicts            57
 :bv-dynamic-diseqs       1089
 :bv-dynamic-eqs          3379
 :bv->core-eq             3379
 :conflicts               191
 :datatype-accessor-ax    1526
 :datatype-constructor-ax 2212
 :datatype-occurs-check   84480
 :datatype-splits         2415
 :decisions               30312
 :del-clause              2879
 :final-checks            1438
 :interface-eqs           130
 :max-generation          3
 :max-memory              33.89
 :memory                  26.30
 :minimized-lits          194
 :mk-bool-var             60775
 :mk-clause               4488
 :num-allocs              1157623350
 :num-checks              1
 :propagations            11671
 :quant-instantiations    743
 :restarts                1
 :rlimit-count            450838
 :seq-add-axiom           8030
 :seq-extensionality      1020
 :seq-fixed-length        78
 :seq-length-coherence    82
 :seq-num-reductions      4930
 :seq-unfold-def          3
 :time                    1.06)

One difference I noticed from these statistics to the ones obtained with python/java is the "binary-propagations", the Z3 executable didn't print that line (I suppose it had value 0?)...

Without setting a random seed to the Z3 executable it responds quickly (and with a candidate model) while python/java need a random seed... Is this expected?

facferreira avatar Jul 16 '17 01:07 facferreira

Here is the file: exp.txt (I had to put it with .txt extension due to github)

facferreira avatar Jul 16 '17 01:07 facferreira

I have a similar problem. For the following SMT input:

(set-option :smt.auto-config false)
(set-option :smt.mbqi true)
(set-option :sat.random_seed 488)
(set-option :smt.random_seed 599)
(set-option :nlsat.seed 611)
(set-option :memory_max_size 6000)
(set-option :produce-proofs true)
(declare-sort T@U 0)
(declare-sort T@T 0)
(declare-fun Ctor (T@T) Int)
(declare-const intType T@T)
(declare-const boolType T@T)
(declare-fun type (T@U) T@T)
(declare-const RefType T@T)
(declare-fun int_2_U (Int) T@U)
(declare-fun bool_2_U (Bool) T@U)
(declare-fun U_2_int (T@U) Int)
(declare-fun MapType1Type (T@T T@T) T@T)
(declare-fun MapType1TypeInv1 (T@T) T@T)
(declare-fun MapType1Select (T@U T@U T@U) T@U)
(declare-fun MapType1Store (T@U T@U T@U T@U) T@U)
(assert (= (Ctor intType) 1))
(assert (= (Ctor boolType) 2))
(assert (forall ((kt0 T@T) (vt0 T@T) ) (! (= (MapType1TypeInv1 (MapType1Type kt0 vt0)) vt0) :pattern ( (MapType1Type kt0 vt0)))))
(assert (forall ((m1 T@U) (k1 T@U) (v1 T@U) ) (! (let ((aVar1 (MapType1TypeInv1 (type m1)))) (= (type (MapType1Select m1 k1 v1)) aVar1)) :pattern ( (MapType1Select m1 k1 v1)))))
(assert (forall ((m2 T@U) (k2 T@U) (x2 T@U) (v2 T@U) ) (! (let ((aVar1@@0 (type v2))) (let ((aVar0@@0 (type k2))) (= (type (MapType1Store m2 k2 x2 v2)) (MapType1Type aVar0@@0 aVar1@@0)))) :pattern ( (MapType1Store m2 k2 x2 v2)))))
(assert (forall ((v3 T@U) (m3 T@U) (k3 T@U) (x3 T@U) (other_k3 T@U) (other_v3 T@U) ) (! (or (= k3 other_k3) (= (MapType1Select (MapType1Store m3 k3 x3 v3) other_k3 other_v3) (MapType1Select m3 other_k3 other_v3))) :pattern ( (MapType1Select (MapType1Store m3 k3 x3 v3) other_k3 other_v3)))))
(assert (forall ((arg4 Int) ) (! (= (type (int_2_U arg4)) intType) :pattern ( (int_2_U arg4)))))
(assert (forall ((arg5 Bool) ) (! (= (type (bool_2_U arg5)) boolType) :pattern ( (bool_2_U arg5)))))
(assert (forall ((arg6 Int) ) (! (= (U_2_int (int_2_U arg6)) arg6) :pattern ( (int_2_U arg6)))))
(check-sat-using smt)
(get-proof)

if I run Z3 from command line, I obtain unsat and a proof immediately. However, with the Java API, the solver times out:

Map<String, String> context_settings = new HashMap<String, String>() {{
				put("auto_config", "false");
				put("proof", "true");
				put("model", "false");
			}};
context = new Context(context_settings);
Tactic tactic = context.andThen(context.mkTactic("solve-eqs"), context.mkTactic("simplify"),
				context.mkTactic("normalize-bounds"), context.mkTactic("propagate-values"), context.mkTactic("smt"));
Solver solver = context.mkSolver(tactic);
Params solver_settings = context.mkParams();
solver_settings.add("auto-config", false);
solver_settings.add("mbqi", true);
solver_settings.add("ematching", false);
solver_settings.add("proof", true);
solver_settings.add("timeout", 600000);
solver_settings.add("max_memory", 6000);
solver_settings.add("smt.random_seed", 599));
solver.setParameters(solver_settings);
solver.add(context.parseSMTLIB2File("input.smt2", null, null, null, null));
Status status = solver.check(); // unknown due to timeout

Is there a way in which I could use the Java API to obtain similar performance with the command line? Thank you very much.

alebugariu avatar Oct 06 '23 17:10 alebugariu

Loading files with parseSMTLIB2File (and similar in the other APIs) is not the same as running the solver on the command-line. IIRC, for example, set-option in the input file is completely ignored when loaded with parseSMTLIB2File. @alebugariu: you set ematching to false in the Java API settings, but not in the .smt2 file. This will obviously have a huge impact on performance.

wintersteiger avatar Oct 29 '23 23:10 wintersteiger