src/HOL/Nominal/nominal_permeq.ML
author urbanc
Wed Mar 01 18:26:20 2006 +0100 (2006-03-01)
changeset 19169 20a73345dd6e
parent 19163 b61039bf141f
child 19350 2e1c7ca05ee0
permissions -rw-r--r--
fixed a problem where a permutation is not analysed
when the term is of the form

(pi o f) x1...xn

This was the case because the head of this term is the
constant "nominal.perm". Now an applicability predicate
decides the right behaviour of the simproc
berghofe@17870
     1
(* $Id$ *)
berghofe@17870
     2
berghofe@17870
     3
(* METHOD FOR ANALYSING EQUATION INVOLVING PERMUTATION *)
berghofe@17870
     4
berghofe@17870
     5
local
berghofe@17870
     6
urbanc@18012
     7
(* pulls out dynamically a thm via the simpset *)
urbanc@18434
     8
fun dynamic_thms ss name = 
urbanc@18434
     9
    ProofContext.get_thms (Simplifier.the_context ss) (Name name);
urbanc@19139
    10
fun dynamic_thm ss name = 
urbanc@19139
    11
    ProofContext.get_thm (Simplifier.the_context ss) (Name name);
urbanc@18012
    12
urbanc@18012
    13
(* initial simplification step in the tactic *)
urbanc@19139
    14
fun perm_eval_tac ss i =
urbanc@18012
    15
    let
urbanc@19139
    16
        fun perm_eval_simproc sg ss redex =
urbanc@19169
    17
        let 
urbanc@19169
    18
	   
urbanc@19169
    19
           (* the "application" case below is only applicable when the head   *)
urbanc@19169
    20
           (* of f is not a constant  or when it is a permuattion with two or *) 
urbanc@19169
    21
           (* more arguments                                                  *)
urbanc@19169
    22
           fun applicable t = 
urbanc@19169
    23
	       (case (strip_comb t) of
urbanc@19169
    24
		  (Const ("nominal.perm",_),ts) => (length ts) >= 2
urbanc@19169
    25
		| (Const _,_) => false
urbanc@19169
    26
		| _ => true)
urbanc@19169
    27
urbanc@19169
    28
	in
urbanc@19139
    29
        (case redex of 
urbanc@19169
    30
        (* case pi o (f x) == (pi o f) (pi o x)          *)
urbanc@19169
    31
        (* special treatment according to the head of f  *)
urbanc@19144
    32
        (Const("nominal.perm",
urbanc@19169
    33
          Type("fun",[Type("List.list",[Type("*",[Type(n,_),_])]),_])) $ pi $ (f $ x)) => 
urbanc@19169
    34
	   (case (applicable f) of
urbanc@19169
    35
                false => NONE  
urbanc@19163
    36
              | _ => 
urbanc@19163
    37
		let
urbanc@19163
    38
		    val name = Sign.base_name n
urbanc@19163
    39
		    val at_inst     = dynamic_thm ss ("at_"^name^"_inst")
urbanc@19163
    40
		    val pt_inst     = dynamic_thm ss ("pt_"^name^"_inst")  
urbanc@19163
    41
		    val perm_eq_app = thm "nominal.pt_fun_app_eq"	  
urbanc@19163
    42
		in SOME ((at_inst RS (pt_inst RS perm_eq_app)) RS eq_reflection) end)
urbanc@19139
    43
urbanc@19139
    44
        (* case pi o (%x. f x) == (%x. pi o (f ((rev pi)o x))) *)
urbanc@19144
    45
        | (Const("nominal.perm",_) $ pi $ (Abs _)) => 
urbanc@19144
    46
           let 
urbanc@19163
    47
               val perm_fun_def = thm "nominal.perm_fun_def"
urbanc@19139
    48
           in SOME (perm_fun_def) end
urbanc@19139
    49
urbanc@19139
    50
        (* no redex otherwise *) 
urbanc@19169
    51
        | _ => NONE) end
urbanc@19139
    52
urbanc@19139
    53
	val perm_eval =
urbanc@19139
    54
	    Simplifier.simproc (Theory.sign_of (the_context ())) "perm_eval" 
urbanc@19139
    55
	    ["nominal.perm pi x"] perm_eval_simproc;
urbanc@19139
    56
urbanc@18279
    57
        (* these lemmas are created dynamically according to the atom types *) 
urbanc@19163
    58
	val perm_swap     = dynamic_thms ss "perm_swap"
urbanc@19163
    59
	val perm_fresh    = dynamic_thms ss "perm_fresh_fresh"
urbanc@19163
    60
        val perm_bij      = dynamic_thms ss "perm_bij"
urbanc@19163
    61
        val perm_compose' = dynamic_thms ss "perm_compose'"
urbanc@19163
    62
        val perm_pi_simp  = dynamic_thms ss "perm_pi_simp"
urbanc@19139
    63
        val ss' = ss addsimps (perm_swap@perm_fresh@perm_bij@perm_compose'@perm_pi_simp)
