Quot/quotient_term.ML
changeset 854 5961edda27d7
parent 836 c2501b2b262a
child 856 433f7c17255f
equal deleted inserted replaced
843:2480fb2a5e4e 854:5961edda27d7
    22 
    22 
    23 open Quotient_Info;
    23 open Quotient_Info;
    24 
    24 
    25 exception LIFT_MATCH of string
    25 exception LIFT_MATCH of string
    26 
    26 
    27 (* simplifies a term according to the id_rules *)
    27 
    28 fun id_simplify ctxt trm =
    28 
    29 let
    29 (*** Aggregate Rep/Abs Function ***)
    30   val thy = ProofContext.theory_of ctxt 
    30 
    31   val id_thms = id_simps_get ctxt
    31 
    32 in
    32 (* The flag repF is for types in negative position; absF is for types 
    33   MetaSimplifier.rewrite_term thy id_thms [] trm
    33    in positive position. Because of this, function types need to be   
    34 end		
    34    treated specially, since there the polarity changes.               
    35  
    35 *)
    36 (******************************)
       
    37 (* Aggregate Rep/Abs Function *)
       
    38 (******************************)
       
    39 
       
    40 (* The flag repF is for types in negative position; absF is for types *)
       
    41 (* in positive position. Because of this, function types need to be   *)
       
    42 (* treated specially, since there the polarity changes.               *)
       
    43 
    36 
    44 datatype flag = absF | repF
    37 datatype flag = absF | repF
    45 
    38 
    46 fun negF absF = repF
    39 fun negF absF = repF
    47   | negF repF = absF
    40   | negF repF = absF
       
    41 
       
    42 fun is_identity (Const (@{const_name "id"}, _)) = true
       
    43   | is_identity _ = false
    48 
    44 
    49 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty)
    45 fun mk_identity ty = Const (@{const_name "id"}, ty --> ty)
    50 
    46 
    51 fun mk_fun_compose flag (trm1, trm2) = 
    47 fun mk_fun_compose flag (trm1, trm2) = 
    52   case flag of
    48   case flag of
    63 end
    59 end
    64 
    60 
    65 (* makes a Free out of a TVar *)
    61 (* makes a Free out of a TVar *)
    66 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT)
    62 fun mk_Free (TVar ((x, i), _)) = Free (unprefix "'" x ^ string_of_int i, dummyT)
    67 
    63 
    68 (* produces an aggregate map function for the       *)
    64 (* produces an aggregate map function for the       
    69 (* rty-part of a quotient definition; abstracts     *)
    65    rty-part of a quotient definition; abstracts     
    70 (* over all variables listed in vs (these variables *)
    66    over all variables listed in vs (these variables 
    71 (* correspond to the type variables in rty)         *)        
    67    correspond to the type variables in rty)         
    72 (*                                                  *)
    68                                                     
    73 (* for example for: (?'a list * ?'b)                *)
    69    for example for: (?'a list * ?'b)                
    74 (* it produces:     %a b. prod_map (map a) b        *)
    70    it produces:     %a b. prod_map (map a) b 
       
    71 *)
    75 fun mk_mapfun ctxt vs rty =
    72 fun mk_mapfun ctxt vs rty =
    76 let
    73 let
    77   val vs' = map (mk_Free) vs
    74   val vs' = map (mk_Free) vs
    78 
    75 
    79   fun mk_mapfun_aux rty =
    76   fun mk_mapfun_aux rty =
    84     | _ => raise LIFT_MATCH ("mk_mapfun (default)")
    81     | _ => raise LIFT_MATCH ("mk_mapfun (default)")
    85 in
    82 in
    86   fold_rev Term.lambda vs' (mk_mapfun_aux rty)
    83   fold_rev Term.lambda vs' (mk_mapfun_aux rty)
    87 end
    84 end
    88 
    85 
    89 (* looks up the (varified) rty and qty for *)
    86 (* looks up the (varified) rty and qty for 
    90 (* a quotient definition                   *)
    87    a quotient definition                   
       
    88 *)
    91 fun get_rty_qty ctxt s =
    89 fun get_rty_qty ctxt s =
    92 let
    90 let
    93   val thy = ProofContext.theory_of ctxt
    91   val thy = ProofContext.theory_of ctxt
    94   val exc = LIFT_MATCH ("No quotient type " ^ (quote s) ^ " found.")
    92   val exc = LIFT_MATCH ("No quotient type " ^ (quote s) ^ " found.")
    95   val qdata = (quotdata_lookup thy s) handle NotFound => raise exc
    93   val qdata = (quotdata_lookup thy s) handle NotFound => raise exc
    96 in
    94 in
    97   (#rtyp qdata, #qtyp qdata)
    95   (#rtyp qdata, #qtyp qdata)
    98 end
    96 end
    99 
    97 
   100 (* takes two type-environments and looks    *)
    98 (* takes two type-environments and looks    
   101 (* up in both of them the variable v, which *)
    99    up in both of them the variable v, which 
   102 (* must be listed in the environment        *)
   100    must be listed in the environment        
       
   101 *)
   103 fun double_lookup rtyenv qtyenv v =
   102 fun double_lookup rtyenv qtyenv v =
   104 let
   103 let
   105   val v' = fst (dest_TVar v)
   104   val v' = fst (dest_TVar v)
   106 in
   105 in
   107   (snd (the (Vartab.lookup rtyenv v')), snd (the (Vartab.lookup qtyenv v')))
   106   (snd (the (Vartab.lookup rtyenv v')), snd (the (Vartab.lookup qtyenv v')))
   134 in
   133 in
   135   raise LIFT_MATCH (space_implode " " 
   134   raise LIFT_MATCH (space_implode " " 
   136     ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   135     ["absrep_fun (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   137 end
   136 end
   138 
   137 
   139 (* produces an aggregate absrep function                           *)
   138 
   140 (*                                                                 *)
   139 (** generation of an aggregate absrep function **)
   141 (* - In case of equal types we just return the identity.           *)
   140 
   142 (*                                                                 *)
   141 (* - In case of equal types we just return the identity.           
   143 (* - In case of function types and TFrees, we recurse, taking in   *) 
   142      
   144 (*   the first case the polarity change into account.              *)
   143    - In case of TFrees we also return the identity.
   145 (*                                                                 *)
   144                                                              
   146 (* - If the type constructors are equal, we recurse for the        *)
   145    - In case of function types we recurse taking   
   147 (*   arguments and build the appropriate map function.             *)
   146      the polarity change into account.              
   148 (*                                                                 *)
   147                                                                    
   149 (* - If the type constructors are unequal, there must be an        *)
   148    - If the type constructors are equal, we recurse for the        
   150 (*   instance of quotient types:                                   *)
   149      arguments and build the appropriate map function.             
   151 (*     - we first look up the corresponding rty_pat and qty_pat    *)
   150                                                                    
   152 (*       from the quotient definition; the arguments of qty_pat    *)
   151    - If the type constructors are unequal, there must be an        
   153 (*       must be some distinct TVars                               *)  
   152      instance of quotient types:         
   154 (*     - we then match the rty_pat with rty and qty_pat with qty;  *)
   153                           
   155 (*       if matching fails the types do not match                  *)
   154        - we first look up the corresponding rty_pat and qty_pat    
   156 (*     - the matching produces two environments; we look up the    *)
   155          from the quotient definition; the arguments of qty_pat    
   157 (*       assignments for the qty_pat variables and recurse on the  *)
   156          must be some distinct TVars                               
   158 (*       assignments                                               *)
   157        - we then match the rty_pat with rty and qty_pat with qty;  
   159 (*     - we prefix the aggregate map function for the rty_pat,     *)
   158          if matching fails the types do not correspond -> error                  
   160 (*       which is an abstraction over all type variables           *)
   159        - the matching produces two environments; we look up the    
   161 (*     - finally we compose the result with the appropriate        *)
   160          assignments for the qty_pat variables and recurse on the  
   162 (*       absrep function                                           *)    
   161          assignments                                               
   163 (*                                                                 *)
   162        - we prefix the aggregate map function for the rty_pat,     
   164 (*   The composition is necessary for types like                   *)
   163          which is an abstraction over all type variables           
   165 (*                                                                 *)
   164        - finally we compose the result with the appropriate        
   166 (*      ('a list) list / ('a foo) foo                              *)
   165          absrep function in case at least one argument produced
   167 (*                                                                 *)
   166          a non-identity function /
   168 (*   The matching is necessary for types like                      *)
   167          otherwise we just return the appropriate absrep
   169 (*                                                                 *)
   168          function                                          
   170 (*      ('a * 'a) list / 'a bar                                    *)  
   169                                                                    
       
   170      The composition is necessary for types like                   
       
   171                                                                  
       
   172         ('a list) list / ('a foo) foo                              
       
   173                                                                  
       
   174      The matching is necessary for types like                      
       
   175                                                                  
       
   176         ('a * 'a) list / 'a bar   
       
   177 
       
   178      The test is necessary in order to eliminate superflous
       
   179      identity maps.                                 
       
   180 *)  
   171 
   181 
   172 fun absrep_fun flag ctxt (rty, qty) =
   182 fun absrep_fun flag ctxt (rty, qty) =
   173   if rty = qty  
   183   if rty = qty  
   174   then mk_identity rty
   184   then mk_identity rty
   175   else
   185   else
   192         else
   202         else
   193            let
   203            let
   194              val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   204              val (rty_pat, qty_pat as Type (_, vs)) = get_rty_qty ctxt s'
   195              val rtyenv = match ctxt absrep_match_err rty_pat rty
   205              val rtyenv = match ctxt absrep_match_err rty_pat rty
   196              val qtyenv = match ctxt absrep_match_err qty_pat qty
   206              val qtyenv = match ctxt absrep_match_err qty_pat qty
   197              val args_aux = map (double_lookup rtyenv qtyenv) vs 
   207              val args_aux = map (double_lookup rtyenv qtyenv) vs
   198              val args = map (absrep_fun flag ctxt) args_aux
   208              val args = map (absrep_fun flag ctxt) args_aux
   199              val map_fun = mk_mapfun ctxt vs rty_pat       
   209              val map_fun = mk_mapfun ctxt vs rty_pat       
   200              val result = list_comb (map_fun, args) 
   210              val result = list_comb (map_fun, args) 
   201            in
   211            in
   202              mk_fun_compose flag (absrep_const flag ctxt s', result)
   212              if forall is_identity args
       
   213              then absrep_const flag ctxt s'
       
   214              else mk_fun_compose flag (absrep_const flag ctxt s', result)
   203            end
   215            end
   204     | (TFree x, TFree x') =>
   216     | (TFree x, TFree x') =>
   205         if x = x'
   217         if x = x'
   206         then mk_identity rty
   218         then mk_identity rty
   207         else raise (LIFT_MATCH "absrep_fun (frees)")
   219         else raise (LIFT_MATCH "absrep_fun (frees)")
   209     | _ => raise (LIFT_MATCH "absrep_fun (default)")
   221     | _ => raise (LIFT_MATCH "absrep_fun (default)")
   210 
   222 
   211 fun absrep_fun_chk flag ctxt (rty, qty) =
   223 fun absrep_fun_chk flag ctxt (rty, qty) =
   212   absrep_fun flag ctxt (rty, qty)
   224   absrep_fun flag ctxt (rty, qty)
   213   |> Syntax.check_term ctxt
   225   |> Syntax.check_term ctxt
   214   |> id_simplify ctxt
   226 
   215 
   227 
   216 (**********************************)
   228 
   217 (* Aggregate Equivalence Relation *)
   229 
   218 (**********************************)
   230 (*** Aggregate Equivalence Relation ***)
       
   231 
       
   232 
       
   233 (* works very similar to the absrep generation,
       
   234    except there is no need for polarities
       
   235 *)
   219 
   236 
   220 (* instantiates TVars so that the term is of type ty *)
   237 (* instantiates TVars so that the term is of type ty *)
   221 fun force_typ ctxt trm ty =
   238 fun force_typ ctxt trm ty =
   222 let
   239 let
   223   val thy = ProofContext.theory_of ctxt 
   240   val thy = ProofContext.theory_of ctxt 
   225   val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty
   242   val ty_inst = Sign.typ_match thy (trm_ty, ty) Vartab.empty
   226 in
   243 in
   227   map_types (Envir.subst_type ty_inst) trm
   244   map_types (Envir.subst_type ty_inst) trm
   228 end
   245 end
   229 
   246 
       
   247 fun is_eq (Const (@{const_name "op ="}, _)) = true
       
   248   | is_eq _ = false
       
   249 
   230 fun mk_rel_compose (trm1, trm2) =
   250 fun mk_rel_compose (trm1, trm2) =
   231   Const (@{const_name "pred_comp"}, dummyT) $ trm1 $
   251   Const (@{const_name "rel_conj"}, dummyT) $ trm1 $ trm2
   232    (Const (@{const_name "pred_comp"}, dummyT) $ trm2 $ trm1)
       
   233 
   252 
   234 fun get_relmap ctxt s =
   253 fun get_relmap ctxt s =
   235 let
   254 let
   236   val thy = ProofContext.theory_of ctxt
   255   val thy = ProofContext.theory_of ctxt
   237   val exc =  LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")") 
   256   val exc =  LIFT_MATCH ("get_relmap (no relation map function found for type " ^ s ^ ")") 
   269 in
   288 in
   270   raise LIFT_MATCH (space_implode " " 
   289   raise LIFT_MATCH (space_implode " " 
   271     ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   290     ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
   272 end
   291 end
   273 
   292 
   274 (* builds the aggregate equivalence relation *)
   293 (* builds the aggregate equivalence relation 
   275 (* that will be the argument of Respects     *)
   294    that will be the argument of Respects     
       
   295 *)
   276 fun equiv_relation ctxt (rty, qty) =
   296 fun equiv_relation ctxt (rty, qty) =
   277   if rty = qty
   297   if rty = qty
   278   then HOLogic.eq_const rty
   298   then HOLogic.eq_const rty
   279   else
   299   else
   280     case (rty, qty) of
   300     case (rty, qty) of
   296            val rel_map = mk_relmap ctxt vs rty_pat       
   316            val rel_map = mk_relmap ctxt vs rty_pat       
   297            val result = list_comb (rel_map, args)
   317            val result = list_comb (rel_map, args)
   298            val eqv_rel = get_equiv_rel ctxt s'
   318            val eqv_rel = get_equiv_rel ctxt s'
   299            val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool})
   319            val eqv_rel' = force_typ ctxt eqv_rel ([rty, rty] ---> @{typ bool})
   300          in
   320          in
   301            mk_rel_compose (result, eqv_rel')
   321            if forall is_eq args 
       
   322            then eqv_rel'
       
   323            else mk_rel_compose (result, eqv_rel')
   302          end
   324          end
   303       | _ => HOLogic.eq_const rty
   325       | _ => HOLogic.eq_const rty
   304 
   326 
   305 fun equiv_relation_chk ctxt (rty, qty) =
   327 fun equiv_relation_chk ctxt (rty, qty) =
   306   equiv_relation ctxt (rty, qty)
   328   equiv_relation ctxt (rty, qty)
   307   |> Syntax.check_term ctxt
   329   |> Syntax.check_term ctxt
   308   |> id_simplify ctxt
   330 
   309 
   331 
   310 
   332 
   311 (******************)
   333 (*** Regularization ***)
   312 (* Regularization *)
       
   313 (******************)
       
   314 
   334 
   315 (* Regularizing an rtrm means:
   335 (* Regularizing an rtrm means:
   316  
   336  
   317  - Quantifiers over types that need lifting are replaced 
   337  - Quantifiers over types that need lifting are replaced 
   318    by bounded quantifiers, for example:
   338    by bounded quantifiers, for example:
   342 val mk_babs = Const (@{const_name Babs}, dummyT)
   362 val mk_babs = Const (@{const_name Babs}, dummyT)
   343 val mk_ball = Const (@{const_name Ball}, dummyT)
   363 val mk_ball = Const (@{const_name Ball}, dummyT)
   344 val mk_bex  = Const (@{const_name Bex}, dummyT)
   364 val mk_bex  = Const (@{const_name Bex}, dummyT)
   345 val mk_resp = Const (@{const_name Respects}, dummyT)
   365 val mk_resp = Const (@{const_name Respects}, dummyT)
   346 
   366 
   347 (* - applies f to the subterm of an abstraction,   *)
   367 (* - applies f to the subterm of an abstraction, 
   348 (*   otherwise to the given term,                  *)
   368      otherwise to the given term,                
   349 (* - used by regularize, therefore abstracted      *)
   369    - used by regularize, therefore abstracted    
   350 (*   variables do not have to be treated specially *)
   370      variables do not have to be treated specially 
       
   371 *)
   351 fun apply_subt f (trm1, trm2) =
   372 fun apply_subt f (trm1, trm2) =
   352   case (trm1, trm2) of
   373   case (trm1, trm2) of
   353     (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t'))
   374     (Abs (x, T, t), Abs (_ , _, t')) => Abs (x, T, f (t, t'))
   354   | _ => f (trm1, trm2)
   375   | _ => f (trm1, trm2)
   355 
   376 
   356 (* the major type of All and Ex quantifiers *)
   377 (* the major type of All and Ex quantifiers *)
   357 fun qnt_typ ty = domain_type (domain_type ty)  
   378 fun qnt_typ ty = domain_type (domain_type ty)  
   358 
   379 
   359 
   380 (* produces a regularized version of rtrm      
   360 (* produces a regularized version of rtrm       *)
   381 
   361 (*                                              *)
   382    - the result might contain dummyTs           
   362 (* - the result might contain dummyTs           *)
   383 
   363 (*                                              *)
   384    - for regularisation we do not need any      
   364 (* - for regularisation we do not need any      *)
   385      special treatment of bound variables       
   365 (*   special treatment of bound variables       *)
   386 *)
   366 
       
   367 fun regularize_trm ctxt (rtrm, qtrm) =
   387 fun regularize_trm ctxt (rtrm, qtrm) =
   368   case (rtrm, qtrm) of
   388   case (rtrm, qtrm) of
   369     (Abs (x, ty, t), Abs (_, ty', t')) =>
   389     (Abs (x, ty, t), Abs (_, ty', t')) =>
   370        let
   390        let
   371          val subtrm = Abs(x, ty, regularize_trm ctxt (t, t'))
   391          val subtrm = Abs(x, ty, regularize_trm ctxt (t, t'))
   463        end
   483        end
   464 
   484 
   465 fun regularize_trm_chk ctxt (rtrm, qtrm) =
   485 fun regularize_trm_chk ctxt (rtrm, qtrm) =
   466   regularize_trm ctxt (rtrm, qtrm) 
   486   regularize_trm ctxt (rtrm, qtrm) 
   467   |> Syntax.check_term ctxt
   487   |> Syntax.check_term ctxt
   468   |> id_simplify ctxt
       
   469 
   488 
   470 
   489 
   471 (*********************)
   490 (*********************)
   472 (* Rep/Abs Injection *)
   491 (* Rep/Abs Injection *)
   473 (*********************)
   492 (*********************)
   565   | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm
   584   | _ => inj_repabs_err ctxt "injection (default):" rtrm qtrm
   566 
   585 
   567 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) =
   586 fun inj_repabs_trm_chk ctxt (rtrm, qtrm) =
   568   inj_repabs_trm ctxt (rtrm, qtrm) 
   587   inj_repabs_trm ctxt (rtrm, qtrm) 
   569   |> Syntax.check_term ctxt
   588   |> Syntax.check_term ctxt
   570   |> id_simplify ctxt
       
   571 
   589 
   572 end; (* structure *)
   590 end; (* structure *)
   573 
   591 
   574 
   592 
   575 
   593