src/HOL/SMT.thy
author boehmes
Mon Nov 22 15:45:42 2010 +0100 (2010-11-22)
changeset 40662 798aad2229c0
parent 40424 7550b2cba1cb
child 40664 e023788a91a1
permissions -rw-r--r--
added prove reconstruction for injective functions;
added SMT_Utils to collect frequently used functions
boehmes@36898
     1
(*  Title:      HOL/SMT.thy
boehmes@36898
     2
    Author:     Sascha Boehme, TU Muenchen
boehmes@36898
     3
*)
boehmes@36898
     4
boehmes@36898
     5
header {* Bindings to Satisfiability Modulo Theories (SMT) solvers *}
boehmes@36898
     6
boehmes@36898
     7
theory SMT
boehmes@36898
     8
imports List
boehmes@36898
     9
uses
boehmes@39483
    10
  "Tools/Datatype/datatype_selectors.ML"
boehmes@40424
    11
  "Tools/SMT/smt_failure.ML"
boehmes@40424
    12
  "Tools/SMT/smt_config.ML"
boehmes@40662
    13
  "Tools/SMT/smt_utils.ML"
boehmes@40424
    14
  "Tools/SMT/smt_monomorph.ML"
boehmes@40277
    15
  ("Tools/SMT/smt_builtin.ML")
boehmes@36898
    16
  ("Tools/SMT/smt_normalize.ML")
boehmes@36898
    17
  ("Tools/SMT/smt_translate.ML")
boehmes@36898
    18
  ("Tools/SMT/smt_solver.ML")
boehmes@36898
    19
  ("Tools/SMT/smtlib_interface.ML")
boehmes@36898
    20
  ("Tools/SMT/z3_proof_parser.ML")
boehmes@36898
    21
  ("Tools/SMT/z3_proof_tools.ML")
boehmes@36898
    22
  ("Tools/SMT/z3_proof_literals.ML")
boehmes@40662
    23
  ("Tools/SMT/z3_proof_methods.ML")
boehmes@36898
    24
  ("Tools/SMT/z3_proof_reconstruction.ML")
boehmes@36898
    25
  ("Tools/SMT/z3_model.ML")
boehmes@36898
    26
  ("Tools/SMT/z3_interface.ML")
boehmes@40162
    27
  ("Tools/SMT/smt_setup_solvers.ML")
boehmes@36898
    28
begin
boehmes@36898
    29
boehmes@36898
    30
boehmes@36898
    31
huffman@36902
    32
subsection {* Triggers for quantifier instantiation *}
boehmes@36898
    33
boehmes@36898
    34
text {*
boehmes@36898
    35
Some SMT solvers support triggers for quantifier instantiation.
boehmes@36898
    36
Each trigger consists of one ore more patterns.  A pattern may either
boehmes@37124
    37
be a list of positive subterms (each being tagged by "pat"), or a
boehmes@37124
    38
list of negative subterms (each being tagged by "nopat").
boehmes@37124
    39
boehmes@37124
    40
When an SMT solver finds a term matching a positive pattern (a
boehmes@37124
    41
pattern with positive subterms only), it instantiates the
boehmes@37124
    42
corresponding quantifier accordingly.  Negative patterns inhibit
boehmes@37124
    43
quantifier instantiations.  Each pattern should mention all preceding
boehmes@37124
    44
bound variables.
boehmes@36898
    45
*}
boehmes@36898
    46
boehmes@36898
    47
datatype pattern = Pattern
boehmes@36898
    48
boehmes@37124
    49
definition pat :: "'a \<Rightarrow> pattern" where "pat _ = Pattern"
boehmes@37124
    50
definition nopat :: "'a \<Rightarrow> pattern" where "nopat _ = Pattern"
boehmes@36898
    51
boehmes@37124
    52
definition trigger :: "pattern list list \<Rightarrow> bool \<Rightarrow> bool"
boehmes@36898
    53
where "trigger _ P = P"
boehmes@36898
    54
boehmes@36898
    55
boehmes@36898
    56
boehmes@40274
    57
subsection {* Distinctness *}
boehmes@40274
    58
boehmes@40274
    59
text {*
boehmes@40274
    60
As an abbreviation for a quadratic number of inequalities, SMT solvers
boehmes@40274
    61
provide a built-in @{text distinct}.  To avoid confusion with the
boehmes@40274
    62
already defined (and more general) @{term List.distinct}, a separate
boehmes@40274
    63
constant is defined.
boehmes@40274
    64
*}
boehmes@40274
    65
