src/HOL/Tools/SMT/z3_proof_tools.ML
changeset 36899 bcd6fce5bf06
parent 36898 8e55aa1306c5
child 36936 c52d1c130898
equal deleted inserted replaced
36898:8e55aa1306c5 36899:bcd6fce5bf06
    23   val varify: string list -> thm -> thm
    23   val varify: string list -> thm -> thm
    24   val unfold_eqs: Proof.context -> thm list -> conv
    24   val unfold_eqs: Proof.context -> thm list -> conv
    25   val match_instantiate: (cterm -> cterm) -> cterm -> thm -> thm
    25   val match_instantiate: (cterm -> cterm) -> cterm -> thm -> thm
    26   val by_tac: (int -> tactic) -> cterm -> thm
    26   val by_tac: (int -> tactic) -> cterm -> thm
    27   val make_hyp_def: thm -> Proof.context -> thm * Proof.context
    27   val make_hyp_def: thm -> Proof.context -> thm * Proof.context
    28   val by_abstraction: Proof.context -> thm list -> (Proof.context -> cterm ->
    28   val by_abstraction: bool * bool -> Proof.context -> thm list ->
    29     thm) -> cterm -> thm
    29     (Proof.context -> cterm -> thm) -> cterm -> thm
    30 
    30 
    31   (* a faster COMP *)
    31   (* a faster COMP *)
    32   type compose_data
    32   type compose_data
    33   val precompose: (cterm -> cterm list) -> thm -> compose_data
    33   val precompose: (cterm -> cterm list) -> thm -> compose_data
    34   val precompose2: (cterm -> cterm * cterm) -> thm -> compose_data
    34   val precompose2: (cterm -> cterm * cterm) -> thm -> compose_data
    36 
    36 
    37   (* unfolding of 'distinct' *)
    37   (* unfolding of 'distinct' *)
    38   val unfold_distinct_conv: conv
    38   val unfold_distinct_conv: conv
    39 
    39 
    40   (* simpset *)
    40   (* simpset *)
       
    41   val add_simproc: Simplifier.simproc -> Context.generic -> Context.generic
    41   val make_simpset: Proof.context -> thm list -> simpset
    42   val make_simpset: Proof.context -> thm list -> simpset
    42 end
    43 end
    43 
    44 
    44 structure Z3_Proof_Tools: Z3_PROOF_TOOLS =
    45 structure Z3_Proof_Tools: Z3_PROOF_TOOLS =
    45 struct
    46 struct
    46 
    47 
       
    48 structure I = Z3_Interface
       
    49 
    47 
    50 
    48 
    51 
    49 (* accessing terms *)
    52 (* accessing terms *)
    50 
    53 
    51 val dest_prop = (fn @{term Trueprop} $ t => t | t => t)
    54 val dest_prop = (fn @{term Trueprop} $ t => t | t => t)
    53 fun term_of ct = dest_prop (Thm.term_of ct)
    56 fun term_of ct = dest_prop (Thm.term_of ct)
    54 fun prop_of thm = dest_prop (Thm.prop_of thm)
    57 fun prop_of thm = dest_prop (Thm.prop_of thm)
    55 
    58 
    56 val mk_prop = Thm.capply @{cterm Trueprop}
    59 val mk_prop = Thm.capply @{cterm Trueprop}
    57 
    60 
    58 val (eqT, eq) = `(hd o Thm.dest_ctyp o Thm.ctyp_of_term) @{cpat "op =="}
    61 val eq = I.mk_inst_pair I.destT1 @{cpat "op =="}
    59 fun mk_meta_eq_cterm ct cu =
    62 fun mk_meta_eq_cterm ct cu = Thm.mk_binop (I.instT' ct eq) ct cu
    60   let val inst = ([(eqT, Thm.ctyp_of_term ct)], [])
       
    61   in Thm.mk_binop (Thm.instantiate_cterm inst eq) ct cu end
       
    62 
    63 
    63 fun as_meta_eq ct = uncurry mk_meta_eq_cterm (Thm.dest_binop (Thm.dest_arg ct))
    64 fun as_meta_eq ct = uncurry mk_meta_eq_cterm (Thm.dest_binop (Thm.dest_arg ct))
    64 
    65 
    65 
    66 
    66 
    67 
   127 
   128 
   128 fun abs_context ctxt = (ctxt, Termtab.empty, 1, false)
   129 fun abs_context ctxt = (ctxt, Termtab.empty, 1, false)
   129 
   130 
   130 fun context_of (ctxt, _, _, _) = ctxt
   131 fun context_of (ctxt, _, _, _) = ctxt
   131 
   132 
   132 fun replace (cv, ct) = Thm.forall_elim ct o Thm.forall_intr cv
   133 fun replace (_, (cv, ct)) = Thm.forall_elim ct o Thm.forall_intr cv
   133 
   134 
   134 fun abs_instantiate (_, tab, _, beta_norm) =
   135 fun abs_instantiate (_, tab, _, beta_norm) =
   135   fold replace (map snd (Termtab.dest tab)) #>
   136   fold replace (Termtab.dest tab) #>
   136   beta_norm ? Conv.fconv_rule (Thm.beta_conversion true)
   137   beta_norm ? Conv.fconv_rule (Thm.beta_conversion true)
   137 
   138 
   138 fun generalize cvs =
   139 fun lambda_abstract cvs t =
   139   let
   140   let
   140     val no_name = ""
   141     val frees = map Free (Term.add_frees t [])
   141 
   142     val cvs' = filter (fn cv => member (op aconv) frees (Thm.term_of cv)) cvs
   142     fun dest (Free (n, _)) = n
   143     val vs = map (Term.dest_Free o Thm.term_of) cvs'
   143       | dest _ = no_name
   144   in (Term.list_abs_free (vs, t), cvs') end
   144 
       
   145     fun gen vs (t as Free (n, _)) =
       
   146           let val i = find_index (equal n) vs
       
   147           in
       
   148             if i >= 0 then insert (op aconvc) (nth cvs i) #> pair (Bound i)
       
   149             else pair t
       
   150           end
       
   151       | gen vs (t $ u) = gen vs t ##>> gen vs u #>> (op $)
       
   152       | gen vs (Abs (n, T, t)) =
       
   153           gen (no_name :: vs) t #>> (fn u => Abs (n, T, u))
       
   154       | gen _ t = pair t
       
   155 
       
   156   in (fn ct => gen (map (dest o Thm.term_of) cvs) (Thm.term_of ct) []) end
       
   157 
   145 
   158 fun fresh_abstraction cvs ct (cx as (ctxt, tab, idx, beta_norm)) =
   146 fun fresh_abstraction cvs ct (cx as (ctxt, tab, idx, beta_norm)) =
   159   let val (t, cvs') = generalize cvs ct
   147   let val (t, cvs') = lambda_abstract cvs (Thm.term_of ct)
   160   in
   148   in
   161     (case Termtab.lookup tab t of
   149     (case Termtab.lookup tab t of
   162       SOME (cv, _) => (cv, cx)
   150       SOME (cv, _) => (Drule.list_comb (cv, cvs'), cx)
   163     | NONE =>
   151     | NONE =>
   164         let
   152         let
   165           val (n, ctxt') = yield_singleton Variable.variant_fixes "x" ctxt
   153           val (n, ctxt') = yield_singleton Variable.variant_fixes "x" ctxt
   166           val cv = certify ctxt (Free (n, map typ_of cvs' ---> typ_of ct))
   154           val cv = certify ctxt' (Free (n, map typ_of cvs' ---> typ_of ct))
   167           val cv' = Drule.list_comb (cv, cvs')
   155           val cu = Drule.list_comb (cv, cvs')
   168           val e = (t, (cv, fold_rev Thm.cabs cvs' ct))
   156           val e = (t, (cv, fold_rev Thm.cabs cvs' ct))
   169           val beta_norm' = beta_norm orelse not (null cvs')
   157           val beta_norm' = beta_norm orelse not (null cvs')
   170         in (cv', (ctxt', Termtab.update e tab, idx + 1, beta_norm')) end)
   158         in (cu, (ctxt', Termtab.update e tab, idx + 1, beta_norm')) end)
   171   end
   159   end
   172 
       
   173 fun abs_arg f cvs ct =
       
   174   let val (cf, cu) = Thm.dest_comb ct
       
   175   in f cvs cu #>> Thm.capply cf end
       
   176 
   160 
   177 fun abs_comb f g cvs ct =
   161 fun abs_comb f g cvs ct =
   178   let val (cf, cu) = Thm.dest_comb ct
   162   let val (cf, cu) = Thm.dest_comb ct
   179   in f cvs cf ##>> g cvs cu #>> uncurry Thm.capply end
   163   in f cvs cf ##>> g cvs cu #>> uncurry Thm.capply end
       
   164 
       
   165 fun abs_arg f = abs_comb (K pair) f
       
   166 
       
   167 fun abs_args f cvs ct =
       
   168   (case Thm.term_of ct of
       
   169     _ $ _ => abs_comb (abs_args f) f cvs ct
       
   170   | _ => pair ct)
   180 
   171 
   181 fun abs_list f g cvs ct =
   172 fun abs_list f g cvs ct =
   182   (case Thm.term_of ct of
   173   (case Thm.term_of ct of
   183     Const (@{const_name Nil}, _) => pair ct
   174     Const (@{const_name Nil}, _) => pair ct
   184   | Const (@{const_name Cons}, _) $ _ $ _ =>
   175   | Const (@{const_name Cons}, _) $ _ $ _ =>
   188 fun abs_abs f cvs ct =
   179 fun abs_abs f cvs ct =
   189   let val (cv, cu) = Thm.dest_abs NONE ct
   180   let val (cv, cu) = Thm.dest_abs NONE ct
   190   in f (cv :: cvs) cu #>> Thm.cabs cv end
   181   in f (cv :: cvs) cu #>> Thm.cabs cv end
   191 
   182 
   192 val is_atomic = (fn _ $ _ => false | Abs _ => false | _ => true)
   183 val is_atomic = (fn _ $ _ => false | Abs _ => false | _ => true)
   193 val is_arithT = (fn @{typ int} => true | @{typ real} => true | _ => false)
       
   194 fun is_number t =
       
   195   (case try HOLogic.dest_number t of
       
   196     SOME (T, _) => is_arithT T
       
   197   | NONE => false)
       
   198 
   184 
   199 fun abstract (ext_logic, with_theories) =
   185 fun abstract (ext_logic, with_theories) =
   200   let
   186   let
   201     fun abstr1 cvs ct = abs_arg abstr cvs ct
   187     fun abstr1 cvs ct = abs_arg abstr cvs ct
   202     and abstr2 cvs ct = abs_comb abstr1 abstr cvs ct
   188     and abstr2 cvs ct = abs_comb abstr1 abstr cvs ct
   221           if ext_logic then abstr3 cvs ct else fresh_abstraction cvs ct
   207           if ext_logic then abstr3 cvs ct else fresh_abstraction cvs ct
   222       | Const (@{const_name All}, _) $ _ =>
   208       | Const (@{const_name All}, _) $ _ =>
   223           if ext_logic then abstr_abs cvs ct else fresh_abstraction cvs ct
   209           if ext_logic then abstr_abs cvs ct else fresh_abstraction cvs ct
   224       | Const (@{const_name Ex}, _) $ _ =>
   210       | Const (@{const_name Ex}, _) $ _ =>
   225           if ext_logic then abstr_abs cvs ct else fresh_abstraction cvs ct
   211           if ext_logic then abstr_abs cvs ct else fresh_abstraction cvs ct
   226       | @{term "uminus :: int => _"} $ _ => abstr1 cvs ct
   212       | t => (fn cx =>
   227       | @{term "uminus :: real => _"} $ _ => abstr1 cvs ct
   213           if is_atomic t orelse can HOLogic.dest_number t then (ct, cx)
   228       | @{term "op + :: int => _"} $ _ $ _ => abstr2 cvs ct
   214           else if with_theories andalso
   229       | @{term "op + :: real => _"} $ _ $ _ => abstr2 cvs ct
   215             I.is_builtin_theory_term (context_of cx) t
   230       | @{term "op - :: int => _"} $ _ $ _ => abstr2 cvs ct
   216           then abs_args abstr cvs ct cx
   231       | @{term "op - :: real => _"} $ _ $ _ => abstr2 cvs ct
   217           else fresh_abstraction cvs ct cx))
   232       | @{term "op * :: int => _"} $ _ $ _ => abstr2 cvs ct
       
   233       | @{term "op * :: real => _"} $ _ $ _ => abstr2 cvs ct
       
   234       | @{term "op div :: int => _"} $ _ $ _ => abstr2 cvs ct
       
   235       | @{term "op mod :: int => _"} $ _ $ _ => abstr2 cvs ct
       
   236       | @{term "op / :: real => _"} $ _ $ _ => abstr2 cvs ct
       
   237       | @{term "op < :: int => _"} $ _ $ _ => abstr2 cvs ct
       
   238       | @{term "op < :: real => _"} $ _ $ _ => abstr2 cvs ct
       
   239       | @{term "op <= :: int => _"} $ _ $ _ => abstr2 cvs ct
       
   240       | @{term "op <= :: real => _"} $ _ $ _ => abstr2 cvs ct
       
   241       | Const (@{const_name apply}, _) $ _ $ _ => abstr2 cvs ct
       
   242       | Const (@{const_name fun_upd}, _) $ _ $ _ $ _ => abstr3 cvs ct
       
   243       | t =>
       
   244           if is_atomic t orelse is_number t then pair ct
       
   245           else fresh_abstraction cvs ct)
       
   246   in abstr [] end
   218   in abstr [] end
   247 
   219 
   248 fun with_prems thms f ct =
   220 fun with_prems thms f ct =
   249   fold_rev (Thm.mk_binop @{cterm "op ==>"} o Thm.cprop_of) thms ct
   221   fold_rev (Thm.mk_binop @{cterm "op ==>"} o Thm.cprop_of) thms ct
   250   |> f
   222   |> f
   251   |> fold (fn prem => fn th => Thm.implies_elim th prem) thms
   223   |> fold (fn prem => fn th => Thm.implies_elim th prem) thms
   252 
   224 
   253 in
   225 in
   254 
   226 
   255 fun by_abstraction ctxt thms prove = with_prems thms (fn ct =>
   227 fun by_abstraction mode ctxt thms prove = with_prems thms (fn ct =>
   256   let val (cu, cx) = abstract (true, true) ct (abs_context ctxt)
   228   let val (cu, cx) = abstract mode ct (abs_context ctxt)
   257   in abs_instantiate cx (prove (context_of cx) cu) end)
   229   in abs_instantiate cx (prove (context_of cx) cu) end)
   258 
   230 
   259 end
   231 end
   260 
   232 
   261 
   233 
   338           find_first (eq_prop (HOLogic.mk_not (less $ s $ r))) prems
   310           find_first (eq_prop (HOLogic.mk_not (less $ s $ r))) prems
   339           |> Option.map (fn thm => thm RS antisym_less2)
   311           |> Option.map (fn thm => thm RS antisym_less2)
   340       | SOME thm => SOME (thm RS antisym_le2))
   312       | SOME thm => SOME (thm RS antisym_le2))
   341   end
   313   end
   342   handle THM _ => NONE
   314   handle THM _ => NONE
       
   315 
       
   316   val basic_simpset = HOL_ss addsimps @{thms field_simps}
       
   317     addsimps [@{thm times_divide_eq_right}, @{thm times_divide_eq_left}]
       
   318     addsimps @{thms arith_special} addsimps @{thms less_bin_simps}
       
   319     addsimps @{thms le_bin_simps} addsimps @{thms eq_bin_simps}
       
   320     addsimps @{thms add_bin_simps} addsimps @{thms succ_bin_simps}
       
   321     addsimps @{thms minus_bin_simps} addsimps @{thms pred_bin_simps}
       
   322     addsimps @{thms mult_bin_simps} addsimps @{thms iszero_simps}
       
   323     addsimps @{thms array_rules}
       
   324     addsimprocs [
       
   325       Simplifier.simproc @{theory} "fast_int_arith" [
       
   326         "(m::int) < n", "(m::int) <= n", "(m::int) = n"] (K Lin_Arith.simproc),
       
   327       Simplifier.simproc @{theory} "antisym_le" ["(x::'a::order) <= y"]
       
   328         (K prove_antisym_le),
       
   329       Simplifier.simproc @{theory} "antisym_less" ["~ (x::'a::linorder) < y"]
       
   330         (K prove_antisym_less)]
       
   331 
       
   332   structure Simpset = Generic_Data
       
   333   (
       
   334     type T = simpset
       
   335     val empty = basic_simpset
       
   336     val extend = I
       
   337     val merge = Simplifier.merge_ss
       
   338   )
   343 in
   339 in
   344 
   340 
   345 fun make_simpset ctxt rules = Simplifier.context ctxt (HOL_ss
   341 fun add_simproc simproc = Simpset.map (fn ss => ss addsimprocs [simproc])
   346   addsimps @{thms field_simps}
   342 
   347   addsimps [@{thm times_divide_eq_right}, @{thm times_divide_eq_left}]
   343 fun make_simpset ctxt rules =
   348   addsimps @{thms arith_special} addsimps @{thms less_bin_simps}
   344   Simplifier.context ctxt (Simpset.get (Context.Proof ctxt)) addsimps rules
   349   addsimps @{thms le_bin_simps} addsimps @{thms eq_bin_simps}
   345 
   350   addsimps @{thms add_bin_simps} addsimps @{thms succ_bin_simps}
   346 end
   351   addsimps @{thms minus_bin_simps} addsimps @{thms pred_bin_simps}
   347 
   352   addsimps @{thms mult_bin_simps} addsimps @{thms iszero_simps}
   348 end
   353   addsimps @{thms array_rules}
       
   354   addsimprocs [
       
   355     Simplifier.simproc @{theory} "fast_int_arith" [
       
   356       "(m::int) < n", "(m::int) <= n", "(m::int) = n"] (K Lin_Arith.simproc),
       
   357     Simplifier.simproc @{theory} "fast_real_arith" [
       
   358       "(m::real) < n", "(m::real) <= n", "(m::real) = n"]
       
   359       (K Lin_Arith.simproc),
       
   360     Simplifier.simproc @{theory} "antisym_le" ["(x::'a::order) <= y"]
       
   361       (K prove_antisym_le),
       
   362     Simplifier.simproc @{theory} "antisym_less" ["~ (x::'a::linorder) < y"]
       
   363       (K prove_antisym_less)]
       
   364   addsimps rules)
       
   365 
       
   366 end
       
   367 
       
   368 end