src/HOL/SMT.thy
author blanchet
Thu Aug 03 23:43:17 2017 +0200 (22 months ago)
changeset 66323 c41642bc1ebb
parent 66298 5ff9fe3fee66
child 66551 4df6b0ae900d
permissions -rw-r--r--
pass option recommended by Andy Reynolds to CVC4 1.5 (released) or better
     1 (*  Title:      HOL/SMT.thy
     2     Author:     Sascha Boehme, TU Muenchen
     3 *)
     4 
     5 section \<open>Bindings to Satisfiability Modulo Theories (SMT) solvers based on SMT-LIB 2\<close>
     6 
     7 theory SMT
     8 imports Divides
     9 keywords "smt_status" :: diag
    10 begin
    11 
    12 subsection \<open>A skolemization tactic and proof method\<close>
    13 
    14 lemma choices:
    15   "\<And>Q. \<forall>x. \<exists>y ya. Q x y ya \<Longrightarrow> \<exists>f fa. \<forall>x. Q x (f x) (fa x)"
    16   "\<And>Q. \<forall>x. \<exists>y ya yb. Q x y ya yb \<Longrightarrow> \<exists>f fa fb. \<forall>x. Q x (f x) (fa x) (fb x)"
    17   "\<And>Q. \<forall>x. \<exists>y ya yb yc. Q x y ya yb yc \<Longrightarrow> \<exists>f fa fb fc. \<forall>x. Q x (f x) (fa x) (fb x) (fc x)"
    18   "\<And>Q. \<forall>x. \<exists>y ya yb yc yd. Q x y ya yb yc yd \<Longrightarrow>
    19      \<exists>f fa fb fc fd. \<forall>x. Q x (f x) (fa x) (fb x) (fc x) (fd x)"
    20   "\<And>Q. \<forall>x. \<exists>y ya yb yc yd ye. Q x y ya yb yc yd ye \<Longrightarrow>
    21      \<exists>f fa fb fc fd fe. \<forall>x. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x)"
    22   "\<And>Q. \<forall>x. \<exists>y ya yb yc yd ye yf. Q x y ya yb yc yd ye yf \<Longrightarrow>
    23      \<exists>f fa fb fc fd fe ff. \<forall>x. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x) (ff x)"
    24   "\<And>Q. \<forall>x. \<exists>y ya yb yc yd ye yf yg. Q x y ya yb yc yd ye yf yg \<Longrightarrow>
    25      \<exists>f fa fb fc fd fe ff fg. \<forall>x. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x) (ff x) (fg x)"
    26   by metis+
    27 
    28 lemma bchoices:
    29   "\<And>Q. \<forall>x \<in> S. \<exists>y ya. Q x y ya \<Longrightarrow> \<exists>f fa. \<forall>x \<in> S. Q x (f x) (fa x)"
    30   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb. Q x y ya yb \<Longrightarrow> \<exists>f fa fb. \<forall>x \<in> S. Q x (f x) (fa x) (fb x)"
    31   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb yc. Q x y ya yb yc \<Longrightarrow> \<exists>f fa fb fc. \<forall>x \<in> S. Q x (f x) (fa x) (fb x) (fc x)"
    32   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb yc yd. Q x y ya yb yc yd \<Longrightarrow>
    33     \<exists>f fa fb fc fd. \<forall>x \<in> S. Q x (f x) (fa x) (fb x) (fc x) (fd x)"
    34   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb yc yd ye. Q x y ya yb yc yd ye \<Longrightarrow>
    35     \<exists>f fa fb fc fd fe. \<forall>x \<in> S. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x)"
    36   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb yc yd ye yf. Q x y ya yb yc yd ye yf \<Longrightarrow>
    37     \<exists>f fa fb fc fd fe ff. \<forall>x \<in> S. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x) (ff x)"
    38   "\<And>Q. \<forall>x \<in> S. \<exists>y ya yb yc yd ye yf yg. Q x y ya yb yc yd ye yf yg \<Longrightarrow>
    39     \<exists>f fa fb fc fd fe ff fg. \<forall>x \<in> S. Q x (f x) (fa x) (fb x) (fc x) (fd x) (fe x) (ff x) (fg x)"
    40   by metis+
    41 
    42 ML \<open>
    43 fun moura_tac ctxt =
    44   Atomize_Elim.atomize_elim_tac ctxt THEN'
    45   SELECT_GOAL (Clasimp.auto_tac (ctxt addSIs @{thms choice choices bchoice bchoices}) THEN
    46     ALLGOALS (Metis_Tactic.metis_tac (take 1 ATP_Proof_Reconstruct.partial_type_encs)
    47         ATP_Proof_Reconstruct.default_metis_lam_trans ctxt [] ORELSE'
    48       blast_tac ctxt))
    49 \<close>
    50 
    51 method_setup moura = \<open>
    52   Scan.succeed (SIMPLE_METHOD' o moura_tac)
    53 \<close> "solve skolemization goals, especially those arising from Z3 proofs"
    54 
    55 hide_fact (open) choices bchoices
    56 
    57 
    58 subsection \<open>Triggers for quantifier instantiation\<close>
    59 
    60 text \<open>
    61 Some SMT solvers support patterns as a quantifier instantiation
    62 heuristics. Patterns may either be positive terms (tagged by "pat")
    63 triggering quantifier instantiations -- when the solver finds a
    64 term matching a positive pattern, it instantiates the corresponding
    65 quantifier accordingly -- or negative terms (tagged by "nopat")
    66 inhibiting quantifier instantiations. A list of patterns
    67 of the same kind is called a multipattern, and all patterns in a
    68 multipattern are considered conjunctively for quantifier instantiation.
    69 A list of multipatterns is called a trigger, and their multipatterns
    70 act disjunctively during quantifier instantiation. Each multipattern
    71 should mention at least all quantified variables of the preceding
    72 quantifier block.
    73 \<close>
    74 
    75 typedecl 'a symb_list
    76 
    77 consts
    78   Symb_Nil :: "'a symb_list"
    79   Symb_Cons :: "'a \<Rightarrow> 'a symb_list \<Rightarrow> 'a symb_list"
    80 
    81 typedecl pattern
    82 
    83 consts
    84   pat :: "'a \<Rightarrow> pattern"
    85   nopat :: "'a \<Rightarrow> pattern"
    86 
    87 definition trigger :: "pattern symb_list symb_list \<Rightarrow> bool \<Rightarrow> bool" where
    88   "trigger _ P = P"
    89 
    90 
    91 subsection \<open>Higher-order encoding\<close>
    92 
    93 text \<open>
    94 Application is made explicit for constants occurring with varying
    95 numbers of arguments. This is achieved by the introduction of the
    96 following constant.
    97 \<close>
    98 
    99 definition fun_app :: "'a \<Rightarrow> 'a" where "fun_app f = f"
   100 
   101 text \<open>
   102 Some solvers support a theory of arrays which can be used to encode
   103 higher-order functions. The following set of lemmas specifies the
   104 properties of such (extensional) arrays.
   105 \<close>
   106 
   107 lemmas array_rules = ext fun_upd_apply fun_upd_same fun_upd_other  fun_upd_upd fun_app_def
   108 
   109 
   110 subsection \<open>Normalization\<close>
   111 
   112 lemma case_bool_if[abs_def]: "case_bool x y P = (if P then x else y)"
   113   by simp
   114 
   115 lemmas Ex1_def_raw = Ex1_def[abs_def]
   116 lemmas Ball_def_raw = Ball_def[abs_def]
   117 lemmas Bex_def_raw = Bex_def[abs_def]
   118 lemmas abs_if_raw = abs_if[abs_def]
   119 lemmas min_def_raw = min_def[abs_def]
   120 lemmas max_def_raw = max_def[abs_def]
   121 
   122 lemma nat_int': "\<forall>n. nat (int n) = n" by simp
   123 lemma int_nat_nneg: "\<forall>i. i \<ge> 0 \<longrightarrow> int (nat i) = i" by simp
   124 lemma int_nat_neg: "\<forall>i. i < 0 \<longrightarrow> int (nat i) = 0" by simp
   125 
   126 lemmas nat_zero_as_int = transfer_nat_int_numerals(1)
   127 lemmas nat_one_as_int = transfer_nat_int_numerals(2)
   128 lemma nat_numeral_as_int: "numeral = (\<lambda>i. nat (numeral i))" by simp
   129 lemma nat_less_as_int: "op < = (\<lambda>a b. int a < int b)" by simp
   130 lemma nat_leq_as_int: "op \<le> = (\<lambda>a b. int a \<le> int b)" by simp
   131 lemma Suc_as_int: "Suc = (\<lambda>a. nat (int a + 1))" by (rule ext) simp
   132 lemma nat_plus_as_int: "op + = (\<lambda>a b. nat (int a + int b))" by (rule ext)+ simp
   133 lemma nat_minus_as_int: "op - = (\<lambda>a b. nat (int a - int b))" by (rule ext)+ simp
   134 lemma nat_times_as_int: "op * = (\<lambda>a b. nat (int a * int b))" by (simp add: nat_mult_distrib)
   135 lemma nat_div_as_int: "op div = (\<lambda>a b. nat (int a div int b))" by (simp add: nat_div_distrib)
   136 lemma nat_mod_as_int: "op mod = (\<lambda>a b. nat (int a mod int b))" by (simp add: nat_mod_distrib)
   137 
   138 lemma int_Suc: "int (Suc n) = int n + 1" by simp
   139 lemma int_plus: "int (n + m) = int n + int m" by (rule of_nat_add)
   140 lemma int_minus: "int (n - m) = int (nat (int n - int m))" by auto
   141 
   142 
   143 subsection \<open>Integer division and modulo for Z3\<close>
   144 
   145 text \<open>
   146 The following Z3-inspired definitions are overspecified for the case where \<open>l = 0\<close>. This
   147 Schönheitsfehler is corrected in the \<open>div_as_z3div\<close> and \<open>mod_as_z3mod\<close> theorems.
   148 \<close>
   149 
   150 definition z3div :: "int \<Rightarrow> int \<Rightarrow> int" where
   151   "z3div k l = (if l \<ge> 0 then k div l else - (k div - l))"
   152 
   153 definition z3mod :: "int \<Rightarrow> int \<Rightarrow> int" where
   154   "z3mod k l = k mod (if l \<ge> 0 then l else - l)"
   155 
   156 lemma div_as_z3div:
   157   "\<forall>k l. k div l = (if l = 0 then 0 else if l > 0 then z3div k l else z3div (- k) (- l))"
   158   by (simp add: z3div_def)
   159 
   160 lemma mod_as_z3mod:
   161   "\<forall>k l. k mod l = (if l = 0 then k else if l > 0 then z3mod k l else - z3mod (- k) (- l))"
   162   by (simp add: z3mod_def)
   163 
   164 
   165 subsection \<open>Setup\<close>
   166 
   167 ML_file "Tools/SMT/smt_util.ML"
   168 ML_file "Tools/SMT/smt_failure.ML"
   169 ML_file "Tools/SMT/smt_config.ML"
   170 ML_file "Tools/SMT/smt_builtin.ML"
   171 ML_file "Tools/SMT/smt_datatypes.ML"
   172 ML_file "Tools/SMT/smt_normalize.ML"
   173 ML_file "Tools/SMT/smt_translate.ML"
   174 ML_file "Tools/SMT/smtlib.ML"
   175 ML_file "Tools/SMT/smtlib_interface.ML"
   176 ML_file "Tools/SMT/smtlib_proof.ML"
   177 ML_file "Tools/SMT/smtlib_isar.ML"
   178 ML_file "Tools/SMT/z3_proof.ML"
   179 ML_file "Tools/SMT/z3_isar.ML"
   180 ML_file "Tools/SMT/smt_solver.ML"
   181 ML_file "Tools/SMT/cvc4_interface.ML"
   182 ML_file "Tools/SMT/cvc4_proof_parse.ML"
   183 ML_file "Tools/SMT/verit_proof.ML"
   184 ML_file "Tools/SMT/verit_isar.ML"
   185 ML_file "Tools/SMT/verit_proof_parse.ML"
   186 ML_file "Tools/SMT/conj_disj_perm.ML"
   187 ML_file "Tools/SMT/z3_interface.ML"
   188 ML_file "Tools/SMT/z3_replay_util.ML"
   189 ML_file "Tools/SMT/z3_replay_rules.ML"
   190 ML_file "Tools/SMT/z3_replay_methods.ML"
   191 ML_file "Tools/SMT/z3_replay.ML"
   192 ML_file "Tools/SMT/smt_systems.ML"
   193 
   194 method_setup smt = \<open>
   195   Scan.optional Attrib.thms [] >>
   196     (fn thms => fn ctxt =>
   197       METHOD (fn facts => HEADGOAL (SMT_Solver.smt_tac ctxt (thms @ facts))))
   198 \<close> "apply an SMT solver to the current goal"
   199 
   200 
   201 subsection \<open>Configuration\<close>
   202 
   203 text \<open>
   204 The current configuration can be printed by the command
   205 \<open>smt_status\<close>, which shows the values of most options.
   206 \<close>
   207 
   208 
   209 subsection \<open>General configuration options\<close>
   210 
   211 text \<open>
   212 The option \<open>smt_solver\<close> can be used to change the target SMT
   213 solver. The possible values can be obtained from the \<open>smt_status\<close>
   214 command.
   215 \<close>
   216 
   217 declare [[smt_solver = z3]]
   218 
   219 text \<open>
   220 Since SMT solvers are potentially nonterminating, there is a timeout
   221 (given in seconds) to restrict their runtime.
   222 \<close>
   223 
   224 declare [[smt_timeout = 20]]
   225 
   226 text \<open>
   227 SMT solvers apply randomized heuristics. In case a problem is not
   228 solvable by an SMT solver, changing the following option might help.
   229 \<close>
   230 
   231 declare [[smt_random_seed = 1]]
   232 
   233 text \<open>
   234 In general, the binding to SMT solvers runs as an oracle, i.e, the SMT
   235 solvers are fully trusted without additional checks. The following
   236 option can cause the SMT solver to run in proof-producing mode, giving
   237 a checkable certificate. This is currently only implemented for Z3.
   238 \<close>
   239 
   240 declare [[smt_oracle = false]]
   241 
   242 text \<open>
   243 Each SMT solver provides several commandline options to tweak its
   244 behaviour. They can be passed to the solver by setting the following
   245 options.
   246 \<close>
   247 
   248 declare [[cvc3_options = ""]]
   249 declare [[cvc4_options = "--full-saturate-quant --inst-when=full-last-call --inst-no-entail --term-db-mode=relevant --multi-trigger-linear"]]
   250 declare [[verit_options = ""]]
   251 declare [[z3_options = ""]]
   252 
   253 text \<open>
   254 The SMT method provides an inference mechanism to detect simple triggers
   255 in quantified formulas, which might increase the number of problems
   256 solvable by SMT solvers (note: triggers guide quantifier instantiations
   257 in the SMT solver). To turn it on, set the following option.
   258 \<close>
   259 
   260 declare [[smt_infer_triggers = false]]
   261 
   262 text \<open>
   263 Enable the following option to use built-in support for datatypes,
   264 codatatypes, and records in CVC4. Currently, this is implemented only
   265 in oracle mode.
   266 \<close>
   267 
   268 declare [[cvc4_extensions = false]]
   269 
   270 text \<open>
   271 Enable the following option to use built-in support for div/mod, datatypes,
   272 and records in Z3. Currently, this is implemented only in oracle mode.
   273 \<close>
   274 
   275 declare [[z3_extensions = false]]
   276 
   277 
   278 subsection \<open>Certificates\<close>
   279 
   280 text \<open>
   281 By setting the option \<open>smt_certificates\<close> to the name of a file,
   282 all following applications of an SMT solver a cached in that file.
   283 Any further application of the same SMT solver (using the very same
   284 configuration) re-uses the cached certificate instead of invoking the
   285 solver. An empty string disables caching certificates.
   286 
   287 The filename should be given as an explicit path. It is good
   288 practice to use the name of the current theory (with ending
   289 \<open>.certs\<close> instead of \<open>.thy\<close>) as the certificates file.
   290 Certificate files should be used at most once in a certain theory context,
   291 to avoid race conditions with other concurrent accesses.
   292 \<close>
   293 
   294 declare [[smt_certificates = ""]]
   295 
   296 text \<open>
   297 The option \<open>smt_read_only_certificates\<close> controls whether only
   298 stored certificates are should be used or invocation of an SMT solver
   299 is allowed. When set to \<open>true\<close>, no SMT solver will ever be
   300 invoked and only the existing certificates found in the configured
   301 cache are used;  when set to \<open>false\<close> and there is no cached
   302 certificate for some proposition, then the configured SMT solver is
   303 invoked.
   304 \<close>
   305 
   306 declare [[smt_read_only_certificates = false]]
   307 
   308 
   309 subsection \<open>Tracing\<close>
   310 
   311 text \<open>
   312 The SMT method, when applied, traces important information. To
   313 make it entirely silent, set the following option to \<open>false\<close>.
   314 \<close>
   315 
   316 declare [[smt_verbose = true]]
   317 
   318 text \<open>
   319 For tracing the generated problem file given to the SMT solver as
   320 well as the returned result of the solver, the option
   321 \<open>smt_trace\<close> should be set to \<open>true\<close>.
   322 \<close>
   323 
   324 declare [[smt_trace = false]]
   325 
   326 
   327 subsection \<open>Schematic rules for Z3 proof reconstruction\<close>
   328 
   329 text \<open>
   330 Several prof rules of Z3 are not very well documented. There are two
   331 lemma groups which can turn failing Z3 proof reconstruction attempts
   332 into succeeding ones: the facts in \<open>z3_rule\<close> are tried prior to
   333 any implemented reconstruction procedure for all uncertain Z3 proof
   334 rules;  the facts in \<open>z3_simp\<close> are only fed to invocations of
   335 the simplifier when reconstructing theory-specific proof steps.
   336 \<close>
   337 
   338 lemmas [z3_rule] =
   339   refl eq_commute conj_commute disj_commute simp_thms nnf_simps
   340   ring_distribs field_simps times_divide_eq_right times_divide_eq_left
   341   if_True if_False not_not
   342   NO_MATCH_def
   343 
   344 lemma [z3_rule]:
   345   "(P \<and> Q) = (\<not> (\<not> P \<or> \<not> Q))"
   346   "(P \<and> Q) = (\<not> (\<not> Q \<or> \<not> P))"
   347   "(\<not> P \<and> Q) = (\<not> (P \<or> \<not> Q))"
   348   "(\<not> P \<and> Q) = (\<not> (\<not> Q \<or> P))"
   349   "(P \<and> \<not> Q) = (\<not> (\<not> P \<or> Q))"
   350   "(P \<and> \<not> Q) = (\<not> (Q \<or> \<not> P))"
   351   "(\<not> P \<and> \<not> Q) = (\<not> (P \<or> Q))"
   352   "(\<not> P \<and> \<not> Q) = (\<not> (Q \<or> P))"
   353   by auto
   354 
   355 lemma [z3_rule]:
   356   "(P \<longrightarrow> Q) = (Q \<or> \<not> P)"
   357   "(\<not> P \<longrightarrow> Q) = (P \<or> Q)"
   358   "(\<not> P \<longrightarrow> Q) = (Q \<or> P)"
   359   "(True \<longrightarrow> P) = P"
   360   "(P \<longrightarrow> True) = True"
   361   "(False \<longrightarrow> P) = True"
   362   "(P \<longrightarrow> P) = True"
   363   "(\<not> (A \<longleftrightarrow> \<not> B)) \<longleftrightarrow> (A \<longleftrightarrow> B)"
   364   by auto
   365 
   366 lemma [z3_rule]:
   367   "((P = Q) \<longrightarrow> R) = (R | (Q = (\<not> P)))"
   368   by auto
   369 
   370 lemma [z3_rule]:
   371   "(\<not> True) = False"
   372   "(\<not> False) = True"
   373   "(x = x) = True"
   374   "(P = True) = P"
   375   "(True = P) = P"
   376   "(P = False) = (\<not> P)"
   377   "(False = P) = (\<not> P)"
   378   "((\<not> P) = P) = False"
   379   "(P = (\<not> P)) = False"
   380   "((\<not> P) = (\<not> Q)) = (P = Q)"
   381   "\<not> (P = (\<not> Q)) = (P = Q)"
   382   "\<not> ((\<not> P) = Q) = (P = Q)"
   383   "(P \<noteq> Q) = (Q = (\<not> P))"
   384   "(P = Q) = ((\<not> P \<or> Q) \<and> (P \<or> \<not> Q))"
   385   "(P \<noteq> Q) = ((\<not> P \<or> \<not> Q) \<and> (P \<or> Q))"
   386   by auto
   387 
   388 lemma [z3_rule]:
   389   "(if P then P else \<not> P) = True"
   390   "(if \<not> P then \<not> P else P) = True"
   391   "(if P then True else False) = P"
   392   "(if P then False else True) = (\<not> P)"
   393   "(if P then Q else True) = ((\<not> P) \<or> Q)"
   394   "(if P then Q else True) = (Q \<or> (\<not> P))"
   395   "(if P then Q else \<not> Q) = (P = Q)"
   396   "(if P then Q else \<not> Q) = (Q = P)"
   397   "(if P then \<not> Q else Q) = (P = (\<not> Q))"
   398   "(if P then \<not> Q else Q) = ((\<not> Q) = P)"
   399   "(if \<not> P then x else y) = (if P then y else x)"
   400   "(if P then (if Q then x else y) else x) = (if P \<and> (\<not> Q) then y else x)"
   401   "(if P then (if Q then x else y) else x) = (if (\<not> Q) \<and> P then y else x)"
   402   "(if P then (if Q then x else y) else y) = (if P \<and> Q then x else y)"
   403   "(if P then (if Q then x else y) else y) = (if Q \<and> P then x else y)"
   404   "(if P then x else if P then y else z) = (if P then x else z)"
   405   "(if P then x else if Q then x else y) = (if P \<or> Q then x else y)"
   406   "(if P then x else if Q then x else y) = (if Q \<or> P then x else y)"
   407   "(if P then x = y else x = z) = (x = (if P then y else z))"
   408   "(if P then x = y else y = z) = (y = (if P then x else z))"
   409   "(if P then x = y else z = y) = (y = (if P then x else z))"
   410   by auto
   411 
   412 lemma [z3_rule]:
   413   "0 + (x::int) = x"
   414   "x + 0 = x"
   415   "x + x = 2 * x"
   416   "0 * x = 0"
   417   "1 * x = x"
   418   "x + y = y + x"
   419   by (auto simp add: mult_2)
   420 
   421 lemma [z3_rule]:  (* for def-axiom *)
   422   "P = Q \<or> P \<or> Q"
   423   "P = Q \<or> \<not> P \<or> \<not> Q"
   424   "(\<not> P) = Q \<or> \<not> P \<or> Q"
   425   "(\<not> P) = Q \<or> P \<or> \<not> Q"
   426   "P = (\<not> Q) \<or> \<not> P \<or> Q"
   427   "P = (\<not> Q) \<or> P \<or> \<not> Q"
   428   "P \<noteq> Q \<or> P \<or> \<not> Q"
   429   "P \<noteq> Q \<or> \<not> P \<or> Q"
   430   "P \<noteq> (\<not> Q) \<or> P \<or> Q"
   431   "(\<not> P) \<noteq> Q \<or> P \<or> Q"
   432   "P \<or> Q \<or> P \<noteq> (\<not> Q)"
   433   "P \<or> Q \<or> (\<not> P) \<noteq> Q"
   434   "P \<or> \<not> Q \<or> P \<noteq> Q"
   435   "\<not> P \<or> Q \<or> P \<noteq> Q"
   436   "P \<or> y = (if P then x else y)"
   437   "P \<or> (if P then x else y) = y"
   438   "\<not> P \<or> x = (if P then x else y)"
   439   "\<not> P \<or> (if P then x else y) = x"
   440   "P \<or> R \<or> \<not> (if P then Q else R)"
   441   "\<not> P \<or> Q \<or> \<not> (if P then Q else R)"
   442   "\<not> (if P then Q else R) \<or> \<not> P \<or> Q"
   443   "\<not> (if P then Q else R) \<or> P \<or> R"
   444   "(if P then Q else R) \<or> \<not> P \<or> \<not> Q"
   445   "(if P then Q else R) \<or> P \<or> \<not> R"
   446   "(if P then \<not> Q else R) \<or> \<not> P \<or> Q"
   447   "(if P then Q else \<not> R) \<or> P \<or> R"
   448   by auto
   449 
   450 hide_type (open) symb_list pattern
   451 hide_const (open) Symb_Nil Symb_Cons trigger pat nopat fun_app z3div z3mod
   452 
   453 end