boehmes@40274
    66
definition distinct :: "'a list \<Rightarrow> bool"
boehmes@40274
    67
where "distinct xs = List.distinct xs"
boehmes@40274
    68
boehmes@40274
    69
boehmes@40274
    70
huffman@36902
    71
subsection {* Higher-order encoding *}
boehmes@36898
    72
boehmes@36898
    73
text {*
boehmes@36898
    74
Application is made explicit for constants occurring with varying
boehmes@36898
    75
numbers of arguments.  This is achieved by the introduction of the
boehmes@36898
    76
following constant.
boehmes@36898
    77
*}
boehmes@36898
    78
boehmes@37153
    79
definition fun_app where "fun_app f x = f x"
boehmes@36898
    80
boehmes@36898
    81
text {*
boehmes@36898
    82
Some solvers support a theory of arrays which can be used to encode
boehmes@36898
    83
higher-order functions.  The following set of lemmas specifies the
boehmes@36898
    84
properties of such (extensional) arrays.
boehmes@36898
    85
*}
boehmes@36898
    86
boehmes@36898
    87
lemmas array_rules = ext fun_upd_apply fun_upd_same fun_upd_other
boehmes@37157
    88
  fun_upd_upd fun_app_def
boehmes@36898
    89
boehmes@36898
    90
boehmes@36898
    91
huffman@36902
    92
subsection {* First-order logic *}
boehmes@36898
    93
boehmes@36898
    94
text {*
boehmes@36898
    95
Some SMT solvers require a strict separation between formulas and
boehmes@36898
    96
terms.  When translating higher-order into first-order problems,
boehmes@36898
    97
all uninterpreted constants (those not builtin in the target solver)
boehmes@36898
    98
are treated as function symbols in the first-order sense.  Their
boehmes@36898
    99
occurrences as head symbols in atoms (i.e., as predicate symbols) is
boehmes@36898
   100
turned into terms by equating such atoms with @{term True} using the
boehmes@36898
   101
following term-level equation symbol.
boehmes@36898
   102
*}
boehmes@36898
   103
boehmes@37124
   104
definition term_eq :: "bool \<Rightarrow> bool \<Rightarrow> bool" where "term_eq x y = (x = y)"
boehmes@36898
   105
boehmes@36898
   106
boehmes@36898
   107
boehmes@37151
   108
subsection {* Integer division and modulo for Z3 *}
boehmes@37151
   109
boehmes@37151
   110
definition z3div :: "int \<Rightarrow> int \<Rightarrow> int" where
boehmes@37151
   111
  "z3div k l = (if 0 \<le> l then k div l else -(k div (-l)))"
boehmes@37151
   112
boehmes@37151
   113
definition z3mod :: "int \<Rightarrow> int \<Rightarrow> int" where
boehmes@37151
   114
  "z3mod k l = (if 0 \<le> l then k mod l else k mod (-l))"
boehmes@37151
   115
boehmes@37151
   116
lemma div_by_z3div: "k div l = (
boehmes@37151
   117
     if k = 0 \<or> l = 0 then 0
boehmes@37151
   118
     else if (0 < k \<and> 0 < l) \<or> (k < 0 \<and> 0 < l) then z3div k l
boehmes@37151
   119
     else z3div (-k) (-l))"
boehmes@37151
   120
  by (auto simp add: z3div_def)
boehmes@37151
   121
boehmes@37151
   122
lemma mod_by_z3mod: "k mod l = (
boehmes@37151
   123
     if l = 0 then k
boehmes@37151
   124
     else if k = 0 then 0
boehmes@37151
   125
     else if (0 < k \<and> 0 < l) \<or> (k < 0 \<and> 0 < l) then z3mod k l
boehmes@37151
   126
     else - z3mod (-k) (-l))"
boehmes@37151
   127
  by (auto simp add: z3mod_def)
boehmes@37151
   128
boehmes@37151
   129
boehmes@37151
   130
huffman@36902
   131
subsection {* Setup *}
boehmes@36898
   132
boehmes@40277
   133
use "Tools/SMT/smt_builtin.ML"
boehmes@36898
   134
use "Tools/SMT/smt_normalize.ML"
boehmes@36898
   135
use "Tools/SMT/smt_translate.ML"
boehmes@36898
   136
use "Tools/SMT/smt_solver.ML"
boehmes@36898
   137