urbanc@18012
    64
    in
urbanc@19163
    65
      ("general simplification step", 
urbanc@19163
    66
        FIRST [rtac conjI i, asm_full_simp_tac (ss' addsimprocs [perm_eval]) i])
urbanc@18012
    67
    end;
berghofe@17870
    68
urbanc@18434
    69
(* applies the perm_compose rule - this rule would loop in the simplifier     *)
urbanc@18434
    70
(* in case there are more atom-types we have to check every possible instance *)
urbanc@19139
    71
(* of perm_compose                                                            *)
urbanc@18012
    72
fun apply_perm_compose_tac ss i = 
urbanc@18012
    73
    let
urbanc@18434
    74
	val perm_compose = dynamic_thms ss "perm_compose"; 
urbanc@18434
    75
        val tacs = map (fn thm => (rtac (thm RS trans) i)) perm_compose
urbanc@18012
    76
    in
urbanc@18434
    77
	("analysing permutation compositions on the lhs",FIRST (tacs))
urbanc@18012
    78
    end
urbanc@18012
    79
urbanc@18012
    80
(* applying Stefan's smart congruence tac *)
urbanc@18012
    81
fun apply_cong_tac i = 
urbanc@18012
    82
    ("application of congruence",
urbanc@18012
    83
     (fn st => DatatypeAux.cong_tac  i st handle Subscript => no_tac st));
berghofe@17870
    84
berghofe@17870
    85
(* unfolds the definition of permutations applied to functions *)
urbanc@18012
    86
fun unfold_perm_fun_def_tac i = 
urbanc@18012
    87
    let
urbanc@18012
    88
	val perm_fun_def = thm "nominal.perm_fun_def"
urbanc@18012
    89
    in
urbanc@18012
    90
	("unfolding of permutations on functions", 
urbanc@18012
    91
	 simp_tac (HOL_basic_ss addsimps [perm_fun_def]) i)
berghofe@17870
    92
    end
berghofe@17870
    93
urbanc@18012
    94
(* applies the expand_fun_eq rule to the first goal and strips off all universal quantifiers *)
urbanc@18012
    95
fun expand_fun_eq_tac i =    
urbanc@18012
    96
    ("extensionality expansion of functions",
urbanc@18012
    97
    EVERY [simp_tac (HOL_basic_ss addsimps [expand_fun_eq]) i, REPEAT_DETERM (rtac allI i)]);
berghofe@17870
    98
berghofe@17870
    99
(* debugging *)
berghofe@17870
   100
fun DEBUG_tac (msg,tac) = 
urbanc@19169
   101
    CHANGED (EVERY [tac, print_tac ("after "^msg)]); 
berghofe@17870
   102
fun NO_DEBUG_tac (_,tac) = CHANGED tac; 
berghofe@17870
   103
berghofe@17870
   104
(* Main Tactic *)
urbanc@18012
   105
urbanc@18012
   106
fun perm_simp_tac tactical ss i = 
urbanc@19139
   107
    DETERM (tactical (perm_eval_tac ss i));
urbanc@19139
   108
urbanc@19151
   109
urbanc@19151
   110
(* perm_simp_tac plus additional tactics to decide            *)
urbanc@19151
   111
(* support problems                                           *)
urbanc@19163
   112
(* the "recursion"-depth is set to 10 - this seems sufficient *)
urbanc@19151
   113
fun perm_supports_tac tactical ss n = 
urbanc@19151
   114
    if n=0 then K all_tac
urbanc@19151
   115
    else DETERM o 
urbanc@19151
   116
         (FIRST'[fn i => tactical (perm_eval_tac ss i),
urbanc@19163
   117
                 fn i => tactical (apply_perm_compose_tac ss i),
urbanc@19163
   118
		 fn i => tactical (apply_cong_tac i), 
urbanc@19163
   119
                 fn i => tactical (unfold_perm_fun_def_tac i),
urbanc@19163
   120
		 fn i => tactical (expand_fun_eq_tac i)]
urbanc@19151
   121
         THEN_ALL_NEW (TRY o (perm_supports_tac tactical ss (n-1))));
berghofe@17870
   122
urbanc@19139
   123
(* tactic that first unfolds the support definition          *)
urbanc@19139
   124
(* and strips off the intros, then applies perm_supports_tac *)
urbanc@18012
   125
fun supports_tac tactical ss i =
urbanc@18012
   126
  let 
urbanc@18012
   127
      val supports_def = thm "nominal.op supports_def";
urbanc@18012
   128
      val fresh_def    = thm "nominal.fresh_def";
urbanc@18012
   129
      val fresh_prod   = thm "nominal.fresh_prod";
urbanc@18012
   130
      val simps        = [supports_def,symmetric fresh_def,fresh_prod]
berghofe@17870
   131
  in
urbanc@19151
   132
      EVERY [tactical ("unfolding of supports ", simp_tac (HOL_basic_ss addsimps simps) i),
urbanc@19151
   133
             tactical ("stripping of foralls  ", REPEAT_DETERM (rtac allI i)),
urbanc@19151
   134
             tactical ("geting rid of the imps", rtac impI i),
urbanc@19151
   135
             tactical ("eliminating conjuncts ", REPEAT_DETERM (etac  conjE i)),
urbanc@19151
   136
             tactical ("applying perm_simp    ", perm_supports_tac tactical ss 10 i)]
berghofe@17870
   137
  end;
berghofe@17870
   138
urbanc@19151
   139
urbanc@19151
   140
(* tactic that guesses the finite-support of a goal *)
urbanc@19151
   141
urbanc@19151
   142
fun collect_vars i (Bound j) vs = if j < i then vs else Bound (j - i) ins vs
urbanc@19151
   143
  | collect_vars i (v as Free _) vs = v ins vs
urbanc@19151
   144
  | collect_vars i (v as Var _) vs = v ins vs
urbanc@19151
   145
  | collect_vars i (Const _) vs = vs
urbanc@19151
   146
  | collect_vars i (Abs (_, _, t)) vs = collect_vars (i+1) t vs
urbanc@19151
   147
  | collect_vars i (t $ u) vs = collect_vars i u (collect_vars i t vs);
urbanc@19151
   148
urbanc@19151
   149
val supports_rule = thm "supports_finite";
urbanc@19151
   150
urbanc@19151
   151
fun finite_guess_tac tactical ss i st =
urbanc@19151
   152
    let val goal = List.nth(cprems_of st, i-1)
urbanc@19151
   153
    in
urbanc@19151
   154
      case Logic.strip_assums_concl (term_of goal) of
urbanc@19151
   155
          _ $ (Const ("op :", _) $ (Const ("nominal.supp", T) $ x) $
urbanc@19151
   156
            Const ("Finite_Set.Finites", _)) =>
urbanc@19151
   157
          let
urbanc@19151
   158
            val cert = Thm.cterm_of (sign_of_thm st);
urbanc@19151
   159
            val ps = Logic.strip_params (term_of goal);
urbanc@19151
   160
            val Ts = rev (map snd ps);
urbanc@19151
   161
            val vs = collect_vars 0 x [];
urbanc@19151
   162
            val s = foldr (fn (v, s) =>
urbanc@19151
   163
                HOLogic.pair_const (fastype_of1 (Ts, v)) (fastype_of1 (Ts, s)) $ v $ s)
urbanc@19151
   164
              HOLogic.unit vs;
urbanc@19151
   165
            val s' = list_abs (ps,
urbanc@19151
   166
              Const ("nominal.supp", fastype_of1 (Ts, s) --> body_type T) $ s);
urbanc@19151
   167
            val supports_rule' = Thm.lift_rule goal supports_rule;
urbanc@19151
   168
            val _ $ (_ $ S $ _) =
urbanc@19151
   169
              Logic.strip_assums_concl (hd (prems_of supports_rule'));
urbanc@19151
   170
            val supports_rule'' = Drule.cterm_instantiate
urbanc@19151
   171
              [(cert (head_of S), cert s')] supports_rule'
urbanc@19151
   172
          in
urbanc@19151
   173
            (tactical ("guessing of the right supports-set",
urbanc@19151
   174
                      EVERY [compose_tac (false, supports_rule'', 2) i,
urbanc@19151
   175
                             asm_full_simp_tac ss (i+1),
urbanc@19151
   176
                             supports_tac tactical ss i])) st
urbanc@19151
   177
          end
urbanc@19151
   178
        | _ => Seq.empty
urbanc@19151
   179
    end
urbanc@19151
   180
    handle Subscript => Seq.empty
urbanc@19151
   181
berghofe@17870
   182
in             
berghofe@17870
   183
berghofe@17870
   184
urbanc@18012
   185
fun simp_meth_setup tac =
urbanc@18046
   186
  Method.only_sectioned_args (Simplifier.simp_modifiers' @ Splitter.split_modifiers)
urbanc@18012
   187
  (Method.SIMPLE_METHOD' HEADGOAL o tac o local_simpset_of);
berghofe@17870
   188
urbanc@19151
   189
val perm_eq_meth         = simp_meth_setup (perm_simp_tac NO_DEBUG_tac);
urbanc@19151
   190
val perm_eq_meth_debug   = simp_meth_setup (perm_simp_tac DEBUG_tac);
urbanc@19151
   191
val supports_meth        = simp_meth_setup (supports_tac NO_DEBUG_tac);
urbanc@19151
   192
val supports_meth_debug  = simp_meth_setup (supports_tac DEBUG_tac);
urbanc@19151
   193
val finite_gs_meth       = simp_meth_setup (finite_guess_tac NO_DEBUG_tac);
urbanc@19151
   194
val finite_gs_meth_debug = simp_meth_setup (finite_guess_tac DEBUG_tac);
berghofe@17870
   195
berghofe@17870
   196
end
berghofe@17870
   197
berghofe@17870
   198
berghofe@17870
   199