src/HOL/SMT/Tools/z3_proof_rules.ML
changeset 33529 9fd3de94e6a2
parent 33519 e31a85f92ce9
child 33660 11574d52169d
equal deleted inserted replaced
33528:b34511bbc121 33529:9fd3de94e6a2
   150 fun net_instance net ct = first_of (Net.match_term net (Thm.term_of ct)) ct
   150 fun net_instance net ct = first_of (Net.match_term net (Thm.term_of ct)) ct
   151 end
   151 end
   152 
   152 
   153 fun certify ctxt = Thm.cterm_of (ProofContext.theory_of ctxt)
   153 fun certify ctxt = Thm.cterm_of (ProofContext.theory_of ctxt)
   154 fun certify_var ctxt idx T = certify ctxt (Var (("x", idx), T))
   154 fun certify_var ctxt idx T = certify ctxt (Var (("x", idx), T))
       
   155 fun certify_free ctxt idx T = certify ctxt (Free ("x" ^ string_of_int idx, T))
   155 
   156 
   156 fun varify ctxt =
   157 fun varify ctxt =
   157   let
   158   let
   158     fun varify1 cv thm =
   159     fun varify1 cv thm =
   159       let
   160       let
   434 in
   435 in
   435 fun unfold_distinct_conv ct =
   436 fun unfold_distinct_conv ct =
   436   (More_Conv.rewrs_conv [dist1, dist2] else_conv
   437   (More_Conv.rewrs_conv [dist1, dist2] else_conv
   437   (Conv.rewr_conv dist3 then_conv binop_conv set_conv unfold_distinct_conv)) ct
   438   (Conv.rewr_conv dist3 then_conv binop_conv set_conv unfold_distinct_conv)) ct
   438 end
   439 end
       
   440 
       
   441 (** proving abstractions **)
       
   442 
       
   443 fun fold_map_op f ct =
       
   444   let val (cf, cu) = Thm.dest_comb ct
       
   445   in f cu #>> Thm.capply cf end
       
   446 
       
   447 fun fold_map_binop f1 f2 ct =
       
   448   let val ((cf, cu1), cu2) = apfst Thm.dest_comb (Thm.dest_comb ct)
       
   449   in f1 cu1 ##>> f2 cu2 #>> uncurry (Thm.mk_binop cf) end
       
   450 
       
   451 fun abstraction_context ctxt = (ctxt, certify_var, 1, false, Ctermtab.empty)
       
   452 fun abstraction_context' ctxt = (ctxt, certify_free, 1, true, Ctermtab.empty)
       
   453 
       
   454 fun fresh_abstraction ct (cx as (ctxt, mk_var, idx, gen, tab)) =
       
   455   (case Ctermtab.lookup tab ct of
       
   456     SOME cv => (cv, cx)
       
   457   | NONE =>
       
   458       let val cv = mk_var ctxt idx (#T (Thm.rep_cterm ct))
       
   459       in (cv, (ctxt, mk_var, idx + 1, gen, Ctermtab.update (ct, cv) tab)) end)
       
   460 
       
   461 fun prove_abstraction tac ct (ctxt, _, _, gen, tab) =
       
   462   let
       
   463     val insts = map swap (Ctermtab.dest tab)
       
   464     val thm = Goal.prove_internal [] ct (fn _ => tac 1)
       
   465   in
       
   466     if gen
       
   467     then fold SMT_Normalize.instantiate_free insts thm
       
   468     else Thm.instantiate ([], insts) thm
       
   469   end
   439 
   470 
   440 
   471 
   441 (* core proof rules *)
   472 (* core proof rules *)
   442 
   473 
   443 datatype assms = Some of thm list | Many of thm Net.net
   474 datatype assms = Some of thm list | Many of thm Net.net
   686     as_meta_eq ct
   717     as_meta_eq ct
   687     |> by_tac' (nnf_quant_tac (varify ctxt vars (meta_eq_of p)) qs)
   718     |> by_tac' (nnf_quant_tac (varify ctxt vars (meta_eq_of p)) qs)
   688 
   719 
   689   val nnf_rules = thm_net_of [@{thm not_not}]
   720   val nnf_rules = thm_net_of [@{thm not_not}]
   690 
   721 
       
   722   fun abstract ct =
       
   723     (case Thm.term_of ct of
       
   724       @{term False} => pair
       
   725     | @{term Not} $ _ => fold_map_op abstract
       
   726     | @{term "op &"} $ _ $ _ => fold_map_binop abstract abstract
       
   727     | @{term "op |"} $ _ $ _ => fold_map_binop abstract abstract
       
   728     | @{term "op -->"} $ _ $ _ => fold_map_binop abstract abstract
       
   729     | @{term "op = :: bool => _"} $ _ $ _ => fold_map_binop abstract abstract
       
   730     | _ => fresh_abstraction) ct
       
   731 
       
   732   fun abstracted ctxt ct =
       
   733     abstraction_context' ctxt
       
   734     |> abstract (Thm.dest_arg ct)
       
   735     |>> T.mk_prop
       
   736     |-> prove_abstraction (Classical.best_tac HOL_cs)
       
   737 
   691   fun prove_nnf ctxt =
   738   fun prove_nnf ctxt =
   692     try_apply ctxt "nnf" [
   739     try_apply ctxt "nnf" [
   693       ("conj/disj", prove_conj_disj_eq o Thm.dest_arg),
   740       ("conj/disj", prove_conj_disj_eq o Thm.dest_arg),
   694       ("rule", the o net_instance nnf_rules),
   741       ("rule", the o net_instance nnf_rules),
       
   742       ("abstract", abstracted ctxt),
   695       ("tactic", by_tac' (Classical.best_tac HOL_cs))]
   743       ("tactic", by_tac' (Classical.best_tac HOL_cs))]
   696 in
   744 in
   697 fun nnf ctxt ps ct =
   745 fun nnf ctxt ps ct =
   698   (case Thm.term_of ct of
   746   (case Thm.term_of ct of
   699     _ $ (l as Const _ $ Abs _) $ (r as Const _ $ Abs _) =>
   747     _ $ (l as Const _ $ Abs _) $ (r as Const _ $ Abs _) =>
   982   in
  1030   in
   983   val all_distrib_conv = More_Conv.top_sweep_conv (K distrib_conv)
  1031   val all_distrib_conv = More_Conv.top_sweep_conv (K distrib_conv)
   984   end
  1032   end
   985 
  1033 
   986   local
  1034   local
   987     fun make_ctxt ctxt = (ctxt, Ctermtab.empty, 1)
  1035     fun fresh ct = fresh_abstraction ct
   988     fun fresh ct (cx as (ctxt, tab, idx)) =
       
   989       (case Ctermtab.lookup tab ct of
       
   990         SOME cv => (cv, cx)
       
   991       | NONE =>
       
   992           let val cv = certify_var ctxt idx (#T (Thm.rep_cterm ct))
       
   993           in (cv, (ctxt, Ctermtab.update (ct, cv) tab, idx + 1)) end)
       
   994 
       
   995     fun fold_map_op f ct =
       
   996       let val (cf, cu) = Thm.dest_comb ct
       
   997       in f cu #>> Thm.capply cf end
       
   998 
       
   999     fun fold_map_binop f1 f2 ct =
       
  1000       let val ((cf, cu1), cu2) = apfst Thm.dest_comb (Thm.dest_comb ct)
       
  1001       in f1 cu1 ##>> f2 cu2 #>> uncurry (Thm.mk_binop cf) end
       
  1002 
  1036 
  1003     fun mult f1 f2 ct t u =
  1037     fun mult f1 f2 ct t u =
  1004       if is_number t 
  1038       if is_number t 
  1005       then if is_number u then pair ct else fold_map_binop f1 f2 ct
  1039       then if is_number u then pair ct else fold_map_binop f1 f2 ct
  1006       else fresh ct
  1040       else fresh ct
  1039         @{term "op |"} $ _ $ _ => fold_map_binop disj disj ct
  1073         @{term "op |"} $ _ $ _ => fold_map_binop disj disj ct
  1040       | @{term False} => pair ct
  1074       | @{term False} => pair ct
  1041       | _ => conj ct)
  1075       | _ => conj ct)
  1042   in
  1076   in
  1043   fun prove_arith ctxt thms ct =
  1077   fun prove_arith ctxt thms ct =
  1044     let
  1078     abstraction_context ctxt
  1045       val (goal, (_, tab, _)) =
  1079     |> fold_map (fold_map_op ineq o Thm.cprop_of) thms
  1046         make_ctxt ctxt
  1080     ||>> fold_map_op disj ct
  1047         |> fold_map (fold_map_op ineq o Thm.cprop_of) thms
  1081     |>> uncurry (fold_rev (Thm.mk_binop @{cterm "op ==>"}))
  1048         ||>> fold_map_op disj ct
  1082     |-> prove_abstraction (Arith_Data.arith_tac ctxt)
  1049         |>> uncurry (fold_rev (Thm.mk_binop @{cterm "op ==>"}))
  1083     |> fold (fn th1 => fn th2 => Thm.implies_elim th2 th1) thms
  1050     in
       
  1051       Goal.prove_internal [] goal (fn _ => Arith_Data.arith_tac ctxt 1)
       
  1052       |> Thm.instantiate ([], map swap (Ctermtab.dest tab))
       
  1053       |> fold (fn th1 => fn th2 => Thm.implies_elim th2 th1) thms
       
  1054     end
       
  1055   end
  1084   end
  1056 in
  1085 in
  1057 fun arith_lemma ctxt thms ct =
  1086 fun arith_lemma ctxt thms ct =
  1058   let val thms' = map (Conv.fconv_rule (all_distrib_conv ctxt)) thms
  1087   let val thms' = map (Conv.fconv_rule (all_distrib_conv ctxt)) thms
  1059   in with_conv (all_distrib_conv ctxt) (prove_arith ctxt thms') ct end
  1088   in with_conv (all_distrib_conv ctxt) (prove_arith ctxt thms') ct end