src/Provers/classical.ML
changeset 60943 7cf1ea00a020
parent 60942 0af3e522406c
child 60944 bb75b61dba5d
equal deleted inserted replaced
60942:0af3e522406c 60943:7cf1ea00a020
     2     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     2     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     3 
     3 
     4 Theorem prover for classical reasoning, including predicate calculus, set
     4 Theorem prover for classical reasoning, including predicate calculus, set
     5 theory, etc.
     5 theory, etc.
     6 
     6 
     7 Rules must be classified as intro, elim, safe, hazardous (unsafe).
     7 Rules must be classified as intro, elim, safe, unsafe.
     8 
     8 
     9 A rule is unsafe unless it can be applied blindly without harmful results.
     9 A rule is unsafe unless it can be applied blindly without harmful results.
    10 For a rule to be safe, its premises and conclusion should be logically
    10 For a rule to be safe, its premises and conclusion should be logically
    11 equivalent.  There should be no variables in the premises that are not in
    11 equivalent.  There should be no variables in the premises that are not in
    12 the conclusion.
    12 the conclusion.
    74   val contr_tac: Proof.context -> int -> tactic
    74   val contr_tac: Proof.context -> int -> tactic
    75   val dup_elim: Proof.context -> thm -> thm
    75   val dup_elim: Proof.context -> thm -> thm
    76   val dup_intr: thm -> thm
    76   val dup_intr: thm -> thm
    77   val dup_step_tac: Proof.context -> int -> tactic
    77   val dup_step_tac: Proof.context -> int -> tactic
    78   val eq_mp_tac: Proof.context -> int -> tactic
    78   val eq_mp_tac: Proof.context -> int -> tactic
    79   val haz_step_tac: Proof.context -> int -> tactic
    79   val unsafe_step_tac: Proof.context -> int -> tactic
    80   val joinrules: thm list * thm list -> (bool * thm) list
    80   val joinrules: thm list * thm list -> (bool * thm) list
    81   val mp_tac: Proof.context -> int -> tactic
    81   val mp_tac: Proof.context -> int -> tactic
    82   val safe_tac: Proof.context -> tactic
    82   val safe_tac: Proof.context -> tactic
    83   val safe_steps_tac: Proof.context -> int -> tactic
    83   val safe_steps_tac: Proof.context -> int -> tactic
    84   val safe_step_tac: Proof.context -> int -> tactic
    84   val safe_step_tac: Proof.context -> int -> tactic
    99   val classical_rule: Proof.context -> thm -> thm
    99   val classical_rule: Proof.context -> thm -> thm
   100   type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net
   100   type netpair = (int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net
   101   val rep_cs: claset ->
   101   val rep_cs: claset ->
   102    {safeIs: thm Item_Net.T,
   102    {safeIs: thm Item_Net.T,
   103     safeEs: thm Item_Net.T,
   103     safeEs: thm Item_Net.T,
   104     hazIs: thm Item_Net.T,
   104     unsafeIs: thm Item_Net.T,
   105     hazEs: thm Item_Net.T,
   105     unsafeEs: thm Item_Net.T,
   106     swrappers: (string * (Proof.context -> wrapper)) list,
   106     swrappers: (string * (Proof.context -> wrapper)) list,
   107     uwrappers: (string * (Proof.context -> wrapper)) list,
   107     uwrappers: (string * (Proof.context -> wrapper)) list,
   108     safe0_netpair: netpair,
   108     safe0_netpair: netpair,
   109     safep_netpair: netpair,
   109     safep_netpair: netpair,
   110     haz_netpair: netpair,
   110     unsafe_netpair: netpair,
   111     dup_netpair: netpair,
   111     dup_netpair: netpair,
   112     extra_netpair: Context_Rules.netpair}
   112     extra_netpair: Context_Rules.netpair}
   113   val get_cs: Context.generic -> claset
   113   val get_cs: Context.generic -> claset
   114   val map_cs: (claset -> claset) -> Context.generic -> Context.generic
   114   val map_cs: (claset -> claset) -> Context.generic -> Context.generic
   115   val safe_dest: int option -> attribute
   115   val safe_dest: int option -> attribute
   116   val safe_elim: int option -> attribute
   116   val safe_elim: int option -> attribute
   117   val safe_intro: int option -> attribute
   117   val safe_intro: int option -> attribute
   118   val haz_dest: int option -> attribute
   118   val unsafe_dest: int option -> attribute
   119   val haz_elim: int option -> attribute
   119   val unsafe_elim: int option -> attribute
   120   val haz_intro: int option -> attribute
   120   val unsafe_intro: int option -> attribute
   121   val rule_del: attribute
   121   val rule_del: attribute
   122   val cla_modifiers: Method.modifier parser list
   122   val cla_modifiers: Method.modifier parser list
   123   val cla_method:
   123   val cla_method:
   124     (Proof.context -> tactic) -> (Proof.context -> Proof.method) context_parser
   124     (Proof.context -> tactic) -> (Proof.context -> Proof.method) context_parser
   125   val cla_method':
   125   val cla_method':
   197     assume_tac ctxt ORELSE'
   197     assume_tac ctxt ORELSE'
   198     contr_tac ctxt ORELSE'
   198     contr_tac ctxt ORELSE'
   199     biresolve_tac ctxt (fold_rev addrl rls [])
   199     biresolve_tac ctxt (fold_rev addrl rls [])
   200   end;
   200   end;
   201 
   201 
   202 (*Duplication of hazardous rules, for complete provers*)
   202 (*Duplication of unsafe rules, for complete provers*)
   203 fun dup_intr th = zero_var_indexes (th RS Data.classical);
   203 fun dup_intr th = zero_var_indexes (th RS Data.classical);
   204 
   204 
   205 fun dup_elim ctxt th =
   205 fun dup_elim ctxt th =
   206   let val rl = (th RSN (2, revcut_rl)) |> Thm.assumption (SOME ctxt) 2 |> Seq.hd;
   206   let val rl = (th RSN (2, revcut_rl)) |> Thm.assumption (SOME ctxt) 2 |> Seq.hd;
   207   in rule_by_tactic ctxt (TRYALL (eresolve_tac ctxt [revcut_rl])) rl end;
   207   in rule_by_tactic ctxt (TRYALL (eresolve_tac ctxt [revcut_rl])) rl end;
   214 
   214 
   215 datatype claset =
   215 datatype claset =
   216   CS of
   216   CS of
   217    {safeIs         : thm Item_Net.T,          (*safe introduction rules*)
   217    {safeIs         : thm Item_Net.T,          (*safe introduction rules*)
   218     safeEs         : thm Item_Net.T,          (*safe elimination rules*)
   218     safeEs         : thm Item_Net.T,          (*safe elimination rules*)
   219     hazIs          : thm Item_Net.T,          (*unsafe introduction rules*)
   219     unsafeIs       : thm Item_Net.T,          (*unsafe introduction rules*)
   220     hazEs          : thm Item_Net.T,          (*unsafe elimination rules*)
   220     unsafeEs       : thm Item_Net.T,          (*unsafe elimination rules*)
   221     swrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming safe_step_tac*)
   221     swrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming safe_step_tac*)
   222     uwrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming step_tac*)
   222     uwrappers      : (string * (Proof.context -> wrapper)) list, (*for transforming step_tac*)
   223     safe0_netpair  : netpair,                 (*nets for trivial cases*)
   223     safe0_netpair  : netpair,                 (*nets for trivial cases*)
   224     safep_netpair  : netpair,                 (*nets for >0 subgoals*)
   224     safep_netpair  : netpair,                 (*nets for >0 subgoals*)
   225     haz_netpair    : netpair,                 (*nets for unsafe rules*)
   225     unsafe_netpair : netpair,                 (*nets for unsafe rules*)
   226     dup_netpair    : netpair,                 (*nets for duplication*)
   226     dup_netpair    : netpair,                 (*nets for duplication*)
   227     extra_netpair  : Context_Rules.netpair};  (*nets for extra rules*)
   227     extra_netpair  : Context_Rules.netpair};  (*nets for extra rules*)
   228 
   228 
   229 val empty_netpair = (Net.empty, Net.empty);
   229 val empty_netpair = (Net.empty, Net.empty);
   230 
   230 
   231 val empty_cs =
   231 val empty_cs =
   232   CS
   232   CS
   233    {safeIs = Thm.full_rules,
   233    {safeIs = Thm.full_rules,
   234     safeEs = Thm.full_rules,
   234     safeEs = Thm.full_rules,
   235     hazIs = Thm.full_rules,
   235     unsafeIs = Thm.full_rules,
   236     hazEs = Thm.full_rules,
   236     unsafeEs = Thm.full_rules,
   237     swrappers = [],
   237     swrappers = [],
   238     uwrappers = [],
   238     uwrappers = [],
   239     safe0_netpair = empty_netpair,
   239     safe0_netpair = empty_netpair,
   240     safep_netpair = empty_netpair,
   240     safep_netpair = empty_netpair,
   241     haz_netpair = empty_netpair,
   241     unsafe_netpair = empty_netpair,
   242     dup_netpair = empty_netpair,
   242     dup_netpair = empty_netpair,
   243     extra_netpair = empty_netpair};
   243     extra_netpair = empty_netpair};
   244 
   244 
   245 fun rep_cs (CS args) = args;
   245 fun rep_cs (CS args) = args;
   246 
   246 
   297   | warn_thm _ _ _ = ();
   297   | warn_thm _ _ _ = ();
   298 
   298 
   299 fun warn_rules opt_context msg rules th =
   299 fun warn_rules opt_context msg rules th =
   300   Item_Net.member rules th andalso (warn_thm opt_context msg th; true);
   300   Item_Net.member rules th andalso (warn_thm opt_context msg th; true);
   301 
   301 
   302 fun warn_claset opt_context th (CS {safeIs, safeEs, hazIs, hazEs, ...}) =
   302 fun warn_claset opt_context th (CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   303   warn_rules opt_context "Rule already declared as safe introduction (intro!)\n" safeIs th orelse
   303   warn_rules opt_context "Rule already declared as safe introduction (intro!)\n" safeIs th orelse
   304   warn_rules opt_context "Rule already declared as safe elimination (elim!)\n" safeEs th orelse
   304   warn_rules opt_context "Rule already declared as safe elimination (elim!)\n" safeEs th orelse
   305   warn_rules opt_context "Rule already declared as introduction (intro)\n" hazIs th orelse
   305   warn_rules opt_context "Rule already declared as introduction (intro)\n" unsafeIs th orelse
   306   warn_rules opt_context "Rule already declared as elimination (elim)\n" hazEs th;
   306   warn_rules opt_context "Rule already declared as elimination (elim)\n" unsafeEs th;
   307 
   307 
   308 
   308 
   309 (*** Safe rules ***)
   309 (*** Safe rules ***)
   310 
   310 
   311 fun addSI w opt_context th
   311 fun addSI w opt_context th
   312     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   312     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   313       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   313       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   314   if warn_rules opt_context "Ignoring duplicate safe introduction (intro!)\n" safeIs th then cs
   314   if warn_rules opt_context "Ignoring duplicate safe introduction (intro!)\n" safeIs th then cs
   315   else
   315   else
   316     let
   316     let
   317       val ctxt = default_context opt_context th;
   317       val ctxt = default_context opt_context th;
   318       val th' = flat_rule ctxt th;
   318       val th' = flat_rule ctxt th;
   325       CS
   325       CS
   326        {safeIs = Item_Net.update th safeIs,
   326        {safeIs = Item_Net.update th safeIs,
   327         safe0_netpair = insert (nI,nE) (safe0_rls, []) safe0_netpair,
   327         safe0_netpair = insert (nI,nE) (safe0_rls, []) safe0_netpair,
   328         safep_netpair = insert (nI,nE) (safep_rls, []) safep_netpair,
   328         safep_netpair = insert (nI,nE) (safep_rls, []) safep_netpair,
   329         safeEs = safeEs,
   329         safeEs = safeEs,
   330         hazIs = hazIs,
   330         unsafeIs = unsafeIs,
   331         hazEs = hazEs,
   331         unsafeEs = unsafeEs,
   332         swrappers = swrappers,
   332         swrappers = swrappers,
   333         uwrappers = uwrappers,
   333         uwrappers = uwrappers,
   334         haz_netpair = haz_netpair,
   334         unsafe_netpair = unsafe_netpair,
   335         dup_netpair = dup_netpair,
   335         dup_netpair = dup_netpair,
   336         extra_netpair = insert' (the_default 0 w) (nI,nE) ([th], []) extra_netpair}
   336         extra_netpair = insert' (the_default 0 w) (nI,nE) ([th], []) extra_netpair}
   337     end;
   337     end;
   338 
   338 
   339 fun addSE w opt_context th
   339 fun addSE w opt_context th
   340     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   340     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   341       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   341       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   342   if warn_rules opt_context "Ignoring duplicate safe elimination (elim!)\n" safeEs th then cs
   342   if warn_rules opt_context "Ignoring duplicate safe elimination (elim!)\n" safeEs th then cs
   343   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
   343   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
   344   else
   344   else
   345     let
   345     let
   346       val ctxt = default_context opt_context th;
   346       val ctxt = default_context opt_context th;
   354       CS
   354       CS
   355        {safeEs = Item_Net.update th safeEs,
   355        {safeEs = Item_Net.update th safeEs,
   356         safe0_netpair = insert (nI,nE) ([], safe0_rls) safe0_netpair,
   356         safe0_netpair = insert (nI,nE) ([], safe0_rls) safe0_netpair,
   357         safep_netpair = insert (nI,nE) ([], safep_rls) safep_netpair,
   357         safep_netpair = insert (nI,nE) ([], safep_rls) safep_netpair,
   358         safeIs = safeIs,
   358         safeIs = safeIs,
   359         hazIs = hazIs,
   359         unsafeIs = unsafeIs,
   360         hazEs = hazEs,
   360         unsafeEs = unsafeEs,
   361         swrappers = swrappers,
   361         swrappers = swrappers,
   362         uwrappers = uwrappers,
   362         uwrappers = uwrappers,
   363         haz_netpair = haz_netpair,
   363         unsafe_netpair = unsafe_netpair,
   364         dup_netpair = dup_netpair,
   364         dup_netpair = dup_netpair,
   365         extra_netpair = insert' (the_default 0 w) (nI,nE) ([], [th]) extra_netpair}
   365         extra_netpair = insert' (the_default 0 w) (nI,nE) ([], [th]) extra_netpair}
   366     end;
   366     end;
   367 
   367 
   368 fun addSD w opt_context th = addSE w opt_context (make_elim opt_context th);
   368 fun addSD w opt_context th = addSE w opt_context (make_elim opt_context th);
   369 
   369 
   370 
   370 
   371 (*** Hazardous (unsafe) rules ***)
   371 (*** Hazardous (unsafe) rules ***)
   372 
   372 
   373 fun addI w opt_context th
   373 fun addI w opt_context th
   374     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   374     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   375       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   375       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   376   if warn_rules opt_context "Ignoring duplicate introduction (intro)\n" hazIs th then cs
   376   if warn_rules opt_context "Ignoring duplicate introduction (intro)\n" unsafeIs th then cs
   377   else
   377   else
   378     let
   378     let
   379       val ctxt = default_context opt_context th;
   379       val ctxt = default_context opt_context th;
   380       val th' = flat_rule ctxt th;
   380       val th' = flat_rule ctxt th;
   381       val nI = Item_Net.length hazIs + 1;
   381       val nI = Item_Net.length unsafeIs + 1;
   382       val nE = Item_Net.length hazEs;
   382       val nE = Item_Net.length unsafeEs;
   383       val _ = warn_claset opt_context th cs;
   383       val _ = warn_claset opt_context th cs;
   384     in
   384     in
   385       CS
   385       CS
   386        {hazIs = Item_Net.update th hazIs,
   386        {unsafeIs = Item_Net.update th unsafeIs,
   387         haz_netpair = insert (nI, nE) ([th'], []) haz_netpair,
   387         unsafe_netpair = insert (nI, nE) ([th'], []) unsafe_netpair,
   388         dup_netpair = insert (nI, nE) ([dup_intr th'], []) dup_netpair,
   388         dup_netpair = insert (nI, nE) ([dup_intr th'], []) dup_netpair,
   389         safeIs = safeIs,
   389         safeIs = safeIs,
   390         safeEs = safeEs,
   390         safeEs = safeEs,
   391         hazEs = hazEs,
   391         unsafeEs = unsafeEs,
   392         swrappers = swrappers,
   392         swrappers = swrappers,
   393         uwrappers = uwrappers,
   393         uwrappers = uwrappers,
   394         safe0_netpair = safe0_netpair,
   394         safe0_netpair = safe0_netpair,
   395         safep_netpair = safep_netpair,
   395         safep_netpair = safep_netpair,
   396         extra_netpair = insert' (the_default 1 w) (nI, nE) ([th], []) extra_netpair}
   396         extra_netpair = insert' (the_default 1 w) (nI, nE) ([th], []) extra_netpair}
   397     end
   397     end
   398     handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   398     handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   399       bad_thm opt_context "Ill-formed introduction rule" th;
   399       bad_thm opt_context "Ill-formed introduction rule" th;
   400 
   400 
   401 fun addE w opt_context th
   401 fun addE w opt_context th
   402     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   402     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   403       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   403       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   404   if warn_rules opt_context "Ignoring duplicate elimination (elim)\n" hazEs th then cs
   404   if warn_rules opt_context "Ignoring duplicate elimination (elim)\n" unsafeEs th then cs
   405   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
   405   else if has_fewer_prems 1 th then bad_thm opt_context "Ill-formed elimination rule" th
   406   else
   406   else
   407     let
   407     let
   408       val ctxt = default_context opt_context th;
   408       val ctxt = default_context opt_context th;
   409       val th' = classical_rule ctxt (flat_rule ctxt th);
   409       val th' = classical_rule ctxt (flat_rule ctxt th);
   410       val nI = Item_Net.length hazIs;
   410       val nI = Item_Net.length unsafeIs;
   411       val nE = Item_Net.length hazEs + 1;
   411       val nE = Item_Net.length unsafeEs + 1;
   412       val _ = warn_claset opt_context th cs;
   412       val _ = warn_claset opt_context th cs;
   413     in
   413     in
   414       CS
   414       CS
   415        {hazEs = Item_Net.update th hazEs,
   415        {unsafeEs = Item_Net.update th unsafeEs,
   416         haz_netpair = insert (nI, nE) ([], [th']) haz_netpair,
   416         unsafe_netpair = insert (nI, nE) ([], [th']) unsafe_netpair,
   417         dup_netpair = insert (nI, nE) ([], [dup_elim ctxt th']) dup_netpair,
   417         dup_netpair = insert (nI, nE) ([], [dup_elim ctxt th']) dup_netpair,
   418         safeIs = safeIs,
   418         safeIs = safeIs,
   419         safeEs = safeEs,
   419         safeEs = safeEs,
   420         hazIs = hazIs,
   420         unsafeIs = unsafeIs,
   421         swrappers = swrappers,
   421         swrappers = swrappers,
   422         uwrappers = uwrappers,
   422         uwrappers = uwrappers,
   423         safe0_netpair = safe0_netpair,
   423         safe0_netpair = safe0_netpair,
   424         safep_netpair = safep_netpair,
   424         safep_netpair = safep_netpair,
   425         extra_netpair = insert' (the_default 1 w) (nI, nE) ([], [th]) extra_netpair}
   425         extra_netpair = insert' (the_default 1 w) (nI, nE) ([], [th]) extra_netpair}
   433      Working out what to delete, requires repeating much of the code used
   433      Working out what to delete, requires repeating much of the code used
   434         to insert.
   434         to insert.
   435 ***)
   435 ***)
   436 
   436 
   437 fun delSI opt_context th
   437 fun delSI opt_context th
   438     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   438     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   439       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   439       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   440   if Item_Net.member safeIs th then
   440   if Item_Net.member safeIs th then
   441     let
   441     let
   442       val ctxt = default_context opt_context th;
   442       val ctxt = default_context opt_context th;
   443       val th' = flat_rule ctxt th;
   443       val th' = flat_rule ctxt th;
   444       val (safe0_rls, safep_rls) = List.partition Thm.no_prems [th'];
   444       val (safe0_rls, safep_rls) = List.partition Thm.no_prems [th'];
   446       CS
   446       CS
   447        {safe0_netpair = delete (safe0_rls, []) safe0_netpair,
   447        {safe0_netpair = delete (safe0_rls, []) safe0_netpair,
   448         safep_netpair = delete (safep_rls, []) safep_netpair,
   448         safep_netpair = delete (safep_rls, []) safep_netpair,
   449         safeIs = Item_Net.remove th safeIs,
   449         safeIs = Item_Net.remove th safeIs,
   450         safeEs = safeEs,
   450         safeEs = safeEs,
   451         hazIs = hazIs,
   451         unsafeIs = unsafeIs,
   452         hazEs = hazEs,
   452         unsafeEs = unsafeEs,
   453         swrappers = swrappers,
   453         swrappers = swrappers,
   454         uwrappers = uwrappers,
   454         uwrappers = uwrappers,
   455         haz_netpair = haz_netpair,
   455         unsafe_netpair = unsafe_netpair,
   456         dup_netpair = dup_netpair,
   456         dup_netpair = dup_netpair,
   457         extra_netpair = delete' ([th], []) extra_netpair}
   457         extra_netpair = delete' ([th], []) extra_netpair}
   458     end
   458     end
   459   else cs;
   459   else cs;
   460 
   460 
   461 fun delSE opt_context th
   461 fun delSE opt_context th
   462     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   462     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   463       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   463       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   464   if Item_Net.member safeEs th then
   464   if Item_Net.member safeEs th then
   465     let
   465     let
   466       val ctxt = default_context opt_context th;
   466       val ctxt = default_context opt_context th;
   467       val th' = classical_rule ctxt (flat_rule ctxt th);
   467       val th' = classical_rule ctxt (flat_rule ctxt th);
   468       val (safe0_rls, safep_rls) = List.partition (fn rl => Thm.nprems_of rl = 1) [th'];
   468       val (safe0_rls, safep_rls) = List.partition (fn rl => Thm.nprems_of rl = 1) [th'];
   470       CS
   470       CS
   471        {safe0_netpair = delete ([], safe0_rls) safe0_netpair,
   471        {safe0_netpair = delete ([], safe0_rls) safe0_netpair,
   472         safep_netpair = delete ([], safep_rls) safep_netpair,
   472         safep_netpair = delete ([], safep_rls) safep_netpair,
   473         safeIs = safeIs,
   473         safeIs = safeIs,
   474         safeEs = Item_Net.remove th safeEs,
   474         safeEs = Item_Net.remove th safeEs,
   475         hazIs = hazIs,
   475         unsafeIs = unsafeIs,
   476         hazEs = hazEs,
   476         unsafeEs = unsafeEs,
   477         swrappers = swrappers,
   477         swrappers = swrappers,
   478         uwrappers = uwrappers,
   478         uwrappers = uwrappers,
   479         haz_netpair = haz_netpair,
   479         unsafe_netpair = unsafe_netpair,
   480         dup_netpair = dup_netpair,
   480         dup_netpair = dup_netpair,
   481         extra_netpair = delete' ([], [th]) extra_netpair}
   481         extra_netpair = delete' ([], [th]) extra_netpair}
   482     end
   482     end
   483   else cs;
   483   else cs;
   484 
   484 
   485 fun delI opt_context th
   485 fun delI opt_context th
   486     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   486     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   487       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   487       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   488   if Item_Net.member hazIs th then
   488   if Item_Net.member unsafeIs th then
   489     let
   489     let
   490       val ctxt = default_context opt_context th;
   490       val ctxt = default_context opt_context th;
   491       val th' = flat_rule ctxt th;
   491       val th' = flat_rule ctxt th;
   492     in
   492     in
   493       CS
   493       CS
   494        {haz_netpair = delete ([th'], []) haz_netpair,
   494        {unsafe_netpair = delete ([th'], []) unsafe_netpair,
   495         dup_netpair = delete ([dup_intr th'], []) dup_netpair,
   495         dup_netpair = delete ([dup_intr th'], []) dup_netpair,
   496         safeIs = safeIs,
   496         safeIs = safeIs,
   497         safeEs = safeEs,
   497         safeEs = safeEs,
   498         hazIs = Item_Net.remove th hazIs,
   498         unsafeIs = Item_Net.remove th unsafeIs,
   499         hazEs = hazEs,
   499         unsafeEs = unsafeEs,
   500         swrappers = swrappers,
   500         swrappers = swrappers,
   501         uwrappers = uwrappers,
   501         uwrappers = uwrappers,
   502         safe0_netpair = safe0_netpair,
   502         safe0_netpair = safe0_netpair,
   503         safep_netpair = safep_netpair,
   503         safep_netpair = safep_netpair,
   504         extra_netpair = delete' ([th], []) extra_netpair}
   504         extra_netpair = delete' ([th], []) extra_netpair}
   506   else cs
   506   else cs
   507   handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   507   handle THM ("RSN: no unifiers", _, _) => (*from dup_intr*)  (* FIXME !? *)
   508     bad_thm opt_context "Ill-formed introduction rule" th;
   508     bad_thm opt_context "Ill-formed introduction rule" th;
   509 
   509 
   510 fun delE opt_context th
   510 fun delE opt_context th
   511     (cs as CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   511     (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   512       safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   512       safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   513   if Item_Net.member hazEs th then
   513   if Item_Net.member unsafeEs th then
   514     let
   514     let
   515       val ctxt = default_context opt_context th;
   515       val ctxt = default_context opt_context th;
   516       val th' = classical_rule ctxt (flat_rule ctxt th);
   516       val th' = classical_rule ctxt (flat_rule ctxt th);
   517     in
   517     in
   518       CS
   518       CS
   519        {haz_netpair = delete ([], [th']) haz_netpair,
   519        {unsafe_netpair = delete ([], [th']) unsafe_netpair,
   520         dup_netpair = delete ([], [dup_elim ctxt th']) dup_netpair,
   520         dup_netpair = delete ([], [dup_elim ctxt th']) dup_netpair,
   521         safeIs = safeIs,
   521         safeIs = safeIs,
   522         safeEs = safeEs,
   522         safeEs = safeEs,
   523         hazIs = hazIs,
   523         unsafeIs = unsafeIs,
   524         hazEs = Item_Net.remove th hazEs,
   524         unsafeEs = Item_Net.remove th unsafeEs,
   525         swrappers = swrappers,
   525         swrappers = swrappers,
   526         uwrappers = uwrappers,
   526         uwrappers = uwrappers,
   527         safe0_netpair = safe0_netpair,
   527         safe0_netpair = safe0_netpair,
   528         safep_netpair = safep_netpair,
   528         safep_netpair = safep_netpair,
   529         extra_netpair = delete' ([], [th]) extra_netpair}
   529         extra_netpair = delete' ([], [th]) extra_netpair}
   530     end
   530     end
   531   else cs;
   531   else cs;
   532 
   532 
   533 (*Delete ALL occurrences of "th" in the claset (perhaps from several lists)*)
   533 (*Delete ALL occurrences of "th" in the claset (perhaps from several lists)*)
   534 fun delrule opt_context th (cs as CS {safeIs, safeEs, hazIs, hazEs, ...}) =
   534 fun delrule opt_context th (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, ...}) =
   535   let val th' = Tactic.make_elim th in
   535   let val th' = Tactic.make_elim th in
   536     if Item_Net.member safeIs th orelse Item_Net.member safeEs th orelse
   536     if Item_Net.member safeIs th orelse Item_Net.member safeEs th orelse
   537       Item_Net.member hazIs th orelse Item_Net.member hazEs th orelse
   537       Item_Net.member unsafeIs th orelse Item_Net.member unsafeEs th orelse
   538       Item_Net.member safeEs th' orelse Item_Net.member hazEs th'
   538       Item_Net.member safeEs th' orelse Item_Net.member unsafeEs th'
   539     then
   539     then
   540       cs
   540       cs
   541       |> delE opt_context th'
   541       |> delE opt_context th'
   542       |> delSE opt_context th'
   542       |> delSE opt_context th'
   543       |> delE opt_context th
   543       |> delE opt_context th
   552 (** claset data **)
   552 (** claset data **)
   553 
   553 
   554 (* wrappers *)
   554 (* wrappers *)
   555 
   555 
   556 fun map_swrappers f
   556 fun map_swrappers f
   557   (CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   557   (CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   558     safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   558     safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   559   CS {safeIs = safeIs, safeEs = safeEs, hazIs = hazIs, hazEs = hazEs,
   559   CS {safeIs = safeIs, safeEs = safeEs, unsafeIs = unsafeIs, unsafeEs = unsafeEs,
   560     swrappers = f swrappers, uwrappers = uwrappers,
   560     swrappers = f swrappers, uwrappers = uwrappers,
   561     safe0_netpair = safe0_netpair, safep_netpair = safep_netpair,
   561     safe0_netpair = safe0_netpair, safep_netpair = safep_netpair,
   562     haz_netpair = haz_netpair, dup_netpair = dup_netpair, extra_netpair = extra_netpair};
   562     unsafe_netpair = unsafe_netpair, dup_netpair = dup_netpair, extra_netpair = extra_netpair};
   563 
   563 
   564 fun map_uwrappers f
   564 fun map_uwrappers f
   565   (CS {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers,
   565   (CS {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers,
   566     safe0_netpair, safep_netpair, haz_netpair, dup_netpair, extra_netpair}) =
   566     safe0_netpair, safep_netpair, unsafe_netpair, dup_netpair, extra_netpair}) =
   567   CS {safeIs = safeIs, safeEs = safeEs, hazIs = hazIs, hazEs = hazEs,
   567   CS {safeIs = safeIs, safeEs = safeEs, unsafeIs = unsafeIs, unsafeEs = unsafeEs,
   568     swrappers = swrappers, uwrappers = f uwrappers,
   568     swrappers = swrappers, uwrappers = f uwrappers,
   569     safe0_netpair = safe0_netpair, safep_netpair = safep_netpair,
   569     safe0_netpair = safe0_netpair, safep_netpair = safep_netpair,
   570     haz_netpair = haz_netpair, dup_netpair = dup_netpair, extra_netpair = extra_netpair};
   570     unsafe_netpair = unsafe_netpair, dup_netpair = dup_netpair, extra_netpair = extra_netpair};
   571 
   571 
   572 
   572 
   573 (* merge_cs *)
   573 (* merge_cs *)
   574 
   574 
   575 (*Merge works by adding all new rules of the 2nd claset into the 1st claset,
   575 (*Merge works by adding all new rules of the 2nd claset into the 1st claset,
   576   in order to preserve priorities reliably.*)
   576   in order to preserve priorities reliably.*)
   577 
   577 
   578 fun merge_thms add thms1 thms2 =
   578 fun merge_thms add thms1 thms2 =
   579   fold_rev (fn thm => if Item_Net.member thms1 thm then I else add thm) (Item_Net.content thms2);
   579   fold_rev (fn thm => if Item_Net.member thms1 thm then I else add thm) (Item_Net.content thms2);
   580 
   580 
   581 fun merge_cs (cs as CS {safeIs, safeEs, hazIs, hazEs, ...},
   581 fun merge_cs (cs as CS {safeIs, safeEs, unsafeIs, unsafeEs, ...},
   582     cs' as CS {safeIs = safeIs2, safeEs = safeEs2, hazIs = hazIs2, hazEs = hazEs2,
   582     cs' as CS {safeIs = safeIs2, safeEs = safeEs2, unsafeIs = unsafeIs2, unsafeEs = unsafeEs2,
   583       swrappers, uwrappers, ...}) =
   583       swrappers, uwrappers, ...}) =
   584   if pointer_eq (cs, cs') then cs
   584   if pointer_eq (cs, cs') then cs
   585   else
   585   else
   586     cs
   586     cs
   587     |> merge_thms (addSI NONE NONE) safeIs safeIs2
   587     |> merge_thms (addSI NONE NONE) safeIs safeIs2
   588     |> merge_thms (addSE NONE NONE) safeEs safeEs2
   588     |> merge_thms (addSE NONE NONE) safeEs safeEs2
   589     |> merge_thms (addI NONE NONE) hazIs hazIs2
   589     |> merge_thms (addI NONE NONE) unsafeIs unsafeIs2
   590     |> merge_thms (addE NONE NONE) hazEs hazEs2
   590     |> merge_thms (addE NONE NONE) unsafeEs unsafeEs2
   591     |> map_swrappers (fn ws => AList.merge (op =) (K true) (ws, swrappers))
   591     |> map_swrappers (fn ws => AList.merge (op =) (K true) (ws, swrappers))
   592     |> map_uwrappers (fn ws => AList.merge (op =) (K true) (ws, uwrappers));
   592     |> map_uwrappers (fn ws => AList.merge (op =) (K true) (ws, uwrappers));
   593 
   593 
   594 
   594 
   595 (* data *)
   595 (* data *)
   617 fun map_claset f = Context.proof_map (map_cs f);
   617 fun map_claset f = Context.proof_map (map_cs f);
   618 fun put_claset cs = map_claset (K cs);
   618 fun put_claset cs = map_claset (K cs);
   619 
   619 
   620 fun print_claset ctxt =
   620 fun print_claset ctxt =
   621   let
   621   let
   622     val {safeIs, safeEs, hazIs, hazEs, swrappers, uwrappers, ...} = rep_claset_of ctxt;
   622     val {safeIs, safeEs, unsafeIs, unsafeEs, swrappers, uwrappers, ...} = rep_claset_of ctxt;
   623     val pretty_thms = map (Display.pretty_thm_item ctxt) o Item_Net.content;
   623     val pretty_thms = map (Display.pretty_thm_item ctxt) o Item_Net.content;
   624   in
   624   in
   625     [Pretty.big_list "safe introduction rules (intro!):" (pretty_thms safeIs),
   625     [Pretty.big_list "safe introduction rules (intro!):" (pretty_thms safeIs),
   626       Pretty.big_list "introduction rules (intro):" (pretty_thms hazIs),
   626       Pretty.big_list "introduction rules (intro):" (pretty_thms unsafeIs),
   627       Pretty.big_list "safe elimination rules (elim!):" (pretty_thms safeEs),
   627       Pretty.big_list "safe elimination rules (elim!):" (pretty_thms safeEs),
   628       Pretty.big_list "elimination rules (elim):" (pretty_thms hazEs),
   628       Pretty.big_list "elimination rules (elim):" (pretty_thms unsafeEs),
   629       Pretty.strs ("safe wrappers:" :: map #1 swrappers),
   629       Pretty.strs ("safe wrappers:" :: map #1 swrappers),
   630       Pretty.strs ("unsafe wrappers:" :: map #1 uwrappers)]
   630       Pretty.strs ("unsafe wrappers:" :: map #1 uwrappers)]
   631     |> Pretty.writeln_chunks
   631     |> Pretty.writeln_chunks
   632   end;
   632   end;
   633 
   633 
   765   biresolve_from_nets_tac ctxt (#safep_netpair (rep_claset_of ctxt));
   765   biresolve_from_nets_tac ctxt (#safep_netpair (rep_claset_of ctxt));
   766 
   766 
   767 (*These steps could instantiate variables and are therefore unsafe.*)
   767 (*These steps could instantiate variables and are therefore unsafe.*)
   768 fun inst_step_tac ctxt = inst0_step_tac ctxt APPEND' instp_step_tac ctxt;
   768 fun inst_step_tac ctxt = inst0_step_tac ctxt APPEND' instp_step_tac ctxt;
   769 
   769 
   770 fun haz_step_tac ctxt =
   770 fun unsafe_step_tac ctxt =
   771   biresolve_from_nets_tac ctxt (#haz_netpair (rep_claset_of ctxt));
   771   biresolve_from_nets_tac ctxt (#unsafe_netpair (rep_claset_of ctxt));
   772 
   772 
   773 (*Single step for the prover.  FAILS unless it makes progress. *)
   773 (*Single step for the prover.  FAILS unless it makes progress. *)
   774 fun step_tac ctxt i =
   774 fun step_tac ctxt i =
   775   safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt ORELSE' haz_step_tac ctxt) i;
   775   safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt ORELSE' unsafe_step_tac ctxt) i;
   776 
   776 
   777 (*Using a "safe" rule to instantiate variables is unsafe.  This tactic
   777 (*Using a "safe" rule to instantiate variables is unsafe.  This tactic
   778   allows backtracking from "safe" rules to "unsafe" rules here.*)
   778   allows backtracking from "safe" rules to "unsafe" rules here.*)
   779 fun slow_step_tac ctxt i =
   779 fun slow_step_tac ctxt i =
   780   safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt APPEND' haz_step_tac ctxt) i;
   780   safe_tac ctxt ORELSE appWrappers ctxt (inst_step_tac ctxt APPEND' unsafe_step_tac ctxt) i;
   781 
   781 
   782 
   782 
   783 (**** The following tactics all fail unless they solve one goal ****)
   783 (**** The following tactics all fail unless they solve one goal ****)
   784 
   784 
   785 (*Dumb but fast*)
   785 (*Dumb but fast*)
   864     map_cs (f (SOME opt_context) th) opt_context);
   864     map_cs (f (SOME opt_context) th) opt_context);
   865 
   865 
   866 val safe_elim = attrib o addSE;
   866 val safe_elim = attrib o addSE;
   867 val safe_intro = attrib o addSI;
   867 val safe_intro = attrib o addSI;
   868 val safe_dest = attrib o addSD;
   868 val safe_dest = attrib o addSD;
   869 val haz_elim = attrib o addE;
   869 val unsafe_elim = attrib o addE;
   870 val haz_intro = attrib o addI;
   870 val unsafe_intro = attrib o addI;
   871 val haz_dest = attrib o addD;
   871 val unsafe_dest = attrib o addD;
   872 
   872 
   873 val rule_del =
   873 val rule_del =
   874   Thm.declaration_attribute (fn th => fn opt_context =>
   874   Thm.declaration_attribute (fn th => fn opt_context =>
   875     opt_context |> map_cs (delrule (SOME opt_context) th) |>
   875     opt_context |> map_cs (delrule (SOME opt_context) th) |>
   876     Thm.attribute_declaration Context_Rules.rule_del th);
   876     Thm.attribute_declaration Context_Rules.rule_del th);
   885 
   885 
   886 val _ =
   886 val _ =
   887   Theory.setup
   887   Theory.setup
   888    (Attrib.setup @{binding swapped} (Scan.succeed swapped)
   888    (Attrib.setup @{binding swapped} (Scan.succeed swapped)
   889       "classical swap of introduction rule" #>
   889       "classical swap of introduction rule" #>
   890     Attrib.setup @{binding dest} (Context_Rules.add safe_dest haz_dest Context_Rules.dest_query)
   890     Attrib.setup @{binding dest} (Context_Rules.add safe_dest unsafe_dest Context_Rules.dest_query)
   891       "declaration of Classical destruction rule" #>
   891       "declaration of Classical destruction rule" #>
   892     Attrib.setup @{binding elim} (Context_Rules.add safe_elim haz_elim Context_Rules.elim_query)
   892     Attrib.setup @{binding elim} (Context_Rules.add safe_elim unsafe_elim Context_Rules.elim_query)
   893       "declaration of Classical elimination rule" #>
   893       "declaration of Classical elimination rule" #>
   894     Attrib.setup @{binding intro} (Context_Rules.add safe_intro haz_intro Context_Rules.intro_query)
   894     Attrib.setup @{binding intro} (Context_Rules.add safe_intro unsafe_intro Context_Rules.intro_query)
   895       "declaration of Classical introduction rule" #>
   895       "declaration of Classical introduction rule" #>
   896     Attrib.setup @{binding rule} (Scan.lift Args.del >> K rule_del)
   896     Attrib.setup @{binding rule} (Scan.lift Args.del >> K rule_del)
   897       "remove declaration of intro/elim/dest rule");
   897       "remove declaration of intro/elim/dest rule");
   898 
   898 
   899 
   899 
   936 
   936 
   937 (* automatic methods *)
   937 (* automatic methods *)
   938 
   938 
   939 val cla_modifiers =
   939 val cla_modifiers =
   940  [Args.$$$ destN -- Args.bang_colon >> K (Method.modifier (safe_dest NONE) @{here}),
   940  [Args.$$$ destN -- Args.bang_colon >> K (Method.modifier (safe_dest NONE) @{here}),
   941   Args.$$$ destN -- Args.colon >> K (Method.modifier (haz_dest NONE) @{here}),
   941   Args.$$$ destN -- Args.colon >> K (Method.modifier (unsafe_dest NONE) @{here}),
   942   Args.$$$ elimN -- Args.bang_colon >> K (Method.modifier (safe_elim NONE) @{here}),
   942   Args.$$$ elimN -- Args.bang_colon >> K (Method.modifier (safe_elim NONE) @{here}),
   943   Args.$$$ elimN -- Args.colon >> K (Method.modifier (haz_elim NONE) @{here}),
   943   Args.$$$ elimN -- Args.colon >> K (Method.modifier (unsafe_elim NONE) @{here}),
   944   Args.$$$ introN -- Args.bang_colon >> K (Method.modifier (safe_intro NONE) @{here}),
   944   Args.$$$ introN -- Args.bang_colon >> K (Method.modifier (safe_intro NONE) @{here}),
   945   Args.$$$ introN -- Args.colon >> K (Method.modifier (haz_intro NONE) @{here}),
   945   Args.$$$ introN -- Args.colon >> K (Method.modifier (unsafe_intro NONE) @{here}),
   946   Args.del -- Args.colon >> K (Method.modifier rule_del @{here})];
   946   Args.del -- Args.colon >> K (Method.modifier rule_del @{here})];
   947 
   947 
   948 fun cla_method tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD o tac);
   948 fun cla_method tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD o tac);
   949 fun cla_method' tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD' o tac);
   949 fun cla_method' tac = Method.sections cla_modifiers >> K (SIMPLE_METHOD' o tac);
   950 
   950