use "Tools/SMT/smtlib_interface.ML"
boehmes@36898
   138
use "Tools/SMT/z3_interface.ML"
boehmes@36898
   139
use "Tools/SMT/z3_proof_parser.ML"
boehmes@36898
   140
use "Tools/SMT/z3_proof_tools.ML"
boehmes@36898
   141
use "Tools/SMT/z3_proof_literals.ML"
boehmes@40662
   142
use "Tools/SMT/z3_proof_methods.ML"
boehmes@36898
   143
use "Tools/SMT/z3_proof_reconstruction.ML"
boehmes@36898
   144
use "Tools/SMT/z3_model.ML"
boehmes@40162
   145
use "Tools/SMT/smt_setup_solvers.ML"
boehmes@36898
   146
boehmes@36898
   147
setup {*
boehmes@40424
   148
  SMT_Config.setup #>
boehmes@36898
   149
  SMT_Solver.setup #>
boehmes@36898
   150
  Z3_Proof_Reconstruction.setup #>
boehmes@40162
   151
  SMT_Setup_Solvers.setup
boehmes@36898
   152
*}
boehmes@36898
   153
boehmes@36898
   154
boehmes@36898
   155
huffman@36902
   156
subsection {* Configuration *}
boehmes@36898
   157
boehmes@36898
   158
text {*
boehmes@36899
   159
The current configuration can be printed by the command
boehmes@36899
   160
@{text smt_status}, which shows the values of most options.
boehmes@36898
   161
*}
boehmes@36898
   162
boehmes@36898
   163
boehmes@36898
   164
boehmes@36898
   165
subsection {* General configuration options *}
boehmes@36898
   166
boehmes@36898
   167
text {*
boehmes@36898
   168
The option @{text smt_solver} can be used to change the target SMT
boehmes@36898
   169
solver.  The possible values are @{text cvc3}, @{text yices}, and
boehmes@36898
   170
@{text z3}.  It is advisable to locally install the selected solver,
boehmes@36898
   171
although this is not necessary for @{text cvc3} and @{text z3}, which
boehmes@36898
   172
can also be used over an Internet-based service.
boehmes@36898
   173
boehmes@36898
   174
When using local SMT solvers, the path to their binaries should be
boehmes@36898
   175
declared by setting the following environment variables:
boehmes@36898
   176
@{text CVC3_SOLVER}, @{text YICES_SOLVER}, and @{text Z3_SOLVER}.
boehmes@36898
   177
*}
boehmes@36898
   178
boehmes@36898
   179
declare [[ smt_solver = z3 ]]
boehmes@36898
   180
boehmes@36898
   181
text {*
boehmes@36898
   182
Since SMT solvers are potentially non-terminating, there is a timeout
boehmes@36898
   183
(given in seconds) to restrict their runtime.  A value greater than
boehmes@36898
   184
120 (seconds) is in most cases not advisable.
boehmes@36898
   185
*}
boehmes@36898
   186
boehmes@36898
   187
declare [[ smt_timeout = 20 ]]
boehmes@36898
   188
boehmes@40162
   189
text {*
boehmes@40162
   190
In general, the binding to SMT solvers runs as an oracle, i.e, the SMT
boehmes@40162
   191
solvers are fully trusted without additional checks.  The following
boehmes@40162
   192
option can cause the SMT solver to run in proof-producing mode, giving
boehmes@40162
   193
a checkable certificate.  This is currently only implemented for Z3.
boehmes@40162
   194
*}
boehmes@40162
   195
boehmes@40162
   196
declare [[ smt_oracle = false ]]
boehmes@40162
   197
boehmes@40162
   198
text {*
boehmes@40162
   199
Each SMT solver provides several commandline options to tweak its
boehmes@40162
   200
behaviour.  They can be passed to the solver by setting the following
boehmes@40162
   201
options.
boehmes@40162
   202
*}
boehmes@40162
   203
boehmes@40162
   204
declare [[ cvc3_options = "", yices_options = "", z3_options = "" ]]
boehmes@40162
   205
boehmes@40162
   206
text {*
boehmes@40162
   207
Enable the following option to use built-in support for datatypes and
boehmes@40162
   208
records.  Currently, this is only implemented for Z3 running in oracle
boehmes@40162
   209
mode.
boehmes@40162
   210
*}
boehmes@40162
   211
boehmes@40162
   212
declare [[ smt_datatypes = false ]]
boehmes@40162
   213
boehmes@36898
   214
boehmes@36898
   215
