52 fun prove_strong_ind s avoids thy = |
52 fun prove_strong_ind s avoids thy = |
53 let |
53 let |
54 val ctxt = ProofContext.init thy; |
54 val ctxt = ProofContext.init thy; |
55 val ({names, ...}, {raw_induct, ...}) = |
55 val ({names, ...}, {raw_induct, ...}) = |
56 InductivePackage.the_inductive ctxt (Sign.intern_const thy s); |
56 InductivePackage.the_inductive ctxt (Sign.intern_const thy s); |
|
57 val eqvt_thms = NominalThmDecls.get_eqvt_thms thy; |
|
58 val _ = (case names \\ foldl (apfst prop_of #> add_term_consts) [] eqvt_thms of |
|
59 [] => () |
|
60 | xs => error ("Missing equivariance theorem for predicate(s): " ^ |
|
61 commas_quote xs)); |
57 val induct_cases = map fst (fst (RuleCases.get (the |
62 val induct_cases = map fst (fst (RuleCases.get (the |
58 (InductAttrib.lookup_inductS ctxt (hd names))))); |
63 (InductAttrib.lookup_inductS ctxt (hd names))))); |
59 val raw_induct' = Logic.unvarify (prop_of raw_induct); |
64 val raw_induct' = Logic.unvarify (prop_of raw_induct); |
60 val concls = raw_induct' |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop |> |
65 val concls = raw_induct' |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop |> |
61 HOLogic.dest_conj |> map (HOLogic.dest_imp ##> strip_comb); |
66 HOLogic.dest_conj |> map (HOLogic.dest_imp ##> strip_comb); |
166 (mk_distinct bvars @ |
171 (mk_distinct bvars @ |
167 maps (fn (t, T) => map (fn (u, U) => HOLogic.mk_Trueprop |
172 maps (fn (t, T) => map (fn (u, U) => HOLogic.mk_Trueprop |
168 (Const ("Nominal.fresh", U --> T --> HOLogic.boolT) $ u $ t)) bvars) |
173 (Const ("Nominal.fresh", U --> T --> HOLogic.boolT) $ u $ t)) bvars) |
169 (ts ~~ binder_types (fastype_of p)))) prems; |
174 (ts ~~ binder_types (fastype_of p)))) prems; |
170 |
175 |
171 val eqvt_ss = HOL_basic_ss addsimps NominalThmDecls.get_eqvt_thms thy; |
176 val eqvt_ss = HOL_basic_ss addsimps eqvt_thms; |
172 val fresh_bij = PureThy.get_thms thy (Name "fresh_bij"); |
177 val fresh_bij = PureThy.get_thms thy (Name "fresh_bij"); |
173 val perm_bij = PureThy.get_thms thy (Name "perm_bij"); |
178 val perm_bij = PureThy.get_thms thy (Name "perm_bij"); |
174 val fs_atoms = map (fn aT => PureThy.get_thm thy |
179 val fs_atoms = map (fn aT => PureThy.get_thm thy |
175 (Name ("fs_" ^ Sign.base_name (fst (dest_Type aT)) ^ "1"))) atomTs; |
180 (Name ("fs_" ^ Sign.base_name (fst (dest_Type aT)) ^ "1"))) atomTs; |
176 val exists_fresh' = PureThy.get_thms thy (Name "exists_fresh'"); |
181 val exists_fresh' = PureThy.get_thms thy (Name "exists_fresh'"); |
317 end; |
322 end; |
318 |
323 |
319 fun prove_eqvt s xatoms thy = |
324 fun prove_eqvt s xatoms thy = |
320 let |
325 let |
321 val ctxt = ProofContext.init thy; |
326 val ctxt = ProofContext.init thy; |
322 val ({names, ...}, {raw_induct, intrs, ...}) = |
327 val ({names, ...}, {raw_induct, intrs, elims, ...}) = |
323 InductivePackage.the_inductive ctxt (Sign.intern_const thy s); |
328 InductivePackage.the_inductive ctxt (Sign.intern_const thy s); |
|
329 val intrs' = InductivePackage.unpartition_rules intrs |
|
330 (map (fn (((s, ths), (_, k)), th) => |
|
331 (s, ths ~~ InductivePackage.infer_intro_vars th k ths)) |
|
332 (InductivePackage.partition_rules raw_induct intrs ~~ |
|
333 InductivePackage.arities_of raw_induct ~~ elims)); |
324 val atoms' = NominalAtoms.atoms_of thy; |
334 val atoms' = NominalAtoms.atoms_of thy; |
325 val atoms = |
335 val atoms = |
326 if null xatoms then atoms' else |
336 if null xatoms then atoms' else |
327 let val atoms = map (Sign.intern_type thy) xatoms |
337 let val atoms = map (Sign.intern_type thy) xatoms |
328 in |
338 in |
337 val eqvt_ss = HOL_basic_ss addsimps NominalThmDecls.get_eqvt_thms thy; |
347 val eqvt_ss = HOL_basic_ss addsimps NominalThmDecls.get_eqvt_thms thy; |
338 val t = Logic.unvarify (concl_of raw_induct); |
348 val t = Logic.unvarify (concl_of raw_induct); |
339 val pi = Name.variant (add_term_names (t, [])) "pi"; |
349 val pi = Name.variant (add_term_names (t, [])) "pi"; |
340 val ps = map (fst o HOLogic.dest_imp) |
350 val ps = map (fst o HOLogic.dest_imp) |
341 (HOLogic.dest_conj (HOLogic.dest_Trueprop t)); |
351 (HOLogic.dest_conj (HOLogic.dest_Trueprop t)); |
342 fun eqvt_tac th intr st = |
352 fun eqvt_tac th pi (intr, vs) st = |
343 let |
353 let |
344 fun eqvt_err s = error |
354 fun eqvt_err s = error |
345 ("Could not prove equivariance for introduction rule\n" ^ |
355 ("Could not prove equivariance for introduction rule\n" ^ |
346 Sign.string_of_term (theory_of_thm intr) |
356 Sign.string_of_term (theory_of_thm intr) |
347 (Logic.unvarify (prop_of intr)) ^ "\n" ^ s); |
357 (Logic.unvarify (prop_of intr)) ^ "\n" ^ s); |
348 val res = SUBPROOF (fn {prems, ...} => |
358 val res = SUBPROOF (fn {prems, params, ...} => |
349 let val prems' = map (fn th' => Simplifier.simplify eqvt_ss |
359 let |
350 (if null (names inter term_consts (prop_of th')) then th' RS th |
360 val prems' = map (fn th' => Simplifier.simplify eqvt_ss |
351 else th')) prems |
361 (if null (names inter term_consts (prop_of th')) then th' RS th |
352 (* FIXME: instantiate intr? *) |
362 else th')) prems; |
353 in (rtac intr THEN_ALL_NEW resolve_tac prems') 1 |
363 val intr' = Drule.cterm_instantiate (map (cterm_of thy) vs ~~ |
|
364 map (cterm_of thy o NominalPackage.mk_perm [] pi o term_of) params) |
|
365 intr |
|
366 in (rtac intr' THEN_ALL_NEW (TRY o resolve_tac prems')) 1 |
354 end) ctxt 1 st |
367 end) ctxt 1 st |
355 in |
368 in |
356 case (Seq.pull res handle THM (s, _, _) => eqvt_err s) of |
369 case (Seq.pull res handle THM (s, _, _) => eqvt_err s) of |
357 NONE => eqvt_err ("Rule does not match goal\n" ^ |
370 NONE => eqvt_err ("Rule does not match goal\n" ^ |
358 Sign.string_of_term (theory_of_thm st) (hd (prems_of st))) |
371 Sign.string_of_term (theory_of_thm st) (hd (prems_of st))) |
366 in map (fn th => zero_var_indexes (th RS mp)) |
379 in map (fn th => zero_var_indexes (th RS mp)) |
367 (DatatypeAux.split_conj_thm (Goal.prove_global thy [] [] |
380 (DatatypeAux.split_conj_thm (Goal.prove_global thy [] [] |
368 (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map (fn p => |
381 (HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj (map (fn p => |
369 HOLogic.mk_imp (p, list_comb |
382 HOLogic.mk_imp (p, list_comb |
370 (apsnd (map (NominalPackage.mk_perm [] pi')) (strip_comb p)))) ps))) |
383 (apsnd (map (NominalPackage.mk_perm [] pi')) (strip_comb p)))) ps))) |
371 (fn _ => EVERY (rtac raw_induct 1 :: map (fn intr => |
384 (fn _ => EVERY (rtac raw_induct 1 :: map (fn intr_vs => |
372 full_simp_tac eqvt_ss 1 THEN eqvt_tac perm_boolI' intr) intrs)))) |
385 full_simp_tac eqvt_ss 1 THEN |
|
386 eqvt_tac perm_boolI' pi' intr_vs) intrs')))) |
373 end) atoms |
387 end) atoms |
374 in |
388 in |
375 fold (fn (name, ths) => |
389 fold (fn (name, ths) => |
376 Theory.add_path (Sign.base_name name) #> |
390 Theory.add_path (Sign.base_name name) #> |
377 PureThy.add_thmss [(("eqvt", ths), [NominalThmDecls.eqvt_add])] #> snd #> |
391 PureThy.add_thmss [(("eqvt", ths), [NominalThmDecls.eqvt_add])] #> snd #> |