src/HOL/SMT.thy
changeset 58061 3d060f43accb
parent 57704 c0da3fc313e3
child 58072 a86c962de77f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/HOL/SMT.thy	Thu Aug 28 00:40:38 2014 +0200
     1.3 @@ -0,0 +1,379 @@
     1.4 +(*  Title:      HOL/SMT.thy
     1.5 +    Author:     Sascha Boehme, TU Muenchen
     1.6 +*)
     1.7 +
     1.8 +header {* Bindings to Satisfiability Modulo Theories (SMT) solvers based on SMT-LIB 2 *}
     1.9 +
    1.10 +theory SMT
    1.11 +imports Divides
    1.12 +keywords "smt_status" :: diag
    1.13 +begin
    1.14 +
    1.15 +subsection {* Triggers for quantifier instantiation *}
    1.16 +
    1.17 +text {*
    1.18 +Some SMT solvers support patterns as a quantifier instantiation
    1.19 +heuristics. Patterns may either be positive terms (tagged by "pat")
    1.20 +triggering quantifier instantiations -- when the solver finds a
    1.21 +term matching a positive pattern, it instantiates the corresponding
    1.22 +quantifier accordingly -- or negative terms (tagged by "nopat")
    1.23 +inhibiting quantifier instantiations. A list of patterns
    1.24 +of the same kind is called a multipattern, and all patterns in a
    1.25 +multipattern are considered conjunctively for quantifier instantiation.
    1.26 +A list of multipatterns is called a trigger, and their multipatterns
    1.27 +act disjunctively during quantifier instantiation. Each multipattern
    1.28 +should mention at least all quantified variables of the preceding
    1.29 +quantifier block.
    1.30 +*}
    1.31 +
    1.32 +typedecl 'a symb_list
    1.33 +
    1.34 +consts
    1.35 +  Symb_Nil :: "'a symb_list"
    1.36 +  Symb_Cons :: "'a \<Rightarrow> 'a symb_list \<Rightarrow> 'a symb_list"
    1.37 +
    1.38 +typedecl pattern
    1.39 +
    1.40 +consts
    1.41 +  pat :: "'a \<Rightarrow> pattern"
    1.42 +  nopat :: "'a \<Rightarrow> pattern"
    1.43 +
    1.44 +definition trigger :: "pattern symb_list symb_list \<Rightarrow> bool \<Rightarrow> bool" where
    1.45 +  "trigger _ P = P"
    1.46 +
    1.47 +
    1.48 +subsection {* Higher-order encoding *}
    1.49 +
    1.50 +text {*
    1.51 +Application is made explicit for constants occurring with varying
    1.52 +numbers of arguments. This is achieved by the introduction of the
    1.53 +following constant.
    1.54 +*}
    1.55 +
    1.56 +definition fun_app :: "'a \<Rightarrow> 'a" where "fun_app f = f"
    1.57 +
    1.58 +text {*
    1.59 +Some solvers support a theory of arrays which can be used to encode
    1.60 +higher-order functions. The following set of lemmas specifies the
    1.61 +properties of such (extensional) arrays.
    1.62 +*}
    1.63 +
    1.64 +lemmas array_rules = ext fun_upd_apply fun_upd_same fun_upd_other  fun_upd_upd fun_app_def
    1.65 +
    1.66 +
    1.67 +subsection {* Normalization *}
    1.68 +
    1.69 +lemma case_bool_if[abs_def]: "case_bool x y P = (if P then x else y)"
    1.70 +  by simp
    1.71 +
    1.72 +lemmas Ex1_def_raw = Ex1_def[abs_def]
    1.73 +lemmas Ball_def_raw = Ball_def[abs_def]
    1.74 +lemmas Bex_def_raw = Bex_def[abs_def]
    1.75 +lemmas abs_if_raw = abs_if[abs_def]
    1.76 +lemmas min_def_raw = min_def[abs_def]
    1.77 +lemmas max_def_raw = max_def[abs_def]
    1.78 +
    1.79 +
    1.80 +subsection {* Integer division and modulo for Z3 *}
    1.81 +
    1.82 +text {*
    1.83 +The following Z3-inspired definitions are overspecified for the case where @{text "l = 0"}. This
    1.84 +Schönheitsfehler is corrected in the @{text div_as_z3div} and @{text mod_as_z3mod} theorems.
    1.85 +*}
    1.86 +
    1.87 +definition z3div :: "int \<Rightarrow> int \<Rightarrow> int" where
    1.88 +  "z3div k l = (if l \<ge> 0 then k div l else - (k div - l))"
    1.89 +
    1.90 +definition z3mod :: "int \<Rightarrow> int \<Rightarrow> int" where
    1.91 +  "z3mod k l = k mod (if l \<ge> 0 then l else - l)"
    1.92 +
    1.93 +lemma div_as_z3div:
    1.94 +  "\<forall>k l. k div l = (if l = 0 then 0 else if l > 0 then z3div k l else z3div (- k) (- l))"
    1.95 +  by (simp add: z3div_def)
    1.96 +
    1.97 +lemma mod_as_z3mod:
    1.98 +  "\<forall>k l. k mod l = (if l = 0 then k else if l > 0 then z3mod k l else - z3mod (- k) (- l))"
    1.99 +  by (simp add: z3mod_def)
   1.100 +
   1.101 +
   1.102 +subsection {* Setup *}
   1.103 +
   1.104 +ML_file "Tools/SMT/smt_util.ML"
   1.105 +ML_file "Tools/SMT/smt_failure.ML"
   1.106 +ML_file "Tools/SMT/smt_config.ML"
   1.107 +ML_file "Tools/SMT/smt_builtin.ML"
   1.108 +ML_file "Tools/SMT/smt_datatypes.ML"
   1.109 +ML_file "Tools/SMT/smt_normalize.ML"
   1.110 +ML_file "Tools/SMT/smt_translate.ML"
   1.111 +ML_file "Tools/SMT/smtlib.ML"
   1.112 +ML_file "Tools/SMT/smtlib_interface.ML"
   1.113 +ML_file "Tools/SMT/smtlib_proof.ML"
   1.114 +ML_file "Tools/SMT/smtlib_isar.ML"
   1.115 +ML_file "Tools/SMT/z3_proof.ML"
   1.116 +ML_file "Tools/SMT/z3_isar.ML"
   1.117 +ML_file "Tools/SMT/smt_solver.ML"
   1.118 +ML_file "Tools/SMT/z3_interface.ML"
   1.119 +ML_file "Tools/SMT/z3_replay_util.ML"
   1.120 +ML_file "Tools/SMT/z3_replay_literals.ML"
   1.121 +ML_file "Tools/SMT/z3_replay_rules.ML"
   1.122 +ML_file "Tools/SMT/z3_replay_methods.ML"
   1.123 +ML_file "Tools/SMT/z3_replay.ML"
   1.124 +ML_file "Tools/SMT/verit_proof.ML"
   1.125 +ML_file "Tools/SMT/verit_isar.ML"
   1.126 +ML_file "Tools/SMT/verit_proof_parse.ML"
   1.127 +ML_file "Tools/SMT/smt_systems.ML"
   1.128 +
   1.129 +method_setup smt = {*
   1.130 +  Scan.optional Attrib.thms [] >>
   1.131 +    (fn thms => fn ctxt =>
   1.132 +      METHOD (fn facts => HEADGOAL (SMT_Solver.smt_tac ctxt (thms @ facts))))
   1.133 +*} "apply an SMT solver to the current goal (based on SMT-LIB 2)"
   1.134 +
   1.135 +
   1.136 +subsection {* Configuration *}
   1.137 +
   1.138 +text {*
   1.139 +The current configuration can be printed by the command
   1.140 +@{text smt_status}, which shows the values of most options.
   1.141 +*}
   1.142 +
   1.143 +
   1.144 +subsection {* General configuration options *}
   1.145 +
   1.146 +text {*
   1.147 +The option @{text smt_solver} can be used to change the target SMT
   1.148 +solver. The possible values can be obtained from the @{text smt_status}
   1.149 +command.
   1.150 +
   1.151 +Due to licensing restrictions, Z3 is not enabled by default. Z3 is free
   1.152 +for non-commercial applications and can be enabled by setting Isabelle
   1.153 +system option @{text z3_non_commercial} to @{text yes}.
   1.154 +*}
   1.155 +
   1.156 +declare [[smt_solver = z3]]
   1.157 +
   1.158 +text {*
   1.159 +Since SMT solvers are potentially nonterminating, there is a timeout
   1.160 +(given in seconds) to restrict their runtime.
   1.161 +*}
   1.162 +
   1.163 +declare [[smt_timeout = 20]]
   1.164 +
   1.165 +text {*
   1.166 +SMT solvers apply randomized heuristics. In case a problem is not
   1.167 +solvable by an SMT solver, changing the following option might help.
   1.168 +*}
   1.169 +
   1.170 +declare [[smt_random_seed = 1]]
   1.171 +
   1.172 +text {*
   1.173 +In general, the binding to SMT solvers runs as an oracle, i.e, the SMT
   1.174 +solvers are fully trusted without additional checks. The following
   1.175 +option can cause the SMT solver to run in proof-producing mode, giving
   1.176 +a checkable certificate. This is currently only implemented for Z3.
   1.177 +*}
   1.178 +
   1.179 +declare [[smt_oracle = false]]
   1.180 +
   1.181 +text {*
   1.182 +Each SMT solver provides several commandline options to tweak its
   1.183 +behaviour. They can be passed to the solver by setting the following
   1.184 +options.
   1.185 +*}
   1.186 +
   1.187 +declare [[cvc3_options = ""]]
   1.188 +declare [[cvc4_options = ""]]
   1.189 +declare [[veriT_options = ""]]
   1.190 +declare [[z3_options = ""]]
   1.191 +
   1.192 +text {*
   1.193 +The SMT method provides an inference mechanism to detect simple triggers
   1.194 +in quantified formulas, which might increase the number of problems
   1.195 +solvable by SMT solvers (note: triggers guide quantifier instantiations
   1.196 +in the SMT solver). To turn it on, set the following option.
   1.197 +*}
   1.198 +
   1.199 +declare [[smt_infer_triggers = false]]
   1.200 +
   1.201 +text {*
   1.202 +Enable the following option to use built-in support for div/mod, datatypes,
   1.203 +and records in Z3. Currently, this is implemented only in oracle mode.
   1.204 +*}
   1.205 +
   1.206 +declare [[z3_extensions = false]]
   1.207 +
   1.208 +
   1.209 +subsection {* Certificates *}
   1.210 +
   1.211 +text {*
   1.212 +By setting the option @{text smt_certificates} to the name of a file,
   1.213 +all following applications of an SMT solver a cached in that file.
   1.214 +Any further application of the same SMT solver (using the very same
   1.215 +configuration) re-uses the cached certificate instead of invoking the
   1.216 +solver. An empty string disables caching certificates.
   1.217 +
   1.218 +The filename should be given as an explicit path. It is good
   1.219 +practice to use the name of the current theory (with ending
   1.220 +@{text ".certs"} instead of @{text ".thy"}) as the certificates file.
   1.221 +Certificate files should be used at most once in a certain theory context,
   1.222 +to avoid race conditions with other concurrent accesses.
   1.223 +*}
   1.224 +
   1.225 +declare [[smt_certificates = ""]]
   1.226 +
   1.227 +text {*
   1.228 +The option @{text smt_read_only_certificates} controls whether only
   1.229 +stored certificates are should be used or invocation of an SMT solver
   1.230 +is allowed. When set to @{text true}, no SMT solver will ever be
   1.231 +invoked and only the existing certificates found in the configured
   1.232 +cache are used;  when set to @{text false} and there is no cached
   1.233 +certificate for some proposition, then the configured SMT solver is
   1.234 +invoked.
   1.235 +*}
   1.236 +
   1.237 +declare [[smt_read_only_certificates = false]]
   1.238 +
   1.239 +
   1.240 +subsection {* Tracing *}
   1.241 +
   1.242 +text {*
   1.243 +The SMT method, when applied, traces important information. To
   1.244 +make it entirely silent, set the following option to @{text false}.
   1.245 +*}
   1.246 +
   1.247 +declare [[smt_verbose = true]]
   1.248 +
   1.249 +text {*
   1.250 +For tracing the generated problem file given to the SMT solver as
   1.251 +well as the returned result of the solver, the option
   1.252 +@{text smt_trace} should be set to @{text true}.
   1.253 +*}
   1.254 +
   1.255 +declare [[smt_trace = false]]
   1.256 +
   1.257 +
   1.258 +subsection {* Schematic rules for Z3 proof reconstruction *}
   1.259 +
   1.260 +text {*
   1.261 +Several prof rules of Z3 are not very well documented. There are two
   1.262 +lemma groups which can turn failing Z3 proof reconstruction attempts
   1.263 +into succeeding ones: the facts in @{text z3_rule} are tried prior to
   1.264 +any implemented reconstruction procedure for all uncertain Z3 proof
   1.265 +rules;  the facts in @{text z3_simp} are only fed to invocations of
   1.266 +the simplifier when reconstructing theory-specific proof steps.
   1.267 +*}
   1.268 +
   1.269 +lemmas [z3_rule] =
   1.270 +  refl eq_commute conj_commute disj_commute simp_thms nnf_simps
   1.271 +  ring_distribs field_simps times_divide_eq_right times_divide_eq_left
   1.272 +  if_True if_False not_not
   1.273 +
   1.274 +lemma [z3_rule]:
   1.275 +  "(P \<and> Q) = (\<not> (\<not> P \<or> \<not> Q))"
   1.276 +  "(P \<and> Q) = (\<not> (\<not> Q \<or> \<not> P))"
   1.277 +  "(\<not> P \<and> Q) = (\<not> (P \<or> \<not> Q))"
   1.278 +  "(\<not> P \<and> Q) = (\<not> (\<not> Q \<or> P))"
   1.279 +  "(P \<and> \<not> Q) = (\<not> (\<not> P \<or> Q))"
   1.280 +  "(P \<and> \<not> Q) = (\<not> (Q \<or> \<not> P))"
   1.281 +  "(\<not> P \<and> \<not> Q) = (\<not> (P \<or> Q))"
   1.282 +  "(\<not> P \<and> \<not> Q) = (\<not> (Q \<or> P))"
   1.283 +  by auto
   1.284 +
   1.285 +lemma [z3_rule]:
   1.286 +  "(P \<longrightarrow> Q) = (Q \<or> \<not> P)"
   1.287 +  "(\<not> P \<longrightarrow> Q) = (P \<or> Q)"
   1.288 +  "(\<not> P \<longrightarrow> Q) = (Q \<or> P)"
   1.289 +  "(True \<longrightarrow> P) = P"
   1.290 +  "(P \<longrightarrow> True) = True"
   1.291 +  "(False \<longrightarrow> P) = True"
   1.292 +  "(P \<longrightarrow> P) = True"
   1.293 +  by auto
   1.294 +
   1.295 +lemma [z3_rule]:
   1.296 +  "((P = Q) \<longrightarrow> R) = (R | (Q = (\<not> P)))"
   1.297 +  by auto
   1.298 +
   1.299 +lemma [z3_rule]:
   1.300 +  "(\<not> True) = False"
   1.301 +  "(\<not> False) = True"
   1.302 +  "(x = x) = True"
   1.303 +  "(P = True) = P"
   1.304 +  "(True = P) = P"
   1.305 +  "(P = False) = (\<not> P)"
   1.306 +  "(False = P) = (\<not> P)"
   1.307 +  "((\<not> P) = P) = False"
   1.308 +  "(P = (\<not> P)) = False"
   1.309 +  "((\<not> P) = (\<not> Q)) = (P = Q)"
   1.310 +  "\<not> (P = (\<not> Q)) = (P = Q)"
   1.311 +  "\<not> ((\<not> P) = Q) = (P = Q)"
   1.312 +  "(P \<noteq> Q) = (Q = (\<not> P))"
   1.313 +  "(P = Q) = ((\<not> P \<or> Q) \<and> (P \<or> \<not> Q))"
   1.314 +  "(P \<noteq> Q) = ((\<not> P \<or> \<not> Q) \<and> (P \<or> Q))"
   1.315 +  by auto
   1.316 +
   1.317 +lemma [z3_rule]:
   1.318 +  "(if P then P else \<not> P) = True"
   1.319 +  "(if \<not> P then \<not> P else P) = True"
   1.320 +  "(if P then True else False) = P"
   1.321 +  "(if P then False else True) = (\<not> P)"
   1.322 +  "(if P then Q else True) = ((\<not> P) \<or> Q)"
   1.323 +  "(if P then Q else True) = (Q \<or> (\<not> P))"
   1.324 +  "(if P then Q else \<not> Q) = (P = Q)"
   1.325 +  "(if P then Q else \<not> Q) = (Q = P)"
   1.326 +  "(if P then \<not> Q else Q) = (P = (\<not> Q))"
   1.327 +  "(if P then \<not> Q else Q) = ((\<not> Q) = P)"
   1.328 +  "(if \<not> P then x else y) = (if P then y else x)"
   1.329 +  "(if P then (if Q then x else y) else x) = (if P \<and> (\<not> Q) then y else x)"
   1.330 +  "(if P then (if Q then x else y) else x) = (if (\<not> Q) \<and> P then y else x)"
   1.331 +  "(if P then (if Q then x else y) else y) = (if P \<and> Q then x else y)"
   1.332 +  "(if P then (if Q then x else y) else y) = (if Q \<and> P then x else y)"
   1.333 +  "(if P then x else if P then y else z) = (if P then x else z)"
   1.334 +  "(if P then x else if Q then x else y) = (if P \<or> Q then x else y)"
   1.335 +  "(if P then x else if Q then x else y) = (if Q \<or> P then x else y)"
   1.336 +  "(if P then x = y else x = z) = (x = (if P then y else z))"
   1.337 +  "(if P then x = y else y = z) = (y = (if P then x else z))"
   1.338 +  "(if P then x = y else z = y) = (y = (if P then x else z))"
   1.339 +  by auto
   1.340 +
   1.341 +lemma [z3_rule]:
   1.342 +  "0 + (x::int) = x"
   1.343 +  "x + 0 = x"
   1.344 +  "x + x = 2 * x"
   1.345 +  "0 * x = 0"
   1.346 +  "1 * x = x"
   1.347 +  "x + y = y + x"
   1.348 +  by (auto simp add: mult_2)
   1.349 +
   1.350 +lemma [z3_rule]:  (* for def-axiom *)
   1.351 +  "P = Q \<or> P \<or> Q"
   1.352 +  "P = Q \<or> \<not> P \<or> \<not> Q"
   1.353 +  "(\<not> P) = Q \<or> \<not> P \<or> Q"
   1.354 +  "(\<not> P) = Q \<or> P \<or> \<not> Q"
   1.355 +  "P = (\<not> Q) \<or> \<not> P \<or> Q"
   1.356 +  "P = (\<not> Q) \<or> P \<or> \<not> Q"
   1.357 +  "P \<noteq> Q \<or> P \<or> \<not> Q"
   1.358 +  "P \<noteq> Q \<or> \<not> P \<or> Q"
   1.359 +  "P \<noteq> (\<not> Q) \<or> P \<or> Q"
   1.360 +  "(\<not> P) \<noteq> Q \<or> P \<or> Q"
   1.361 +  "P \<or> Q \<or> P \<noteq> (\<not> Q)"
   1.362 +  "P \<or> Q \<or> (\<not> P) \<noteq> Q"
   1.363 +  "P \<or> \<not> Q \<or> P \<noteq> Q"
   1.364 +  "\<not> P \<or> Q \<or> P \<noteq> Q"
   1.365 +  "P \<or> y = (if P then x else y)"
   1.366 +  "P \<or> (if P then x else y) = y"
   1.367 +  "\<not> P \<or> x = (if P then x else y)"
   1.368 +  "\<not> P \<or> (if P then x else y) = x"
   1.369 +  "P \<or> R \<or> \<not> (if P then Q else R)"
   1.370 +  "\<not> P \<or> Q \<or> \<not> (if P then Q else R)"
   1.371 +  "\<not> (if P then Q else R) \<or> \<not> P \<or> Q"
   1.372 +  "\<not> (if P then Q else R) \<or> P \<or> R"
   1.373 +  "(if P then Q else R) \<or> \<not> P \<or> \<not> Q"
   1.374 +  "(if P then Q else R) \<or> P \<or> \<not> R"
   1.375 +  "(if P then \<not> Q else R) \<or> \<not> P \<or> Q"
   1.376 +  "(if P then Q else \<not> R) \<or> P \<or> R"
   1.377 +  by auto
   1.378 +
   1.379 +hide_type (open) symb_list pattern
   1.380 +hide_const (open) Symb_Nil Symb_Cons trigger pat nopat fun_app z3div z3mod
   1.381 +
   1.382 +end