boehmes@36898
   216
subsection {* Certificates *}
boehmes@36898
   217
boehmes@36898
   218
text {*
boehmes@36898
   219
By setting the option @{text smt_certificates} to the name of a file,
boehmes@36898
   220
all following applications of an SMT solver a cached in that file.
boehmes@36898
   221
Any further application of the same SMT solver (using the very same
boehmes@36898
   222
configuration) re-uses the cached certificate instead of invoking the
boehmes@36898
   223
solver.  An empty string disables caching certificates.
boehmes@36898
   224
boehmes@36898
   225
The filename should be given as an explicit path.  It is good
boehmes@36898
   226
practice to use the name of the current theory (with ending
boehmes@36898
   227
@{text ".certs"} instead of @{text ".thy"}) as the certificates file.
boehmes@36898
   228
*}
boehmes@36898
   229
boehmes@36898
   230
declare [[ smt_certificates = "" ]]
boehmes@36898
   231
boehmes@36898
   232
text {*
boehmes@36898
   233
The option @{text smt_fixed} controls whether only stored
boehmes@36898
   234
certificates are should be used or invocation of an SMT solver is
boehmes@36898
   235
allowed.  When set to @{text true}, no SMT solver will ever be
boehmes@36898
   236
invoked and only the existing certificates found in the configured
boehmes@36898
   237
cache are used;  when set to @{text false} and there is no cached
boehmes@36898
   238
certificate for some proposition, then the configured SMT solver is
boehmes@36898
   239
invoked.
boehmes@36898
   240
*}
boehmes@36898
   241
boehmes@36898
   242
declare [[ smt_fixed = false ]]
boehmes@36898
   243
boehmes@36898
   244
boehmes@36898
   245
boehmes@36898
   246
subsection {* Tracing *}
boehmes@36898
   247
boehmes@36898
   248
text {*
boehmes@40424
   249
The SMT method, when applied, traces important information.  To
boehmes@40424
   250
make it entirely silent, set the following option to @{text false}.
boehmes@40424
   251
*}
boehmes@40424
   252
boehmes@40424
   253
declare [[ smt_verbose = true ]]
boehmes@40424
   254
boehmes@40424
   255
text {*
boehmes@36898
   256
For tracing the generated problem file given to the SMT solver as
boehmes@36898
   257
well as the returned result of the solver, the option
boehmes@36898
   258
@{text smt_trace} should be set to @{text true}.
boehmes@36898
   259
*}
boehmes@36898
   260
boehmes@36898
   261
declare [[ smt_trace = false ]]
boehmes@36898
   262
boehmes@36898
   263
text {*
boehmes@40162
   264
From the set of assumptions given to the SMT solver, those assumptions
boehmes@40162
   265
used in the proof are traced when the following option is set to
boehmes@40162
   266
@{term true}.  This only works for Z3 when it runs in non-oracle mode
boehmes@40162
   267
(see options @{text smt_solver} and @{text smt_oracle} above).
boehmes@36898
   268
*}
boehmes@36898
   269
boehmes@40162
   270
declare [[ smt_trace_used_facts = false ]]
boehmes@39298
   271
boehmes@36898
   272
boehmes@36898
   273
huffman@36902
   274
subsection {* Schematic rules for Z3 proof reconstruction *}
boehmes@36898
   275
boehmes@36898
   276
text {*
boehmes@36898
   277
Several prof rules of Z3 are not very well documented.  There are two
boehmes@36898
   278
lemma groups which can turn failing Z3 proof reconstruction attempts
boehmes@36898
   279
into succeeding ones: the facts in @{text z3_rule} are tried prior to
boehmes@36898
   280
any implemented reconstruction procedure for all uncertain Z3 proof
boehmes@36898
   281
rules;  the facts in @{text z3_simp} are only fed to invocations of
boehmes@36898
   282
the simplifier when reconstructing theory-specific proof steps.
boehmes@36898
   283
*}
boehmes@36898
   284
boehmes@36898
   285
lemmas [z3_rule] =
boehmes@36898
   286
  refl eq_commute conj_commute disj_commute simp_thms nnf_simps
boehmes@36898
   287
  ring_distribs field_simps times_divide_eq_right times_divide_eq_left
boehmes@36898
   288
  if_True if_False not_not
boehmes@36898
   289
boehmes@36898
   290
lemma [z3_rule]:
boehmes@36898
   291
  "(P \<longrightarrow> Q) = (Q \<or> \<not>P)"
