src/HOL/Tools/Lifting/lifting_info.ML
changeset 51374 84d01fd733cf
parent 50227 01d545993e8c
child 51426 f25ee4fb437d
equal deleted inserted replaced
51373:65f4284d3f1a 51374:84d01fd733cf
     9   type quotmaps = {rel_quot_thm: thm}
     9   type quotmaps = {rel_quot_thm: thm}
    10   val lookup_quotmaps: Proof.context -> string -> quotmaps option
    10   val lookup_quotmaps: Proof.context -> string -> quotmaps option
    11   val lookup_quotmaps_global: theory -> string -> quotmaps option
    11   val lookup_quotmaps_global: theory -> string -> quotmaps option
    12   val print_quotmaps: Proof.context -> unit
    12   val print_quotmaps: Proof.context -> unit
    13 
    13 
    14   type quotients = {quot_thm: thm, pcrel_def: thm option}
    14   type pcrel_info = {pcrel_def: thm, pcr_cr_eq: thm}
       
    15   type quotients = {quot_thm: thm, pcrel_info: pcrel_info option}
    15   val transform_quotients: morphism -> quotients -> quotients
    16   val transform_quotients: morphism -> quotients -> quotients
    16   val lookup_quotients: Proof.context -> string -> quotients option
    17   val lookup_quotients: Proof.context -> string -> quotients option
    17   val lookup_quotients_global: theory -> string -> quotients option
    18   val lookup_quotients_global: theory -> string -> quotients option
    18   val update_quotients: string -> quotients -> Context.generic -> Context.generic
    19   val update_quotients: string -> quotients -> Context.generic -> Context.generic
    19   val dest_quotients: Proof.context -> quotients list
    20   val dest_quotients: Proof.context -> quotients list
    22   val get_invariant_commute_rules: Proof.context -> thm list
    23   val get_invariant_commute_rules: Proof.context -> thm list
    23   
    24   
    24   val get_reflexivity_rules: Proof.context -> thm list
    25   val get_reflexivity_rules: Proof.context -> thm list
    25   val add_reflexivity_rule_attribute: attribute
    26   val add_reflexivity_rule_attribute: attribute
    26   val add_reflexivity_rule_attrib: Attrib.src
    27   val add_reflexivity_rule_attrib: Attrib.src
       
    28 
       
    29   type relator_distr_data = {pos_mono_rule: thm, neg_mono_rule: thm, 
       
    30     pos_distr_rules: thm list, neg_distr_rules: thm list}
       
    31   val lookup_relator_distr_data: Proof.context -> string -> relator_distr_data option
       
    32   val lookup_relator_distr_data_global: theory -> string -> relator_distr_data option
    27 
    33 
    28   val setup: theory -> theory
    34   val setup: theory -> theory
    29 end;
    35 end;
    30 
    36 
    31 structure Lifting_Info: LIFTING_INFO =
    37 structure Lifting_Info: LIFTING_INFO =
   116     |> Pretty.big_list "maps for type constructors:"
   122     |> Pretty.big_list "maps for type constructors:"
   117     |> Pretty.writeln
   123     |> Pretty.writeln
   118   end
   124   end
   119 
   125 
   120 (* info about quotient types *)
   126 (* info about quotient types *)
   121 type quotients = {quot_thm: thm, pcrel_def: thm option}
   127 type pcrel_info = {pcrel_def: thm, pcr_cr_eq: thm}
       
   128 type quotients = {quot_thm: thm, pcrel_info: pcrel_info option}
   122 
   129 
   123 structure Quotients = Generic_Data
   130 structure Quotients = Generic_Data
   124 (
   131 (
   125   type T = quotients Symtab.table
   132   type T = quotients Symtab.table
   126   val empty = Symtab.empty
   133   val empty = Symtab.empty
   127   val extend = I
   134   val extend = I
   128   fun merge data = Symtab.merge (K true) data
   135   fun merge data = Symtab.merge (K true) data
   129 )
   136 )
   130 
   137 
   131 fun transform_quotients phi {quot_thm, pcrel_def} =
   138 fun transform_pcrel_info phi {pcrel_def, pcr_cr_eq} =
   132   {quot_thm = Morphism.thm phi quot_thm, pcrel_def = Option.map (Morphism.thm phi) pcrel_def}
   139   {pcrel_def = Morphism.thm phi pcrel_def, pcr_cr_eq = Morphism.thm phi pcr_cr_eq}
       
   140 
       
   141 fun transform_quotients phi {quot_thm, pcrel_info} =
       
   142   {quot_thm = Morphism.thm phi quot_thm, pcrel_info = Option.map (transform_pcrel_info phi) pcrel_info}
   133 
   143 
   134 val lookup_quotients = Symtab.lookup o Quotients.get o Context.Proof
   144 val lookup_quotients = Symtab.lookup o Quotients.get o Context.Proof
   135 val lookup_quotients_global = Symtab.lookup o Quotients.get o Context.Theory
   145 val lookup_quotients_global = Symtab.lookup o Quotients.get o Context.Theory
   136 
   146 
   137 fun update_quotients str qinfo = Quotients.map (Symtab.update (str, qinfo))
   147 fun update_quotients str qinfo = Quotients.map (Symtab.update (str, qinfo))
   139 fun delete_quotients quot_thm ctxt =
   149 fun delete_quotients quot_thm ctxt =
   140   let
   150   let
   141     val (_, qtyp) = quot_thm_rty_qty quot_thm
   151     val (_, qtyp) = quot_thm_rty_qty quot_thm
   142     val qty_full_name = (fst o dest_Type) qtyp
   152     val qty_full_name = (fst o dest_Type) qtyp
   143     val symtab = Quotients.get ctxt
   153     val symtab = Quotients.get ctxt
   144     val maybe_stored_quot_thm = Symtab.lookup symtab qty_full_name
   154     val opt_stored_quot_thm = Symtab.lookup symtab qty_full_name
   145   in
   155   in
   146     case maybe_stored_quot_thm of
   156     case opt_stored_quot_thm of
   147       SOME data => 
   157       SOME data => 
   148         if Thm.eq_thm_prop (#quot_thm data, quot_thm) then
   158         if Thm.eq_thm_prop (#quot_thm data, quot_thm) then
   149           Quotients.map (Symtab.delete qty_full_name) ctxt
   159           Quotients.map (Symtab.delete qty_full_name) ctxt
   150         else
   160         else
   151           ctxt
   161           ctxt
   155 fun dest_quotients ctxt =  (* FIXME slightly expensive way to retrieve data *)
   165 fun dest_quotients ctxt =  (* FIXME slightly expensive way to retrieve data *)
   156   map snd (Symtab.dest (Quotients.get (Context.Proof ctxt)))
   166   map snd (Symtab.dest (Quotients.get (Context.Proof ctxt)))
   157 
   167 
   158 fun print_quotients ctxt =
   168 fun print_quotients ctxt =
   159   let
   169   let
   160     fun prt_quot (qty_name, {quot_thm, pcrel_def}) =
   170     fun prt_quot (qty_name, {quot_thm, pcrel_info}) =
   161       Pretty.block (separate (Pretty.brk 2)
   171       Pretty.block (separate (Pretty.brk 2)
   162        [Pretty.str "type:", 
   172        [Pretty.str "type:", 
   163         Pretty.str qty_name,
   173         Pretty.str qty_name,
   164         Pretty.str "quot. thm:",
   174         Pretty.str "quot. thm:",
   165         Syntax.pretty_term ctxt (prop_of quot_thm),
   175         Syntax.pretty_term ctxt (prop_of quot_thm),
   166         Pretty.str "pcrel_def thm:",
   176         Pretty.str "pcrel_def thm:",
   167         option_fold (Pretty.str "-") ((Syntax.pretty_term ctxt) o prop_of) pcrel_def])
   177         option_fold (Pretty.str "-") ((Syntax.pretty_term ctxt) o prop_of o #pcrel_def) pcrel_info,
       
   178         Pretty.str "pcr_cr_eq thm:",
       
   179         option_fold (Pretty.str "-") ((Syntax.pretty_term ctxt) o prop_of o #pcr_cr_eq) pcrel_info])
   168   in
   180   in
   169     map prt_quot (Symtab.dest (Quotients.get (Context.Proof ctxt)))
   181     map prt_quot (Symtab.dest (Quotients.get (Context.Proof ctxt)))
   170     |> Pretty.big_list "quotients:"
   182     |> Pretty.big_list "quotients:"
   171     |> Pretty.writeln
   183     |> Pretty.writeln
   172   end
   184   end
   191 
   203 
   192 val get_reflexivity_rules = Reflp_Preserve.get
   204 val get_reflexivity_rules = Reflp_Preserve.get
   193 val add_reflexivity_rule_attribute = Reflp_Preserve.add
   205 val add_reflexivity_rule_attribute = Reflp_Preserve.add
   194 val add_reflexivity_rule_attrib = Attrib.internal (K add_reflexivity_rule_attribute)
   206 val add_reflexivity_rule_attrib = Attrib.internal (K add_reflexivity_rule_attribute)
   195 
   207 
       
   208 (* info about relator distributivity theorems *)
       
   209 type relator_distr_data = {pos_mono_rule: thm, neg_mono_rule: thm, 
       
   210   pos_distr_rules: thm list, neg_distr_rules: thm list}
       
   211 
       
   212 fun map_relator_distr_data f1 f2 f3 f4
       
   213   {pos_mono_rule, neg_mono_rule, pos_distr_rules, neg_distr_rules} =
       
   214   {pos_mono_rule   = f1 pos_mono_rule, 
       
   215    neg_mono_rule   = f2 neg_mono_rule,
       
   216    pos_distr_rules = f3 pos_distr_rules, 
       
   217    neg_distr_rules = f4 neg_distr_rules}
       
   218 
       
   219 fun map_pos_mono_rule f = map_relator_distr_data f I I I
       
   220 fun map_neg_mono_rule f = map_relator_distr_data I f I I
       
   221 fun map_pos_distr_rules f = map_relator_distr_data I I f I 
       
   222 fun map_neg_distr_rules f = map_relator_distr_data I I I f
       
   223 
       
   224 structure Relator_Distr = Generic_Data
       
   225 (
       
   226   type T = relator_distr_data Symtab.table
       
   227   val empty = Symtab.empty
       
   228   val extend = I
       
   229   fun merge data = Symtab.merge (K true) data
       
   230 );
       
   231 
       
   232 fun introduce_polarities rule =
       
   233   let
       
   234     val dest_less_eq = HOLogic.dest_bin @{const_name "less_eq"} dummyT
       
   235     val prems_pairs = map (dest_less_eq o HOLogic.dest_Trueprop) (prems_of rule)
       
   236     val equal_prems = filter op= prems_pairs
       
   237     val _ = if null equal_prems then () 
       
   238       else error "The rule contains reflexive assumptions."
       
   239     val concl_pairs = rule 
       
   240       |> concl_of
       
   241       |> HOLogic.dest_Trueprop
       
   242       |> dest_less_eq
       
   243       |> pairself (snd o strip_comb)
       
   244       |> op~~
       
   245       |> filter_out op=
       
   246     
       
   247     val _ = if has_duplicates op= concl_pairs 
       
   248       then error "The rule contains duplicated variables in the conlusion." else ()
       
   249 
       
   250     fun mem a l = member op= l a
       
   251 
       
   252     fun rewrite_prem prem_pair = 
       
   253       if mem prem_pair concl_pairs 
       
   254       then HOLogic.Trueprop_conv (Conv.rewr_conv (Thm.symmetric @{thm POS_def}))
       
   255       else if mem (swap prem_pair) concl_pairs 
       
   256         then HOLogic.Trueprop_conv (Conv.rewr_conv (Thm.symmetric @{thm NEG_def}))
       
   257       else error "The rule contains a non-relevant assumption."
       
   258     
       
   259     fun rewrite_prems [] = Conv.all_conv
       
   260       | rewrite_prems (x::xs) = Conv.implies_conv (rewrite_prem x) (rewrite_prems xs)
       
   261     
       
   262     val rewrite_prems_conv = rewrite_prems prems_pairs
       
   263     val rewrite_concl_conv = 
       
   264       Conv.concl_conv ~1 (HOLogic.Trueprop_conv (Conv.rewr_conv (Thm.symmetric @{thm POS_def})))
       
   265   in
       
   266     (Conv.fconv_rule (rewrite_prems_conv then_conv rewrite_concl_conv)) rule
       
   267   end
       
   268   handle 
       
   269     TERM _ => error "The rule has a wrong format."
       
   270     | CTERM _ => error "The rule has a wrong format."
       
   271 
       
   272 fun negate_mono_rule mono_rule = 
       
   273   let
       
   274     val rewr_conv = HOLogic.Trueprop_conv (Conv.rewrs_conv [@{thm POS_NEG}, @{thm NEG_POS}])
       
   275   in
       
   276     Conv.fconv_rule (Conv.prems_conv ~1 rewr_conv then_conv Conv.concl_conv ~1 rewr_conv) mono_rule
       
   277   end;
       
   278 
       
   279 fun add_mono_rule mono_rule ctxt = 
       
   280   let
       
   281     val mono_rule = introduce_polarities mono_rule
       
   282     val mono_ruleT_name = (fst o dest_Type o fst o relation_types o fst o relation_types o snd o 
       
   283       dest_Const o head_of o HOLogic.dest_Trueprop o concl_of) mono_rule
       
   284     val _ = if Symtab.defined (Relator_Distr.get ctxt) mono_ruleT_name 
       
   285       then error ("Monotocity rule for type " ^ quote mono_ruleT_name ^ " is already_defined.")
       
   286       else ()
       
   287     val neg_mono_rule = negate_mono_rule mono_rule
       
   288     val relator_distr_data = {pos_mono_rule = mono_rule, neg_mono_rule = neg_mono_rule, 
       
   289       pos_distr_rules = [], neg_distr_rules = []}
       
   290   in
       
   291     Relator_Distr.map (Symtab.update (mono_ruleT_name, relator_distr_data)) ctxt
       
   292   end;
       
   293 
       
   294 local 
       
   295   fun add_distr_rule update_entry distr_rule ctxt =
       
   296     let
       
   297       val distr_ruleT_name = (fst o dest_Type o fst o relation_types o fst o relation_types o snd o 
       
   298         dest_Const o head_of o HOLogic.dest_Trueprop o concl_of) distr_rule
       
   299     in
       
   300       if Symtab.defined (Relator_Distr.get ctxt) distr_ruleT_name then 
       
   301         Relator_Distr.map (Symtab.map_entry distr_ruleT_name (update_entry distr_rule)) ctxt
       
   302       else error "The monoticity rule is not defined."
       
   303     end
       
   304 
       
   305     fun rewrite_concl_conv thm ctm = 
       
   306       Conv.concl_conv ~1 (HOLogic.Trueprop_conv (Conv.rewr_conv (Thm.symmetric thm))) ctm
       
   307       handle CTERM _ => error "The rule has a wrong format."
       
   308 
       
   309 in
       
   310   fun add_pos_distr_rule distr_rule ctxt = 
       
   311     let
       
   312       val distr_rule = Conv.fconv_rule (rewrite_concl_conv @{thm POS_def}) distr_rule
       
   313       fun update_entry distr_rule data = 
       
   314         map_pos_distr_rules (cons (@{thm POS_trans} OF [distr_rule, #pos_mono_rule data])) data
       
   315     in
       
   316       add_distr_rule update_entry distr_rule ctxt
       
   317     end
       
   318     handle THM _ => error "Combining of the distr. rule and the monotonicity rule together has failed."
       
   319 
       
   320   
       
   321   fun add_neg_distr_rule distr_rule ctxt = 
       
   322     let
       
   323       val distr_rule = Conv.fconv_rule (rewrite_concl_conv @{thm NEG_def}) distr_rule
       
   324       fun update_entry distr_rule data = 
       
   325         map_neg_distr_rules (cons (@{thm NEG_trans} OF [distr_rule, #neg_mono_rule data])) data
       
   326     in
       
   327       add_distr_rule update_entry distr_rule ctxt
       
   328     end
       
   329     handle THM _ => error "Combining of the distr. rule and the monotonicity rule together has failed."
       
   330 end
       
   331 
       
   332 local 
       
   333   val eq_refl2 = sym RS @{thm eq_refl}
       
   334 in
       
   335   fun add_eq_distr_rule distr_rule ctxt =
       
   336     let 
       
   337       val pos_distr_rule = @{thm eq_refl} OF [distr_rule]
       
   338       val neg_distr_rule = eq_refl2 OF [distr_rule]
       
   339     in
       
   340       ctxt 
       
   341       |> add_pos_distr_rule pos_distr_rule
       
   342       |> add_neg_distr_rule neg_distr_rule
       
   343     end
       
   344 end;
       
   345 
       
   346 local
       
   347   fun sanity_check rule =
       
   348     let
       
   349       val assms = map (perhaps (try HOLogic.dest_Trueprop)) (prems_of rule)
       
   350       val concl = (perhaps (try HOLogic.dest_Trueprop)) (concl_of rule);
       
   351       val (lhs, rhs) = case concl of
       
   352         Const ("Orderings.ord_class.less_eq", _) $ (lhs as Const ("Relation.relcompp",_) $ _ $ _) $ rhs => 
       
   353           (lhs, rhs)
       
   354         | Const ("Orderings.ord_class.less_eq", _) $ rhs $ (lhs as Const ("Relation.relcompp",_) $ _ $ _) => 
       
   355           (lhs, rhs)
       
   356         | Const ("HOL.eq", _) $ (lhs as Const ("Relation.relcompp",_) $ _ $ _) $ rhs => (lhs, rhs)
       
   357         | _ => error "The rule has a wrong format."
       
   358       
       
   359       val lhs_vars = Term.add_vars lhs []
       
   360       val rhs_vars = Term.add_vars rhs []
       
   361       val assms_vars = fold Term.add_vars assms [];
       
   362       val _ = if has_duplicates op= lhs_vars then error "Left-hand side has variable duplicates" else ()
       
   363       val _ = if subset op= (rhs_vars, lhs_vars) then () 
       
   364         else error "Extra variables in the right-hand side of the rule"
       
   365       val _ = if subset op= (assms_vars, lhs_vars) then () 
       
   366         else error "Extra variables in the assumptions of the rule"
       
   367       val rhs_args = (snd o strip_comb) rhs;
       
   368       fun check_comp t = case t of 
       
   369         Const ("Relation.relcompp", _) $ Var (_, _) $ Var (_,_) => ()
       
   370         | _ => error "There is an argument on the rhs that is not a composition."
       
   371       val _ = map check_comp rhs_args
       
   372     in
       
   373       ()
       
   374     end
       
   375 in
       
   376 
       
   377   fun add_distr_rule distr_rule ctxt = 
       
   378     let
       
   379       val _ = sanity_check distr_rule
       
   380       val concl = (perhaps (try HOLogic.dest_Trueprop)) (concl_of distr_rule)
       
   381     in
       
   382       case concl of
       
   383         Const ("Orderings.ord_class.less_eq", _) $ (Const ("Relation.relcompp",_) $ _ $ _) $ _ => 
       
   384           add_pos_distr_rule distr_rule ctxt
       
   385         | Const ("Orderings.ord_class.less_eq", _) $ _ $ (Const ("Relation.relcompp",_) $ _ $ _) => 
       
   386           add_neg_distr_rule distr_rule ctxt
       
   387         | Const ("HOL.eq", _) $ (Const ("Relation.relcompp",_) $ _ $ _) $ _ =>
       
   388           add_eq_distr_rule distr_rule ctxt
       
   389     end
       
   390 end
       
   391 
       
   392 fun get_distr_rules_raw ctxt = Symtab.fold 
       
   393   (fn (_, {pos_distr_rules, neg_distr_rules, ...}) => fn rules => pos_distr_rules @ neg_distr_rules @ rules) 
       
   394     (Relator_Distr.get ctxt) []
       
   395 
       
   396 fun get_mono_rules_raw ctxt = Symtab.fold 
       
   397   (fn (_, {pos_mono_rule, neg_mono_rule, ...}) => fn rules => [pos_mono_rule, neg_mono_rule] @ rules) 
       
   398     (Relator_Distr.get ctxt) []
       
   399 
       
   400 val lookup_relator_distr_data = Symtab.lookup o Relator_Distr.get o Context.Proof
       
   401 val lookup_relator_distr_data_global = Symtab.lookup o Relator_Distr.get o Context.Theory
       
   402 
       
   403 val relator_distr_attribute_setup =
       
   404   Attrib.setup @{binding relator_mono} (Scan.succeed (Thm.declaration_attribute add_mono_rule))
       
   405     "declaration of relator's monoticity"
       
   406   #> Attrib.setup @{binding relator_distr} (Scan.succeed (Thm.declaration_attribute add_distr_rule))
       
   407     "declaration of relator's distributivity over OO"
       
   408   #> Global_Theory.add_thms_dynamic
       
   409      (@{binding relator_distr_raw}, get_distr_rules_raw)
       
   410   #> Global_Theory.add_thms_dynamic
       
   411      (@{binding relator_mono_raw}, get_mono_rules_raw)
       
   412 
   196 (* theory setup *)
   413 (* theory setup *)
   197 
   414 
   198 val setup =
   415 val setup =
   199   quot_map_attribute_setup
   416   quot_map_attribute_setup
   200   #> quot_del_attribute_setup
   417   #> quot_del_attribute_setup
   201   #> Invariant_Commute.setup
   418   #> Invariant_Commute.setup
   202   #> Reflp_Preserve.setup
   419   #> Reflp_Preserve.setup
       
   420   #> relator_distr_attribute_setup
   203 
   421 
   204 (* outer syntax commands *)
   422 (* outer syntax commands *)
   205 
   423 
   206 val _ =
   424 val _ =
   207   Outer_Syntax.improper_command @{command_spec "print_quotmaps"} "print quotient map functions"
   425   Outer_Syntax.improper_command @{command_spec "print_quotmaps"} "print quotient map functions"