Quot/quotient_tacs.ML
changeset 1128 17ca92ab4660
parent 1120 42b623872781
child 1137 36d596cb63a2
equal deleted inserted replaced
1127:243a5ceaa088 1128:17ca92ab4660
   100 
   100 
   101       ball_reg_eqv_range and bex_reg_eqv_range
   101       ball_reg_eqv_range and bex_reg_eqv_range
   102 
   102 
   103    Since the left-hand-side contains a non-pattern '?P (f ?x)'
   103    Since the left-hand-side contains a non-pattern '?P (f ?x)'
   104    we rely on unification/instantiation to check whether the
   104    we rely on unification/instantiation to check whether the
   105    theorem applies and return NONE if it doesn't. 
   105    theorem applies and return NONE if it doesn't.
   106 *)
   106 *)
   107 fun calculate_inst ctxt ball_bex_thm redex R1 R2 =
   107 fun calculate_inst ctxt ball_bex_thm redex R1 R2 =
   108 let
   108 let
   109   val thy = ProofContext.theory_of ctxt
   109   val thy = ProofContext.theory_of ctxt
   110   fun get_lhs thm = fst (Logic.dest_equals (Thm.concl_of thm))
   110   fun get_lhs thm = fst (Logic.dest_equals (Thm.concl_of thm))
   120 end
   120 end
   121 
   121 
   122 fun ball_bex_range_simproc ss redex =
   122 fun ball_bex_range_simproc ss redex =
   123 let
   123 let
   124   val ctxt = Simplifier.the_context ss
   124   val ctxt = Simplifier.the_context ss
   125 in 
   125 in
   126   case redex of
   126   case redex of
   127     (Const (@{const_name "Ball"}, _) $ (Const (@{const_name "Respects"}, _) $ 
   127     (Const (@{const_name "Ball"}, _) $ (Const (@{const_name "Respects"}, _) $
   128       (Const (@{const_name "fun_rel"}, _) $ R1 $ R2)) $ _) =>
   128       (Const (@{const_name "fun_rel"}, _) $ R1 $ R2)) $ _) =>
   129         calculate_inst ctxt @{thm ball_reg_eqv_range[THEN eq_reflection]} redex R1 R2
   129         calculate_inst ctxt @{thm ball_reg_eqv_range[THEN eq_reflection]} redex R1 R2
   130 
   130 
   131   | (Const (@{const_name "Bex"}, _) $ (Const (@{const_name "Respects"}, _) $ 
   131   | (Const (@{const_name "Bex"}, _) $ (Const (@{const_name "Respects"}, _) $
   132       (Const (@{const_name "fun_rel"}, _) $ R1 $ R2)) $ _) =>  
   132       (Const (@{const_name "fun_rel"}, _) $ R1 $ R2)) $ _) =>
   133         calculate_inst ctxt @{thm bex_reg_eqv_range[THEN eq_reflection]} redex R1 R2
   133         calculate_inst ctxt @{thm bex_reg_eqv_range[THEN eq_reflection]} redex R1 R2
   134 
   134 
   135   | _ => NONE
   135   | _ => NONE
   136 end
   136 end
   137 
   137 
   149   4. then rel-equalities, which need to be instantiated with 'eq_imp_rel'
   149   4. then rel-equalities, which need to be instantiated with 'eq_imp_rel'
   150      to avoid loops
   150      to avoid loops
   151 
   151 
   152   5. then simplification like 0
   152   5. then simplification like 0
   153 
   153 
   154   finally jump back to 1 
   154   finally jump back to 1
   155 *)
   155 *)
   156 fun regularize_tac ctxt =
   156 fun regularize_tac ctxt =
   157 let
   157 let
   158   val thy = ProofContext.theory_of ctxt
   158   val thy = ProofContext.theory_of ctxt
   159   val ball_pat = @{term "Ball (Respects (R1 ===> R2)) P"}
   159   val ball_pat = @{term "Ball (Respects (R1 ===> R2)) P"}
   160   val bex_pat  = @{term "Bex (Respects (R1 ===> R2)) P"}
   160   val bex_pat  = @{term "Bex (Respects (R1 ===> R2)) P"}
   161   val simproc = Simplifier.simproc_i thy "" [ball_pat, bex_pat] (K (ball_bex_range_simproc))
   161   val simproc = Simplifier.simproc_i thy "" [ball_pat, bex_pat] (K (ball_bex_range_simproc))
   162   val simpset = (mk_minimal_ss ctxt) 
   162   val simpset = (mk_minimal_ss ctxt)
   163                        addsimps @{thms ball_reg_eqv bex_reg_eqv babs_reg_eqv babs_simp}
   163                        addsimps @{thms ball_reg_eqv bex_reg_eqv babs_reg_eqv babs_simp}
   164                        addsimprocs [simproc] 
   164                        addsimprocs [simproc]
   165                        addSolver equiv_solver addSolver quotient_solver
   165                        addSolver equiv_solver addSolver quotient_solver
   166   val eq_eqvs = map (OF1 @{thm eq_imp_rel}) (equiv_rules_get ctxt)
   166   val eq_eqvs = map (OF1 @{thm eq_imp_rel}) (equiv_rules_get ctxt)
   167 in
   167 in
   168   simp_tac simpset THEN'
   168   simp_tac simpset THEN'
   169   REPEAT_ALL_NEW (CHANGED o FIRST' 
   169   REPEAT_ALL_NEW (CHANGED o FIRST'
   170     [resolve_tac @{thms ball_reg_right bex_reg_left bex1_bexeq_reg},
   170     [resolve_tac @{thms ball_reg_right bex_reg_left bex1_bexeq_reg},
   171      resolve_tac (Inductive.get_monos ctxt),
   171      resolve_tac (Inductive.get_monos ctxt),
   172      resolve_tac @{thms ball_all_comm bex_ex_comm},
   172      resolve_tac @{thms ball_all_comm bex_ex_comm},
   173      resolve_tac eq_eqvs,  
   173      resolve_tac eq_eqvs,
   174      simp_tac simpset])
   174      simp_tac simpset])
   175 end
   175 end
   176 
   176 
   177 
   177 
   178 
   178 
   179 (*** Injection Tactic ***)
   179 (*** Injection Tactic ***)
   180 
   180 
   181 (* Looks for Quot_True assumptions, and in case its parameter
   181 (* Looks for Quot_True assumptions, and in case its parameter
   182    is an application, it returns the function and the argument. 
   182    is an application, it returns the function and the argument.
   183 *)
   183 *)
   184 fun find_qt_asm asms =
   184 fun find_qt_asm asms =
   185 let
   185 let
   186   fun find_fun trm =
   186   fun find_fun trm =
   187     case trm of
   187     case trm of
   214       quot_true_simple_conv ctxt fnctn ctrm
   214       quot_true_simple_conv ctxt fnctn ctrm
   215   | _ $ _ => Conv.comb_conv (quot_true_conv ctxt fnctn) ctrm
   215   | _ $ _ => Conv.comb_conv (quot_true_conv ctxt fnctn) ctrm
   216   | Abs _ => Conv.abs_conv (fn (_, ctxt) => quot_true_conv ctxt fnctn) ctxt ctrm
   216   | Abs _ => Conv.abs_conv (fn (_, ctxt) => quot_true_conv ctxt fnctn) ctxt ctrm
   217   | _ => Conv.all_conv ctrm
   217   | _ => Conv.all_conv ctrm
   218 
   218 
   219 fun quot_true_tac ctxt fnctn = 
   219 fun quot_true_tac ctxt fnctn =
   220    CONVERSION
   220    CONVERSION
   221     ((Conv.params_conv ~1 (fn ctxt =>
   221     ((Conv.params_conv ~1 (fn ctxt =>
   222        (Conv.prems_conv ~1 (quot_true_conv ctxt fnctn)))) ctxt)
   222        (Conv.prems_conv ~1 (quot_true_conv ctxt fnctn)))) ctxt)
   223 
   223 
   224 fun dest_comb (f $ a) = (f, a) 
   224 fun dest_comb (f $ a) = (f, a)
   225 fun dest_bcomb ((_ $ l) $ r) = (l, r) 
   225 fun dest_bcomb ((_ $ l) $ r) = (l, r)
   226 
   226 
   227 fun unlam t =
   227 fun unlam t =
   228   case t of
   228   case t of
   229     (Abs a) => snd (Term.dest_abs a)
   229     (Abs a) => snd (Term.dest_abs a)
   230   | _ => unlam (Abs("", domain_type (fastype_of t), (incr_boundvars 1 t) $ (Bound 0)))
   230   | _ => unlam (Abs("", domain_type (fastype_of t), (incr_boundvars 1 t) $ (Bound 0)))
   234 
   234 
   235 val bare_concl = HOLogic.dest_Trueprop o Logic.strip_assums_concl
   235 val bare_concl = HOLogic.dest_Trueprop o Logic.strip_assums_concl
   236 
   236 
   237 (* We apply apply_rsp only in case if the type needs lifting.
   237 (* We apply apply_rsp only in case if the type needs lifting.
   238    This is the case if the type of the data in the Quot_True
   238    This is the case if the type of the data in the Quot_True
   239    assumption is different from the corresponding type in the goal. 
   239    assumption is different from the corresponding type in the goal.
   240 *)
   240 *)
   241 val apply_rsp_tac =
   241 val apply_rsp_tac =
   242   Subgoal.FOCUS (fn {concl, asms, context,...} =>
   242   Subgoal.FOCUS (fn {concl, asms, context,...} =>
   243   let
   243   let
   244     val bare_concl = HOLogic.dest_Trueprop (term_of concl)
   244     val bare_concl = HOLogic.dest_Trueprop (term_of concl)
   263            end
   263            end
   264     | _ => no_tac
   264     | _ => no_tac
   265   end)
   265   end)
   266 
   266 
   267 (* Instantiates and applies 'equals_rsp'. Since the theorem is
   267 (* Instantiates and applies 'equals_rsp'. Since the theorem is
   268    complex we rely on instantiation to tell us if it applies 
   268    complex we rely on instantiation to tell us if it applies
   269 *)
   269 *)
   270 fun equals_rsp_tac R ctxt =
   270 fun equals_rsp_tac R ctxt =
   271 let
   271 let
   272   val thy = ProofContext.theory_of ctxt
   272   val thy = ProofContext.theory_of ctxt
   273 in
   273 in
   302         end
   302         end
   303     | _ => no_tac)
   303     | _ => no_tac)
   304 
   304 
   305 
   305 
   306 
   306 
   307 (* Injection means to prove that the regularised theorem implies 
   307 (* Injection means to prove that the regularised theorem implies
   308    the abs/rep injected one.
   308    the abs/rep injected one.
   309 
   309 
   310    The deterministic part:
   310    The deterministic part:
   311     - remove lambdas from both sides
   311     - remove lambdas from both sides
   312     - prove Ball/Bex/Babs equalities using ball_rsp, bex_rsp, babs_rsp
   312     - prove Ball/Bex/Babs equalities using ball_rsp, bex_rsp, babs_rsp
   315     - prove equality of relations using equals_rsp
   315     - prove equality of relations using equals_rsp
   316     - use user-supplied RSP theorems
   316     - use user-supplied RSP theorems
   317     - solve 'relation of relations' goals using quot_rel_rsp
   317     - solve 'relation of relations' goals using quot_rel_rsp
   318     - remove rep_abs from the right side
   318     - remove rep_abs from the right side
   319       (Lambdas under respects may have left us some assumptions)
   319       (Lambdas under respects may have left us some assumptions)
   320  
   320 
   321    Then in order:
   321    Then in order:
   322     - split applications of lifted type (apply_rsp)
   322     - split applications of lifted type (apply_rsp)
   323     - split applications of non-lifted type (cong_tac)
   323     - split applications of non-lifted type (cong_tac)
   324     - apply extentionality
   324     - apply extentionality
   325     - assumption
   325     - assumption
   362 | (_ $
   362 | (_ $
   363     (Const(@{const_name Babs},_) $ (Const (@{const_name Respects}, _) $ _) $ _) $
   363     (Const(@{const_name Babs},_) $ (Const (@{const_name Respects}, _) $ _) $ _) $
   364     (Const(@{const_name Babs},_) $ (Const (@{const_name Respects}, _) $ _) $ _))
   364     (Const(@{const_name Babs},_) $ (Const (@{const_name Respects}, _) $ _) $ _))
   365       => rtac @{thm babs_rsp} THEN' RANGE [quotient_tac ctxt]
   365       => rtac @{thm babs_rsp} THEN' RANGE [quotient_tac ctxt]
   366 
   366 
   367 | Const (@{const_name "op ="},_) $ (R $ _ $ _) $ (_ $ _ $ _) => 
   367 | Const (@{const_name "op ="},_) $ (R $ _ $ _) $ (_ $ _ $ _) =>
   368    (rtac @{thm refl} ORELSE'
   368    (rtac @{thm refl} ORELSE'
   369     (equals_rsp_tac R ctxt THEN' RANGE [
   369     (equals_rsp_tac R ctxt THEN' RANGE [
   370        quot_true_tac ctxt (fst o dest_bcomb), quot_true_tac ctxt (snd o dest_bcomb)]))
   370        quot_true_tac ctxt (fst o dest_bcomb), quot_true_tac ctxt (snd o dest_bcomb)]))
   371 
   371 
   372     (* reflexivity of operators arising from Cong_tac *)
   372     (* reflexivity of operators arising from Cong_tac *)
   377     => resolve_tac (rsp_rules_get ctxt) THEN_ALL_NEW quotient_tac ctxt
   377     => resolve_tac (rsp_rules_get ctxt) THEN_ALL_NEW quotient_tac ctxt
   378 
   378 
   379     (* R (...) (Rep (Abs ...)) ----> R (...) (...) *)
   379     (* R (...) (Rep (Abs ...)) ----> R (...) (...) *)
   380     (* observe fun_map *)
   380     (* observe fun_map *)
   381 | _ $ _ $ _
   381 | _ $ _ $ _
   382     => (rtac @{thm quot_rel_rsp} THEN_ALL_NEW quotient_tac ctxt) 
   382     => (rtac @{thm quot_rel_rsp} THEN_ALL_NEW quotient_tac ctxt)
   383        ORELSE' rep_abs_rsp_tac ctxt
   383        ORELSE' rep_abs_rsp_tac ctxt
   384 
   384 
   385 | _ => K no_tac
   385 | _ => K no_tac
   386 ) i)
   386 ) i)
   387 
   387 
   426 fun fun_map_simple_conv xs ctrm =
   426 fun fun_map_simple_conv xs ctrm =
   427   case (term_of ctrm) of
   427   case (term_of ctrm) of
   428     ((Const (@{const_name "fun_map"}, _) $ _ $ _) $ h $ _) =>
   428     ((Const (@{const_name "fun_map"}, _) $ _ $ _) $ h $ _) =>
   429         if member (op=) xs h
   429         if member (op=) xs h
   430         then Conv.all_conv ctrm
   430         then Conv.all_conv ctrm
   431         else Conv.rewr_conv @{thm fun_map_def[THEN eq_reflection]} ctrm 
   431         else Conv.rewr_conv @{thm fun_map_def[THEN eq_reflection]} ctrm
   432   | _ => Conv.all_conv ctrm
   432   | _ => Conv.all_conv ctrm
   433 
   433 
   434 fun fun_map_conv xs ctxt ctrm =
   434 fun fun_map_conv xs ctxt ctrm =
   435   case (term_of ctrm) of
   435   case (term_of ctrm) of
   436       _ $ _ => (Conv.comb_conv (fun_map_conv xs ctxt) then_conv
   436       _ $ _ => (Conv.comb_conv (fun_map_conv xs ctxt) then_conv
   468 (* Simplifies a redex using the 'lambda_prs' theorem.
   468 (* Simplifies a redex using the 'lambda_prs' theorem.
   469    First instantiates the types and known subterms.
   469    First instantiates the types and known subterms.
   470    Then solves the quotient assumptions to get Rep2 and Abs1
   470    Then solves the quotient assumptions to get Rep2 and Abs1
   471    Finally instantiates the function f using make_inst
   471    Finally instantiates the function f using make_inst
   472    If Rep2 is an identity then the pattern is simpler and
   472    If Rep2 is an identity then the pattern is simpler and
   473    make_inst_id is used 
   473    make_inst_id is used
   474 *)
   474 *)
   475 fun lambda_prs_simple_conv ctxt ctrm =
   475 fun lambda_prs_simple_conv ctxt ctrm =
   476   case (term_of ctrm) of
   476   case (term_of ctrm) of
   477     (Const (@{const_name fun_map}, _) $ r1 $ a2) $ (Abs _) =>
   477     (Const (@{const_name fun_map}, _) $ r1 $ a2) $ (Abs _) =>
   478       let
   478       let
   499 
   499 
   500 
   500 
   501 (* Cleaning consists of:
   501 (* Cleaning consists of:
   502 
   502 
   503   1. unfolding of ---> in front of everything, except
   503   1. unfolding of ---> in front of everything, except
   504      bound variables (this prevents lambda_prs from 
   504      bound variables (this prevents lambda_prs from
   505      becoming stuck)
   505      becoming stuck)
   506 
   506 
   507   2. simplification with lambda_prs
   507   2. simplification with lambda_prs
   508 
   508 
   509   3. simplification with: 
   509   3. simplification with:
   510 
   510 
   511       - Quotient_abs_rep Quotient_rel_rep 
   511       - Quotient_abs_rep Quotient_rel_rep
   512         babs_prs all_prs ex_prs ex1_prs
   512         babs_prs all_prs ex_prs ex1_prs
   513 
   513 
   514       - id_simps and preservation lemmas and 
   514       - id_simps and preservation lemmas and
   515 
   515 
   516       - symmetric versions of the definitions    
   516       - symmetric versions of the definitions
   517         (that is definitions of quotient constants 
   517         (that is definitions of quotient constants
   518          are folded)
   518          are folded)
   519 
   519 
   520   4. test for refl
   520   4. test for refl
   521 *)
   521 *)
   522 fun clean_tac lthy =
   522 fun clean_tac lthy =
   543    Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}
   543    Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}
   544 
   544 
   545 fun inst_spec_tac ctrms =
   545 fun inst_spec_tac ctrms =
   546   EVERY' (map (dtac o inst_spec) ctrms)
   546   EVERY' (map (dtac o inst_spec) ctrms)
   547 
   547 
   548 fun all_list xs trm = 
   548 fun all_list xs trm =
   549   fold (fn (x, T) => fn t' => HOLogic.mk_all (x, T, t')) xs trm
   549   fold (fn (x, T) => fn t' => HOLogic.mk_all (x, T, t')) xs trm
   550 
   550 
   551 fun apply_under_Trueprop f = 
   551 fun apply_under_Trueprop f =
   552   HOLogic.dest_Trueprop #> f #> HOLogic.mk_Trueprop
   552   HOLogic.dest_Trueprop #> f #> HOLogic.mk_Trueprop
   553 
   553 
   554 fun gen_frees_tac ctxt =
   554 fun gen_frees_tac ctxt =
   555   SUBGOAL (fn (concl, i) =>
   555   SUBGOAL (fn (concl, i) =>
   556     let
   556     let
   575 
   575 
   576    - 1st prem is the regularization step
   576    - 1st prem is the regularization step
   577    - 2nd prem is the rep/abs injection step
   577    - 2nd prem is the rep/abs injection step
   578    - 3rd prem is the cleaning part
   578    - 3rd prem is the cleaning part
   579 
   579 
   580    the Quot_True premise in 2nd records the lifted theorem 
   580    the Quot_True premise in 2nd records the lifted theorem
   581 *)
   581 *)
   582 val lifting_procedure_thm =
   582 val lifting_procedure_thm =
   583   @{lemma  "[|A;
   583   @{lemma  "[|A;
   584               A --> B;
   584               A --> B;
   585               Quot_True D ==> B = C;
   585               Quot_True D ==> B = C;
   588 
   588 
   589 fun lift_match_error ctxt msg rtrm qtrm =
   589 fun lift_match_error ctxt msg rtrm qtrm =
   590 let
   590 let
   591   val rtrm_str = Syntax.string_of_term ctxt rtrm
   591   val rtrm_str = Syntax.string_of_term ctxt rtrm
   592   val qtrm_str = Syntax.string_of_term ctxt qtrm
   592   val qtrm_str = Syntax.string_of_term ctxt qtrm
   593   val msg = cat_lines [enclose "[" "]" msg, "The quotient theorem", qtrm_str, 
   593   val msg = cat_lines [enclose "[" "]" msg, "The quotient theorem", qtrm_str,
   594     "", "does not match with original theorem", rtrm_str]
   594     "", "does not match with original theorem", rtrm_str]
   595 in
   595 in
   596   error msg
   596   error msg
   597 end
   597 end
   598 
   598 
   627 
   627 
   628 
   628 
   629 (* Automatic Proofs *)
   629 (* Automatic Proofs *)
   630 
   630 
   631 val msg1 = "The regularize proof failed."
   631 val msg1 = "The regularize proof failed."
   632 val msg2 = cat_lines ["The injection proof failed.", 
   632 val msg2 = cat_lines ["The injection proof failed.",
   633                       "This is probably due to missing respects lemmas.",
   633                       "This is probably due to missing respects lemmas.",
   634                       "Try invoking the injection method manually to see", 
   634                       "Try invoking the injection method manually to see",
   635                       "which lemmas are missing."]
   635                       "which lemmas are missing."]
   636 val msg3 = "The cleaning proof failed."
   636 val msg3 = "The cleaning proof failed."
   637 
   637 
   638 fun lift_tac ctxt rthms =
   638 fun lift_tac ctxt rthms =
   639 let
   639 let
   640   fun mk_tac rthm = 
   640   fun mk_tac rthm =
   641     procedure_tac ctxt rthm
   641     procedure_tac ctxt rthm
   642     THEN' RANGE_WARN 
   642     THEN' RANGE_WARN
   643       [(regularize_tac ctxt, msg1),
   643       [(regularize_tac ctxt, msg1),
   644        (all_injection_tac ctxt, msg2),
   644        (all_injection_tac ctxt, msg2),
   645        (clean_tac ctxt, msg3)]
   645        (clean_tac ctxt, msg3)]
   646 in
   646 in
   647   simp_tac (mk_minimal_ss ctxt) (* unfolding multiple &&& *)  
   647   simp_tac (mk_minimal_ss ctxt) (* unfolding multiple &&& *)
   648   THEN' RANGE (map mk_tac rthms)
   648   THEN' RANGE (map mk_tac rthms)
   649 end
   649 end
   650 
   650 
   651 (* An Attribute which automatically constructs the qthm *)
   651 (* An Attribute which automatically constructs the qthm *)
   652 fun lifted_attrib_aux context thm =
   652 fun lifted_attrib_aux context thm =