boehmes@36898
   292
  "(\<not>P \<longrightarrow> Q) = (P \<or> Q)"
boehmes@36898
   293
  "(\<not>P \<longrightarrow> Q) = (Q \<or> P)"
boehmes@36898
   294
  by auto
boehmes@36898
   295
boehmes@36898
   296
lemma [z3_rule]:
boehmes@36898
   297
  "((P = Q) \<longrightarrow> R) = (R | (Q = (\<not>P)))"
boehmes@36898
   298
  by auto
boehmes@36898
   299
boehmes@36898
   300
lemma [z3_rule]:
boehmes@36898
   301
  "((\<not>P) = P) = False"
boehmes@36898
   302
  "(P = (\<not>P)) = False"
boehmes@36898
   303
  "(P \<noteq> Q) = (Q = (\<not>P))"
boehmes@36898
   304
  "(P = Q) = ((\<not>P \<or> Q) \<and> (P \<or> \<not>Q))"
boehmes@36898
   305
  "(P \<noteq> Q) = ((\<not>P \<or> \<not>Q) \<and> (P \<or> Q))"
boehmes@36898
   306
  by auto
boehmes@36898
   307
boehmes@36898
   308
lemma [z3_rule]:
boehmes@36898
   309
  "(if P then P else \<not>P) = True"
boehmes@36898
   310
  "(if \<not>P then \<not>P else P) = True"
boehmes@36898
   311
  "(if P then True else False) = P"
boehmes@36898
   312
  "(if P then False else True) = (\<not>P)"
boehmes@36898
   313
  "(if \<not>P then x else y) = (if P then y else x)"
boehmes@36898
   314
  by auto
boehmes@36898
   315
boehmes@36898
   316
lemma [z3_rule]:
boehmes@36898
   317
  "P = Q \<or> P \<or> Q"
boehmes@36898
   318
  "P = Q \<or> \<not>P \<or> \<not>Q"
boehmes@36898
   319
  "(\<not>P) = Q \<or> \<not>P \<or> Q"
boehmes@36898
   320
  "(\<not>P) = Q \<or> P \<or> \<not>Q"
boehmes@36898
   321
  "P = (\<not>Q) \<or> \<not>P \<or> Q"
boehmes@36898
   322
  "P = (\<not>Q) \<or> P \<or> \<not>Q"
boehmes@36898
   323
  "P \<noteq> Q \<or> P \<or> \<not>Q"
boehmes@36898
   324
  "P \<noteq> Q \<or> \<not>P \<or> Q"
boehmes@36898
   325
  "P \<noteq> (\<not>Q) \<or> P \<or> Q"
boehmes@36898
   326
  "(\<not>P) \<noteq> Q \<or> P \<or> Q"
boehmes@36898
   327
  "P \<or> Q \<or> P \<noteq> (\<not>Q)"
boehmes@36898
   328
  "P \<or> Q \<or> (\<not>P) \<noteq> Q"
boehmes@36898
   329
  "P \<or> \<not>Q \<or> P \<noteq> Q"
boehmes@36898
   330
  "\<not>P \<or> Q \<or> P \<noteq> Q"
boehmes@36898
   331
  by auto
boehmes@36898
   332
boehmes@36898
   333
lemma [z3_rule]:
boehmes@36898
   334
  "0 + (x::int) = x"
boehmes@36898
   335
  "x + 0 = x"
boehmes@36898
   336
  "0 * x = 0"
boehmes@36898
   337
  "1 * x = x"
boehmes@36898
   338
  "x + y = y + x"
boehmes@36898
   339
  by auto
boehmes@36898
   340
boehmes@37124
   341
boehmes@37124
   342
boehmes@37124
   343
hide_type (open) pattern
boehmes@37153
   344
hide_const Pattern term_eq
boehmes@40274
   345
hide_const (open) trigger pat nopat distinct fun_app z3div z3mod
boehmes@37124
   346
boehmes@39483
   347
boehmes@39483
   348
boehmes@39483
   349
subsection {* Selectors for datatypes *}
boehmes@39483
   350
boehmes@39483
   351
setup {* Datatype_Selectors.setup *}
boehmes@39483
   352
boehmes@39483
   353
declare [[ selector Pair 1 = fst, selector Pair 2 = snd ]]
boehmes@39483
   354
declare [[ selector Cons 1 = hd, selector Cons 2 = tl ]]
boehmes@39483
   355
boehmes@36898
   356
end