src/ZF/indrule.ML
author wenzelm
Mon, 01 Dec 1997 18:22:38 +0100
changeset 4334 e567f3425267
parent 3939 83f908ed3c04
child 4352 7ac9f3e8a97d
permissions -rw-r--r--
ISABELLE_TMP_PREFIX;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
     1
(*  Title:      ZF/indrule.ML
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     2
    ID:         $Id$
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
     3
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
516
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
     4
    Copyright   1994  University of Cambridge
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     5
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     6
Induction rule module -- for Inductive/Coinductive Definitions
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     7
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     8
Proves a strong induction rule and a mutual induction rule
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     9
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    10
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    11
signature INDRULE =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    12
  sig
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    13
  val induct        : thm                       (*main induction rule*)
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    14
  val mutual_induct : thm                       (*mutual induction rule*)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    15
  end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    16
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    17
516
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    18
functor Indrule_Fun
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    19
    (structure Inductive: sig include INDUCTIVE_ARG INDUCTIVE_I end
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
    20
     and Pr: PR and CP: CARTPROD and Su : SU and 
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    21
     Intr_elim: sig include INTR_ELIM INTR_ELIM_AUX end) : INDRULE  =
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    22
let
516
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    23
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    24
val sign = sign_of Inductive.thy;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    25
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    26
val (Const(_,recT),rec_params) = strip_comb (hd Inductive.rec_tms);
516
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    27
3925
90f499226ab9 (co) inductive / datatype package adapted to qualified names;
wenzelm
parents: 3398
diff changeset
    28
val big_rec_name =
3939
83f908ed3c04 Sign.base_name;
wenzelm
parents: 3925
diff changeset
    29
  Sign.intern_const sign (space_implode "_" (map Sign.base_name Intr_elim.rec_names));
3925
90f499226ab9 (co) inductive / datatype package adapted to qualified names;
wenzelm
parents: 3398
diff changeset
    30
516
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    31
val big_rec_tm = list_comb(Const(big_rec_name,recT), rec_params);
1957113f0d7d installation of new inductive/datatype sections
lcp
parents: 366
diff changeset
    32
724
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
    33
val _ = writeln "  Proving the induction rule...";
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    34
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    35
(*** Prove the main induction rule ***)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    36
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    37
val pred_name = "P";            (*name for predicate variables*)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    38
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    39
val big_rec_def::part_rec_defs = Intr_elim.defs;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    40
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    41
(*Used to make induction rules;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    42
   ind_alist = [(rec_tm1,pred1),...]  -- associates predicates with rec ops
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    43
   prem is a premise of an intr rule*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    44
fun add_induct_prem ind_alist (prem as Const("Trueprop",_) $ 
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    45
                 (Const("op :",_)$t$X), iprems) =
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    46
     (case gen_assoc (op aconv) (ind_alist, X) of
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    47
          Some pred => prem :: Ind_Syntax.mk_tprop (pred $ t) :: iprems
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    48
        | None => (*possibly membership in M(rec_tm), for M monotone*)
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    49
            let fun mk_sb (rec_tm,pred) = 
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    50
                        (rec_tm, Ind_Syntax.Collect_const$rec_tm$pred)
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    51
            in  subst_free (map mk_sb ind_alist) prem :: iprems  end)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    52
  | add_induct_prem ind_alist (prem,iprems) = prem :: iprems;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    53
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    54
(*Make a premise of the induction rule.*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    55
fun induct_prem ind_alist intr =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    56
  let val quantfrees = map dest_Free (term_frees intr \\ rec_params)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    57
      val iprems = foldr (add_induct_prem ind_alist)
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    58
                         (Logic.strip_imp_prems intr,[])
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    59
      val (t,X) = Ind_Syntax.rule_concl intr
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    60
      val (Some pred) = gen_assoc (op aconv) (ind_alist, X)
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    61
      val concl = Ind_Syntax.mk_tprop (pred $ t)
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    62
  in list_all_free (quantfrees, Logic.list_implies (iprems,concl)) end
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    63
  handle Bind => error"Recursion term not found in conclusion";
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    64
633
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
    65
(*Reduces backtracking by delivering the correct premise to each goal.
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
    66
  Intro rules with extra Vars in premises still cause some backtracking *)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    67
fun ind_tac [] 0 = all_tac
633
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
    68
  | ind_tac(prem::prems) i = 
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    69
        DEPTH_SOLVE_1 (ares_tac [prem, refl] i) THEN
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    70
        ind_tac prems (i-1);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    71
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    72
val pred = Free(pred_name, Ind_Syntax.iT --> Ind_Syntax.oT);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    73
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    74
val ind_prems = map (induct_prem (map (rpair pred) Inductive.rec_tms)) 
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    75
                    Inductive.intr_tms;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    76
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    77
(*Debugging code...
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    78
val _ = writeln "ind_prems = ";
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    79
val _ = seq (writeln o Sign.string_of_term sign) ind_prems;
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    80
*)
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    81
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    82
(*We use a MINIMAL simpset because others (such as FOL_ss) contain too many
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    83
  simplifications.  If the premises get simplified, then the proofs will 
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    84
  fail.  *)
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    85
val min_ss = empty_ss
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    86
      setmksimps (map mk_meta_eq o ZF_atomize o gen_all)
2637
e9b203f854ae reflecting my recent changes of the simplifier and classical reasoner
oheimb
parents: 2266
diff changeset
    87
      setSolver  (fn prems => resolve_tac (triv_rls@prems) 
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
    88
                              ORELSE' assume_tac
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
    89
                              ORELSE' etac FalseE);
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
    90
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    91
val quant_induct = 
543
e961b2092869 ZF/ind_syntax/unvarifyT, unvarify: moved to Pure/logic.ML
lcp
parents: 516
diff changeset
    92
    prove_goalw_cterm part_rec_defs 
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    93
      (cterm_of sign 
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
    94
       (Logic.list_implies (ind_prems, 
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    95
                Ind_Syntax.mk_tprop (Ind_Syntax.mk_all_imp(big_rec_tm,pred)))))
543
e961b2092869 ZF/ind_syntax/unvarifyT, unvarify: moved to Pure/logic.ML
lcp
parents: 516
diff changeset
    96
      (fn prems =>
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    97
       [rtac (impI RS allI) 1,
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    98
        DETERM (etac Intr_elim.raw_induct 1),
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
    99
        (*Push Part inside Collect*)
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
   100
        full_simp_tac (min_ss addsimps [Part_Collect]) 1,
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   101
        REPEAT (FIRSTGOAL (eresolve_tac [CollectE, exE, conjE, disjE] ORELSE'
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   102
                           hyp_subst_tac)),
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   103
        ind_tac (rev prems) (length prems) ]);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   104
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   105
(*** Prove the simultaneous induction rule ***)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   106
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   107
(*Make distinct predicates for each inductive set*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   108
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   109
(*The components of the element type, several if it is a product*)
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   110
val elem_type = CP.pseudo_type Inductive.dom_sum;
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   111
val elem_factors = CP.factors elem_type;
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   112
val elem_frees = mk_frees "za" elem_factors;
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   113
val elem_tuple = CP.mk_tuple Pr.pair elem_type elem_frees;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   114
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   115
(*Given a recursive set and its domain, return the "fsplit" predicate
724
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   116
  and a conclusion for the simultaneous induction rule.
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   117
  NOTE.  This will not work for mutually recursive predicates.  Previously
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   118
  a summand 'domt' was also an argument, but this required the domain of
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   119
  mutual recursion to invariably be a disjoint sum.*)
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   120
fun mk_predpair rec_tm = 
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   121
  let val rec_name = (#1 o dest_Const o head_of) rec_tm
3939
83f908ed3c04 Sign.base_name;
wenzelm
parents: 3925
diff changeset
   122
      val pfree = Free(pred_name ^ "_" ^ Sign.base_name rec_name,
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   123
                       elem_factors ---> Ind_Syntax.oT)
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   124
      val qconcl = 
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   125
        foldr Ind_Syntax.mk_all 
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   126
          (elem_frees, 
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   127
           Ind_Syntax.imp $ 
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   128
           (Ind_Syntax.mem_const $ elem_tuple $ rec_tm)
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   129
                 $ (list_comb (pfree, elem_frees)))
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   130
  in  (CP.ap_split elem_type Ind_Syntax.oT pfree, 
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   131
       qconcl)  
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   132
  end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   133
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   134
val (preds,qconcls) = split_list (map mk_predpair Inductive.rec_tms);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   135
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   136
(*Used to form simultaneous induction lemma*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   137
fun mk_rec_imp (rec_tm,pred) = 
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   138
    Ind_Syntax.imp $ (Ind_Syntax.mem_const $ Bound 0 $ rec_tm) $ 
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   139
                     (pred $ Bound 0);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   140
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   141
(*To instantiate the main induction rule*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   142
val induct_concl = 
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   143
    Ind_Syntax.mk_tprop
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   144
      (Ind_Syntax.mk_all_imp
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   145
       (big_rec_tm,
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   146
        Abs("z", Ind_Syntax.iT, 
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   147
            fold_bal (app Ind_Syntax.conj) 
2266
82aef6857c5b Replaced map...~~ by ListPair.map
paulson
parents: 2033
diff changeset
   148
            (ListPair.map mk_rec_imp (Inductive.rec_tms,preds)))))
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   149
and mutual_induct_concl =
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   150
 Ind_Syntax.mk_tprop(fold_bal (app Ind_Syntax.conj) qconcls);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   151
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   152
val lemma_tac = FIRST' [eresolve_tac [asm_rl, conjE, PartE, mp],
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   153
                        resolve_tac [allI, impI, conjI, Part_eqI],
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   154
                        dresolve_tac [spec, mp, Pr.fsplitD]];
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   155
3090
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   156
val need_mutual = length Intr_elim.rec_names > 1;
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   157
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   158
val lemma = (*makes the link between the two induction rules*)
3090
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   159
  if need_mutual then
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   160
     (writeln "  Proving the mutual induction rule...";
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   161
      prove_goalw_cterm part_rec_defs 
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   162
	    (cterm_of sign (Logic.mk_implies (induct_concl,
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   163
					      mutual_induct_concl)))
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   164
	    (fn prems =>
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   165
	     [cut_facts_tac prems 1, 
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   166
	      REPEAT (rewrite_goals_tac [Pr.split_eq] THEN
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   167
		      lemma_tac 1)]))
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   168
  else TrueI;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   169
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   170
(*Mutual induction follows by freeness of Inl/Inr.*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   171
724
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   172
(*Simplification largely reduces the mutual induction rule to the 
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   173
  standard rule*)
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   174
val mut_ss = 
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
   175
    min_ss addsimps [Su.distinct, Su.distinct', Su.inl_iff, Su.inr_iff];
724
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   176
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   177
val all_defs = Inductive.con_defs @ part_rec_defs;
724
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   178
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   179
(*Removes Collects caused by M-operators in the intro rules.  It is very
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   180
  hard to simplify
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   181
    list({v: tf. (v : t --> P_t(v)) & (v : f --> P_f(v))}) 
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   182
  where t==Part(tf,Inl) and f==Part(tf,Inr) to  list({v: tf. P_t(v)}).
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   183
  Instead the following rules extract the relevant conjunct.
36c0ac2f4935 ZF/indrule/mutual_ind_tac: backtracks using DEPTH_SOLVE to be certain of
lcp
parents: 633
diff changeset
   184
*)
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   185
val cmonos = [subset_refl RS Collect_mono] RL Inductive.monos RLN (2,[rev_subsetD]);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   186
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   187
(*Avoids backtracking by delivering the correct premise to each goal*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   188
fun mutual_ind_tac [] 0 = all_tac
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   189
  | mutual_ind_tac(prem::prems) i = 
633
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
   190
      DETERM
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
   191
       (SELECT_GOAL 
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   192
          (
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   193
           (*Simplify the assumptions and goal by unfolding Part and
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   194
             using freeness of the Sum constructors; proves all but one
751
f0aacbcedb77 ZF/indrule/mutual_ind_tac: ensured that asm_full_simp_tac ignores any
lcp
parents: 724
diff changeset
   195
             conjunct by contradiction*)
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   196
           rewrite_goals_tac all_defs  THEN
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   197
           simp_tac (mut_ss addsimps [Part_iff]) 1  THEN
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   198
           IF_UNSOLVED (*simp_tac may have finished it off!*)
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
   199
             ((*simplify assumptions*)
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
   200
              (*some risk of excessive simplification here -- might have
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   201
                to identify the bare minimum set of rewrites*)
1868
836950047d85 Put in minimal simpset to avoid excessive simplification,
paulson
parents: 1736
diff changeset
   202
              full_simp_tac 
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   203
                 (mut_ss addsimps (conj_simps @ imp_simps @ quant_simps)) 1
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   204
              THEN
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   205
              (*unpackage and use "prem" in the corresponding place*)
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   206
              REPEAT (rtac impI 1)  THEN
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   207
              rtac (rewrite_rule all_defs prem) 1  THEN
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   208
              (*prem must not be REPEATed below: could loop!*)
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   209
              DEPTH_SOLVE (FIRSTGOAL (ares_tac [impI] ORELSE' 
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   210
                                      eresolve_tac (conjE::mp::cmonos))))
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   211
          ) i)
633
9e4d4f3eb812 {HOL,ZF}/indrule/ind_tac: now calls DEPTH_SOLVE_1 instead of REPEAT, to
lcp
parents: 590
diff changeset
   212
       THEN mutual_ind_tac prems (i-1);
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   213
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   214
val mutual_induct_fsplit = 
3090
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   215
  if need_mutual then
543
e961b2092869 ZF/ind_syntax/unvarifyT, unvarify: moved to Pure/logic.ML
lcp
parents: 516
diff changeset
   216
    prove_goalw_cterm []
1461
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   217
          (cterm_of sign
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   218
           (Logic.list_implies 
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   219
              (map (induct_prem (Inductive.rec_tms~~preds)) Inductive.intr_tms,
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   220
               mutual_induct_concl)))
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   221
          (fn prems =>
6bcb44e4d6e5 expanded tabs
clasohm
parents: 1418
diff changeset
   222
           [rtac (quant_induct RS lemma) 1,
3090
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   223
            mutual_ind_tac (rev prems) (length prems)])
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   224
  else TrueI;
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   225
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   226
(** Uncurrying the predicate in the ordinary induction rule **)
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   227
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   228
(*instantiate the variable to a tuple, if it is non-trivial, in order to
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   229
  allow the predicate to be "opened up".
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   230
  The name "x.1" comes from the "RS spec" !*)
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   231
val inst = 
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   232
    case elem_frees of [_] => I
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   233
       | _ => instantiate ([], [(cterm_of sign (Var(("x",1), Ind_Syntax.iT)), 
2033
639de962ded4 Ran expandshort; used stac instead of ssubst
paulson
parents: 1956
diff changeset
   234
                                 cterm_of sign elem_tuple)]);
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   235
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   236
(*strip quantifier and the implication*)
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   237
val induct0 = inst (quant_induct RS spec RSN (2,rev_mp));
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   238
3398
dfd9cbad5530 Now extracts the predicate variable from induct0 insteead of trying to
paulson
parents: 3090
diff changeset
   239
val Const ("Trueprop", _) $ (pred_var $ _) = concl_of induct0
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   240
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   241
in
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   242
  struct
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   243
  (*strip quantifier*)
3398
dfd9cbad5530 Now extracts the predicate variable from induct0 insteead of trying to
paulson
parents: 3090
diff changeset
   244
  val induct = CP.split_rule_var(pred_var, elem_type-->Ind_Syntax.oT, induct0) 
dfd9cbad5530 Now extracts the predicate variable from induct0 insteead of trying to
paulson
parents: 3090
diff changeset
   245
               |> standard;
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   246
1736
fe0b459273f2 Predicates are now uncurried in both induction rules,
paulson
parents: 1461
diff changeset
   247
  (*Just "True" unless there's true mutual recursion.  This saves storage.*)
3090
eeb4d0c7f748 No longer proves mutual_induct unless it is necessary.
paulson
parents: 2637
diff changeset
   248
  val mutual_induct = CP.remove_split mutual_induct_fsplit
1418
f5f97ee67cbb Improving space efficiency of inductive/datatype definitions.
paulson
parents: 1104
diff changeset
   249
  end
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   250
end;