src/HOL/Tools/Meson/meson.ML
changeset 67149 e61557884799
parent 67091 1393c2340eec
child 67522 9e712280cc37
equal deleted inserted replaced
67148:d24dcac5eb4c 67149:e61557884799
    46 end
    46 end
    47 
    47 
    48 structure Meson : MESON =
    48 structure Meson : MESON =
    49 struct
    49 struct
    50 
    50 
    51 val trace = Attrib.setup_config_bool @{binding meson_trace} (K false)
    51 val trace = Attrib.setup_config_bool \<^binding>\<open>meson_trace\<close> (K false)
    52 
    52 
    53 fun trace_msg ctxt msg = if Config.get ctxt trace then tracing (msg ()) else ()
    53 fun trace_msg ctxt msg = if Config.get ctxt trace then tracing (msg ()) else ()
    54 
    54 
    55 val max_clauses = Attrib.setup_config_int @{binding meson_max_clauses} (K 60)
    55 val max_clauses = Attrib.setup_config_int \<^binding>\<open>meson_max_clauses\<close> (K 60)
    56 
    56 
    57 (*No known example (on 1-5-2007) needs even thirty*)
    57 (*No known example (on 1-5-2007) needs even thirty*)
    58 val iter_deepen_limit = 50;
    58 val iter_deepen_limit = 50;
    59 
    59 
    60 val disj_forward = @{thm disj_forward};
    60 val disj_forward = @{thm disj_forward};
    98 fun first_order_resolve ctxt thA thB =
    98 fun first_order_resolve ctxt thA thB =
    99   (case
    99   (case
   100     try (fn () =>
   100     try (fn () =>
   101       let val thy = Proof_Context.theory_of ctxt
   101       let val thy = Proof_Context.theory_of ctxt
   102           val tmA = Thm.concl_of thA
   102           val tmA = Thm.concl_of thA
   103           val Const(@{const_name Pure.imp},_) $ tmB $ _ = Thm.prop_of thB
   103           val Const(\<^const_name>\<open>Pure.imp\<close>,_) $ tmB $ _ = Thm.prop_of thB
   104           val tenv =
   104           val tenv =
   105             Pattern.first_order_match thy (tmB, tmA)
   105             Pattern.first_order_match thy (tmB, tmA)
   106                                           (Vartab.empty, Vartab.empty) |> snd
   106                                           (Vartab.empty, Vartab.empty) |> snd
   107           val insts = Vartab.fold (fn (xi, (_, t)) => cons (xi, Thm.cterm_of ctxt t)) tenv [];
   107           val insts = Vartab.fold (fn (xi, (_, t)) => cons (xi, Thm.cterm_of ctxt t)) tenv [];
   108       in  thA RS (infer_instantiate ctxt insts thB) end) () of
   108       in  thA RS (infer_instantiate ctxt insts thB) end) () of
   119     Abs (protect_prefix ^ s, T, protect_bound_var_names t')
   119     Abs (protect_prefix ^ s, T, protect_bound_var_names t')
   120   | protect_bound_var_names t = t
   120   | protect_bound_var_names t = t
   121 
   121 
   122 fun fix_bound_var_names old_t new_t =
   122 fun fix_bound_var_names old_t new_t =
   123   let
   123   let
   124     fun quant_of @{const_name All} = SOME true
   124     fun quant_of \<^const_name>\<open>All\<close> = SOME true
   125       | quant_of @{const_name Ball} = SOME true
   125       | quant_of \<^const_name>\<open>Ball\<close> = SOME true
   126       | quant_of @{const_name Ex} = SOME false
   126       | quant_of \<^const_name>\<open>Ex\<close> = SOME false
   127       | quant_of @{const_name Bex} = SOME false
   127       | quant_of \<^const_name>\<open>Bex\<close> = SOME false
   128       | quant_of _ = NONE
   128       | quant_of _ = NONE
   129     val flip_quant = Option.map not
   129     val flip_quant = Option.map not
   130     fun some_eq (SOME x) (SOME y) = x = y
   130     fun some_eq (SOME x) (SOME y) = x = y
   131       | some_eq _ _ = false
   131       | some_eq _ _ = false
   132     fun add_names quant (Const (quant_s, _) $ Abs (s, _, t')) =
   132     fun add_names quant (Const (quant_s, _) $ Abs (s, _, t')) =
   133         add_names quant t' #> some_eq quant (quant_of quant_s) ? cons s
   133         add_names quant t' #> some_eq quant (quant_of quant_s) ? cons s
   134       | add_names quant (@{const Not} $ t) = add_names (flip_quant quant) t
   134       | add_names quant (\<^const>\<open>Not\<close> $ t) = add_names (flip_quant quant) t
   135       | add_names quant (@{const implies} $ t1 $ t2) =
   135       | add_names quant (\<^const>\<open>implies\<close> $ t1 $ t2) =
   136         add_names (flip_quant quant) t1 #> add_names quant t2
   136         add_names (flip_quant quant) t1 #> add_names quant t2
   137       | add_names quant (t1 $ t2) = fold (add_names quant) [t1, t2]
   137       | add_names quant (t1 $ t2) = fold (add_names quant) [t1, t2]
   138       | add_names _ _ = I
   138       | add_names _ _ = I
   139     fun lost_names quant =
   139     fun lost_names quant =
   140       subtract (op =) (add_names quant new_t []) (add_names quant old_t [])
   140       subtract (op =) (add_names quant new_t []) (add_names quant old_t [])
   167    property of the form "... c ... c ... c ..." will lead to a huge unification
   167    property of the form "... c ... c ... c ..." will lead to a huge unification
   168    problem, due to the (spurious) choices between projection and imitation. The
   168    problem, due to the (spurious) choices between projection and imitation. The
   169    workaround is to instantiate "?P := (%c. ... c ... c ... c ...)" manually. *)
   169    workaround is to instantiate "?P := (%c. ... c ... c ... c ...)" manually. *)
   170 fun quant_resolve_tac ctxt th i st =
   170 fun quant_resolve_tac ctxt th i st =
   171   case (Thm.concl_of st, Thm.prop_of th) of
   171   case (Thm.concl_of st, Thm.prop_of th) of
   172     (@{const Trueprop} $ (Var _ $ (c as Free _)), @{const Trueprop} $ _) =>
   172     (\<^const>\<open>Trueprop\<close> $ (Var _ $ (c as Free _)), \<^const>\<open>Trueprop\<close> $ _) =>
   173     let
   173     let
   174       val cc = Thm.cterm_of ctxt c
   174       val cc = Thm.cterm_of ctxt c
   175       val ct = Thm.dest_arg (Thm.cprop_of th)
   175       val ct = Thm.dest_arg (Thm.cprop_of th)
   176     in resolve_tac ctxt [th] i (Thm.instantiate' [] [SOME (Thm.lambda cc ct)] st) end
   176     in resolve_tac ctxt [th] i (Thm.instantiate' [] [SOME (Thm.lambda cc ct)] st) end
   177   | _ => resolve_tac ctxt [th] i st
   177   | _ => resolve_tac ctxt [th] i st
   195   end;
   195   end;
   196 
   196 
   197 (*Are any of the logical connectives in "bs" present in the term?*)
   197 (*Are any of the logical connectives in "bs" present in the term?*)
   198 fun has_conns bs =
   198 fun has_conns bs =
   199   let fun has (Const _) = false
   199   let fun has (Const _) = false
   200         | has (Const(@{const_name Trueprop},_) $ p) = has p
   200         | has (Const(\<^const_name>\<open>Trueprop\<close>,_) $ p) = has p
   201         | has (Const(@{const_name Not},_) $ p) = has p
   201         | has (Const(\<^const_name>\<open>Not\<close>,_) $ p) = has p
   202         | has (Const(@{const_name HOL.disj},_) $ p $ q) = member (op =) bs @{const_name HOL.disj} orelse has p orelse has q
   202         | has (Const(\<^const_name>\<open>HOL.disj\<close>,_) $ p $ q) = member (op =) bs \<^const_name>\<open>HOL.disj\<close> orelse has p orelse has q
   203         | has (Const(@{const_name HOL.conj},_) $ p $ q) = member (op =) bs @{const_name HOL.conj} orelse has p orelse has q
   203         | has (Const(\<^const_name>\<open>HOL.conj\<close>,_) $ p $ q) = member (op =) bs \<^const_name>\<open>HOL.conj\<close> orelse has p orelse has q
   204         | has (Const(@{const_name All},_) $ Abs(_,_,p)) = member (op =) bs @{const_name All} orelse has p
   204         | has (Const(\<^const_name>\<open>All\<close>,_) $ Abs(_,_,p)) = member (op =) bs \<^const_name>\<open>All\<close> orelse has p
   205         | has (Const(@{const_name Ex},_) $ Abs(_,_,p)) = member (op =) bs @{const_name Ex} orelse has p
   205         | has (Const(\<^const_name>\<open>Ex\<close>,_) $ Abs(_,_,p)) = member (op =) bs \<^const_name>\<open>Ex\<close> orelse has p
   206         | has _ = false
   206         | has _ = false
   207   in  has  end;
   207   in  has  end;
   208 
   208 
   209 
   209 
   210 (**** Clause handling ****)
   210 (**** Clause handling ****)
   211 
   211 
   212 fun literals (Const(@{const_name Trueprop},_) $ P) = literals P
   212 fun literals (Const(\<^const_name>\<open>Trueprop\<close>,_) $ P) = literals P
   213   | literals (Const(@{const_name HOL.disj},_) $ P $ Q) = literals P @ literals Q
   213   | literals (Const(\<^const_name>\<open>HOL.disj\<close>,_) $ P $ Q) = literals P @ literals Q
   214   | literals (Const(@{const_name Not},_) $ P) = [(false,P)]
   214   | literals (Const(\<^const_name>\<open>Not\<close>,_) $ P) = [(false,P)]
   215   | literals P = [(true,P)];
   215   | literals P = [(true,P)];
   216 
   216 
   217 (*number of literals in a term*)
   217 (*number of literals in a term*)
   218 val nliterals = length o literals;
   218 val nliterals = length o literals;
   219 
   219 
   220 
   220 
   221 (*** Tautology Checking ***)
   221 (*** Tautology Checking ***)
   222 
   222 
   223 fun signed_lits_aux (Const (@{const_name HOL.disj}, _) $ P $ Q) (poslits, neglits) =
   223 fun signed_lits_aux (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ P $ Q) (poslits, neglits) =
   224       signed_lits_aux Q (signed_lits_aux P (poslits, neglits))
   224       signed_lits_aux Q (signed_lits_aux P (poslits, neglits))
   225   | signed_lits_aux (Const(@{const_name Not},_) $ P) (poslits, neglits) = (poslits, P::neglits)
   225   | signed_lits_aux (Const(\<^const_name>\<open>Not\<close>,_) $ P) (poslits, neglits) = (poslits, P::neglits)
   226   | signed_lits_aux P (poslits, neglits) = (P::poslits, neglits);
   226   | signed_lits_aux P (poslits, neglits) = (P::poslits, neglits);
   227 
   227 
   228 fun signed_lits th = signed_lits_aux (HOLogic.dest_Trueprop (Thm.concl_of th)) ([],[]);
   228 fun signed_lits th = signed_lits_aux (HOLogic.dest_Trueprop (Thm.concl_of th)) ([],[]);
   229 
   229 
   230 (*Literals like X=X are tautologous*)
   230 (*Literals like X=X are tautologous*)
   231 fun taut_poslit (Const(@{const_name HOL.eq},_) $ t $ u) = t aconv u
   231 fun taut_poslit (Const(\<^const_name>\<open>HOL.eq\<close>,_) $ t $ u) = t aconv u
   232   | taut_poslit (Const(@{const_name True},_)) = true
   232   | taut_poslit (Const(\<^const_name>\<open>True\<close>,_)) = true
   233   | taut_poslit _ = false;
   233   | taut_poslit _ = false;
   234 
   234 
   235 fun is_taut th =
   235 fun is_taut th =
   236   let val (poslits,neglits) = signed_lits th
   236   let val (poslits,neglits) = signed_lits th
   237   in  exists taut_poslit poslits
   237   in  exists taut_poslit poslits
   238       orelse
   238       orelse
   239       exists (member (op aconv) neglits) (@{term False} :: poslits)
   239       exists (member (op aconv) neglits) (\<^term>\<open>False\<close> :: poslits)
   240   end
   240   end
   241   handle TERM _ => false;       (*probably dest_Trueprop on a weird theorem*)
   241   handle TERM _ => false;       (*probably dest_Trueprop on a weird theorem*)
   242 
   242 
   243 
   243 
   244 (*** To remove trivial negated equality literals from clauses ***)
   244 (*** To remove trivial negated equality literals from clauses ***)
   254   | eliminable _ = false;
   254   | eliminable _ = false;
   255 
   255 
   256 fun refl_clause_aux 0 th = th
   256 fun refl_clause_aux 0 th = th
   257   | refl_clause_aux n th =
   257   | refl_clause_aux n th =
   258        case HOLogic.dest_Trueprop (Thm.concl_of th) of
   258        case HOLogic.dest_Trueprop (Thm.concl_of th) of
   259           (Const (@{const_name HOL.disj}, _) $ (Const (@{const_name HOL.disj}, _) $ _ $ _) $ _) =>
   259           (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ _ $ _) $ _) =>
   260             refl_clause_aux n (th RS disj_assoc)    (*isolate an atom as first disjunct*)
   260             refl_clause_aux n (th RS disj_assoc)    (*isolate an atom as first disjunct*)
   261         | (Const (@{const_name HOL.disj}, _) $ (Const(@{const_name Not},_) $ (Const(@{const_name HOL.eq},_) $ t $ u)) $ _) =>
   261         | (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ (Const(\<^const_name>\<open>Not\<close>,_) $ (Const(\<^const_name>\<open>HOL.eq\<close>,_) $ t $ u)) $ _) =>
   262             if eliminable(t,u)
   262             if eliminable(t,u)
   263             then refl_clause_aux (n-1) (th RS not_refl_disj_D)  (*Var inequation: delete*)
   263             then refl_clause_aux (n-1) (th RS not_refl_disj_D)  (*Var inequation: delete*)
   264             else refl_clause_aux (n-1) (th RS disj_comm)  (*not between Vars: ignore*)
   264             else refl_clause_aux (n-1) (th RS disj_comm)  (*not between Vars: ignore*)
   265         | (Const (@{const_name HOL.disj}, _) $ _ $ _) => refl_clause_aux n (th RS disj_comm)
   265         | (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ _ $ _) => refl_clause_aux n (th RS disj_comm)
   266         | _ => (*not a disjunction*) th;
   266         | _ => (*not a disjunction*) th;
   267 
   267 
   268 fun notequal_lits_count (Const (@{const_name HOL.disj}, _) $ P $ Q) =
   268 fun notequal_lits_count (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ P $ Q) =
   269       notequal_lits_count P + notequal_lits_count Q
   269       notequal_lits_count P + notequal_lits_count Q
   270   | notequal_lits_count (Const(@{const_name Not},_) $ (Const(@{const_name HOL.eq},_) $ _ $ _)) = 1
   270   | notequal_lits_count (Const(\<^const_name>\<open>Not\<close>,_) $ (Const(\<^const_name>\<open>HOL.eq\<close>,_) $ _ $ _)) = 1
   271   | notequal_lits_count _ = 0;
   271   | notequal_lits_count _ = 0;
   272 
   272 
   273 (*Simplify a clause by applying reflexivity to its negated equality literals*)
   273 (*Simplify a clause by applying reflexivity to its negated equality literals*)
   274 fun refl_clause th =
   274 fun refl_clause th =
   275   let val neqs = notequal_lits_count (HOLogic.dest_Trueprop (Thm.concl_of th))
   275   let val neqs = notequal_lits_count (HOLogic.dest_Trueprop (Thm.concl_of th))
   310  let
   310  let
   311   fun sum x y = if x < bound andalso y < bound then x+y else bound
   311   fun sum x y = if x < bound andalso y < bound then x+y else bound
   312   fun prod x y = if x < bound andalso y < bound then x*y else bound
   312   fun prod x y = if x < bound andalso y < bound then x*y else bound
   313   
   313   
   314   (*Estimate the number of clauses in order to detect infeasible theorems*)
   314   (*Estimate the number of clauses in order to detect infeasible theorems*)
   315   fun signed_nclauses b (Const(@{const_name Trueprop},_) $ t) = signed_nclauses b t
   315   fun signed_nclauses b (Const(\<^const_name>\<open>Trueprop\<close>,_) $ t) = signed_nclauses b t
   316     | signed_nclauses b (Const(@{const_name Not},_) $ t) = signed_nclauses (not b) t
   316     | signed_nclauses b (Const(\<^const_name>\<open>Not\<close>,_) $ t) = signed_nclauses (not b) t
   317     | signed_nclauses b (Const(@{const_name HOL.conj},_) $ t $ u) =
   317     | signed_nclauses b (Const(\<^const_name>\<open>HOL.conj\<close>,_) $ t $ u) =
   318         if b then sum (signed_nclauses b t) (signed_nclauses b u)
   318         if b then sum (signed_nclauses b t) (signed_nclauses b u)
   319              else prod (signed_nclauses b t) (signed_nclauses b u)
   319              else prod (signed_nclauses b t) (signed_nclauses b u)
   320     | signed_nclauses b (Const(@{const_name HOL.disj},_) $ t $ u) =
   320     | signed_nclauses b (Const(\<^const_name>\<open>HOL.disj\<close>,_) $ t $ u) =
   321         if b then prod (signed_nclauses b t) (signed_nclauses b u)
   321         if b then prod (signed_nclauses b t) (signed_nclauses b u)
   322              else sum (signed_nclauses b t) (signed_nclauses b u)
   322              else sum (signed_nclauses b t) (signed_nclauses b u)
   323     | signed_nclauses b (Const(@{const_name HOL.implies},_) $ t $ u) =
   323     | signed_nclauses b (Const(\<^const_name>\<open>HOL.implies\<close>,_) $ t $ u) =
   324         if b then prod (signed_nclauses (not b) t) (signed_nclauses b u)
   324         if b then prod (signed_nclauses (not b) t) (signed_nclauses b u)
   325              else sum (signed_nclauses (not b) t) (signed_nclauses b u)
   325              else sum (signed_nclauses (not b) t) (signed_nclauses b u)
   326     | signed_nclauses b (Const(@{const_name HOL.eq}, Type ("fun", [T, _])) $ t $ u) =
   326     | signed_nclauses b (Const(\<^const_name>\<open>HOL.eq\<close>, Type ("fun", [T, _])) $ t $ u) =
   327         if T = HOLogic.boolT then (*Boolean equality is if-and-only-if*)
   327         if T = HOLogic.boolT then (*Boolean equality is if-and-only-if*)
   328             if b then sum (prod (signed_nclauses (not b) t) (signed_nclauses b u))
   328             if b then sum (prod (signed_nclauses (not b) t) (signed_nclauses b u))
   329                           (prod (signed_nclauses (not b) u) (signed_nclauses b t))
   329                           (prod (signed_nclauses (not b) u) (signed_nclauses b t))
   330                  else sum (prod (signed_nclauses b t) (signed_nclauses b u))
   330                  else sum (prod (signed_nclauses b t) (signed_nclauses b u))
   331                           (prod (signed_nclauses (not b) t) (signed_nclauses (not b) u))
   331                           (prod (signed_nclauses (not b) t) (signed_nclauses (not b) u))
   332         else 1
   332         else 1
   333     | signed_nclauses b (Const(@{const_name Ex}, _) $ Abs (_,_,t)) = signed_nclauses b t
   333     | signed_nclauses b (Const(\<^const_name>\<open>Ex\<close>, _) $ Abs (_,_,t)) = signed_nclauses b t
   334     | signed_nclauses b (Const(@{const_name All},_) $ Abs (_,_,t)) = signed_nclauses b t
   334     | signed_nclauses b (Const(\<^const_name>\<open>All\<close>,_) $ Abs (_,_,t)) = signed_nclauses b t
   335     | signed_nclauses _ _ = 1; (* literal *)
   335     | signed_nclauses _ _ = 1; (* literal *)
   336  in signed_nclauses true t end
   336  in signed_nclauses true t end
   337 
   337 
   338 fun has_too_many_clauses ctxt t =
   338 fun has_too_many_clauses ctxt t =
   339   let val max_cl = Config.get ctxt max_clauses in
   339   let val max_cl = Config.get ctxt max_clauses in
   344   assumptions may not contain scheme variables.  Later, generalize using Variable.export. *)
   344   assumptions may not contain scheme variables.  Later, generalize using Variable.export. *)
   345 local  
   345 local  
   346   val spec_var =
   346   val spec_var =
   347     Thm.dest_arg (Thm.dest_arg (#2 (Thm.dest_implies (Thm.cprop_of spec))))
   347     Thm.dest_arg (Thm.dest_arg (#2 (Thm.dest_implies (Thm.cprop_of spec))))
   348     |> Thm.term_of |> dest_Var;
   348     |> Thm.term_of |> dest_Var;
   349   fun name_of (Const (@{const_name All}, _) $ Abs(x, _, _)) = x | name_of _ = Name.uu;
   349   fun name_of (Const (\<^const_name>\<open>All\<close>, _) $ Abs(x, _, _)) = x | name_of _ = Name.uu;
   350 in  
   350 in  
   351   fun freeze_spec th ctxt =
   351   fun freeze_spec th ctxt =
   352     let
   352     let
   353       val ([x], ctxt') =
   353       val ([x], ctxt') =
   354         Variable.variant_fixes [name_of (HOLogic.dest_Trueprop (Thm.concl_of th))] ctxt;
   354         Variable.variant_fixes [name_of (HOLogic.dest_Trueprop (Thm.concl_of th))] ctxt;
   368    Eliminates existential quantifiers using Skolemization theorems. *)
   368    Eliminates existential quantifiers using Skolemization theorems. *)
   369 fun cnf old_skolem_ths ctxt (th, ths) =
   369 fun cnf old_skolem_ths ctxt (th, ths) =
   370   let val ctxt_ref = Unsynchronized.ref ctxt   (* FIXME ??? *)
   370   let val ctxt_ref = Unsynchronized.ref ctxt   (* FIXME ??? *)
   371       fun cnf_aux (th,ths) =
   371       fun cnf_aux (th,ths) =
   372         if not (can HOLogic.dest_Trueprop (Thm.prop_of th)) then ths (*meta-level: ignore*)
   372         if not (can HOLogic.dest_Trueprop (Thm.prop_of th)) then ths (*meta-level: ignore*)
   373         else if not (has_conns [@{const_name All}, @{const_name Ex}, @{const_name HOL.conj}] (Thm.prop_of th))
   373         else if not (has_conns [\<^const_name>\<open>All\<close>, \<^const_name>\<open>Ex\<close>, \<^const_name>\<open>HOL.conj\<close>] (Thm.prop_of th))
   374         then nodups ctxt th :: ths (*no work to do, terminate*)
   374         then nodups ctxt th :: ths (*no work to do, terminate*)
   375         else case head_of (HOLogic.dest_Trueprop (Thm.concl_of th)) of
   375         else case head_of (HOLogic.dest_Trueprop (Thm.concl_of th)) of
   376             Const (@{const_name HOL.conj}, _) => (*conjunction*)
   376             Const (\<^const_name>\<open>HOL.conj\<close>, _) => (*conjunction*)
   377                 cnf_aux (th RS conjunct1, cnf_aux (th RS conjunct2, ths))
   377                 cnf_aux (th RS conjunct1, cnf_aux (th RS conjunct2, ths))
   378           | Const (@{const_name All}, _) => (*universal quantifier*)
   378           | Const (\<^const_name>\<open>All\<close>, _) => (*universal quantifier*)
   379                 let val (th', ctxt') = freeze_spec th (! ctxt_ref)
   379                 let val (th', ctxt') = freeze_spec th (! ctxt_ref)
   380                 in  ctxt_ref := ctxt'; cnf_aux (th', ths) end
   380                 in  ctxt_ref := ctxt'; cnf_aux (th', ths) end
   381           | Const (@{const_name Ex}, _) =>
   381           | Const (\<^const_name>\<open>Ex\<close>, _) =>
   382               (*existential quantifier: Insert Skolem functions*)
   382               (*existential quantifier: Insert Skolem functions*)
   383               cnf_aux (apply_skolem_theorem (! ctxt_ref) (th, old_skolem_ths), ths)
   383               cnf_aux (apply_skolem_theorem (! ctxt_ref) (th, old_skolem_ths), ths)
   384           | Const (@{const_name HOL.disj}, _) =>
   384           | Const (\<^const_name>\<open>HOL.disj\<close>, _) =>
   385               (*Disjunction of P, Q: Create new goal of proving ?P | ?Q and solve it using
   385               (*Disjunction of P, Q: Create new goal of proving ?P | ?Q and solve it using
   386                 all combinations of converting P, Q to CNF.*)
   386                 all combinations of converting P, Q to CNF.*)
   387               (*There is one assumption, which gets bound to prem and then normalized via
   387               (*There is one assumption, which gets bound to prem and then normalized via
   388                 cnf_nil. The normal form is given to resolve_tac, instantiate a Boolean
   388                 cnf_nil. The normal form is given to resolve_tac, instantiate a Boolean
   389                 variable created by resolution with disj_forward. Since (cnf_nil prem)
   389                 variable created by resolution with disj_forward. Since (cnf_nil prem)
   407 fun finish_cnf ths = filter (not o is_taut) (map refl_clause ths);
   407 fun finish_cnf ths = filter (not o is_taut) (map refl_clause ths);
   408 
   408 
   409 
   409 
   410 (**** Generation of contrapositives ****)
   410 (**** Generation of contrapositives ****)
   411 
   411 
   412 fun is_left (Const (@{const_name Trueprop}, _) $
   412 fun is_left (Const (\<^const_name>\<open>Trueprop\<close>, _) $
   413                (Const (@{const_name HOL.disj}, _) $ (Const (@{const_name HOL.disj}, _) $ _ $ _) $ _)) = true
   413                (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ _ $ _) $ _)) = true
   414   | is_left _ = false;
   414   | is_left _ = false;
   415 
   415 
   416 (*Associate disjuctions to right -- make leftmost disjunct a LITERAL*)
   416 (*Associate disjuctions to right -- make leftmost disjunct a LITERAL*)
   417 fun assoc_right th =
   417 fun assoc_right th =
   418   if is_left (Thm.prop_of th) then assoc_right (th RS disj_assoc)
   418   if is_left (Thm.prop_of th) then assoc_right (th RS disj_assoc)
   429     make_goal (tryres(th, clause_rules))
   429     make_goal (tryres(th, clause_rules))
   430   handle THM _ => tryres(th, [make_neg_goal, make_pos_goal]);
   430   handle THM _ => tryres(th, [make_neg_goal, make_pos_goal]);
   431 
   431 
   432 fun rigid t = not (is_Var (head_of t));
   432 fun rigid t = not (is_Var (head_of t));
   433 
   433 
   434 fun ok4horn (Const (@{const_name Trueprop},_) $ (Const (@{const_name HOL.disj}, _) $ t $ _)) = rigid t
   434 fun ok4horn (Const (\<^const_name>\<open>Trueprop\<close>,_) $ (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ t $ _)) = rigid t
   435   | ok4horn (Const (@{const_name Trueprop},_) $ t) = rigid t
   435   | ok4horn (Const (\<^const_name>\<open>Trueprop\<close>,_) $ t) = rigid t
   436   | ok4horn _ = false;
   436   | ok4horn _ = false;
   437 
   437 
   438 (*Create a meta-level Horn clause*)
   438 (*Create a meta-level Horn clause*)
   439 fun make_horn crules th =
   439 fun make_horn crules th =
   440   if ok4horn (Thm.concl_of th)
   440   if ok4horn (Thm.concl_of th)
   464 val neg_clauses = filter is_negative;
   464 val neg_clauses = filter is_negative;
   465 
   465 
   466 
   466 
   467 (***** MESON PROOF PROCEDURE *****)
   467 (***** MESON PROOF PROCEDURE *****)
   468 
   468 
   469 fun rhyps (Const(@{const_name Pure.imp},_) $ (Const(@{const_name Trueprop},_) $ A) $ phi,
   469 fun rhyps (Const(\<^const_name>\<open>Pure.imp\<close>,_) $ (Const(\<^const_name>\<open>Trueprop\<close>,_) $ A) $ phi,
   470            As) = rhyps(phi, A::As)
   470            As) = rhyps(phi, A::As)
   471   | rhyps (_, As) = As;
   471   | rhyps (_, As) = As;
   472 
   472 
   473 (** Detecting repeated assumptions in a subgoal **)
   473 (** Detecting repeated assumptions in a subgoal **)
   474 
   474 
   509 
   509 
   510 (*Negation Normal Form*)
   510 (*Negation Normal Form*)
   511 val nnf_rls = [imp_to_disjD, iff_to_disjD, not_conjD, not_disjD,
   511 val nnf_rls = [imp_to_disjD, iff_to_disjD, not_conjD, not_disjD,
   512                not_impD, not_iffD, not_allD, not_exD, not_notD];
   512                not_impD, not_iffD, not_allD, not_exD, not_notD];
   513 
   513 
   514 fun ok4nnf (Const (@{const_name Trueprop},_) $ (Const (@{const_name Not}, _) $ t)) = rigid t
   514 fun ok4nnf (Const (\<^const_name>\<open>Trueprop\<close>,_) $ (Const (\<^const_name>\<open>Not\<close>, _) $ t)) = rigid t
   515   | ok4nnf (Const (@{const_name Trueprop},_) $ t) = rigid t
   515   | ok4nnf (Const (\<^const_name>\<open>Trueprop\<close>,_) $ t) = rigid t
   516   | ok4nnf _ = false;
   516   | ok4nnf _ = false;
   517 
   517 
   518 fun make_nnf1 ctxt th =
   518 fun make_nnf1 ctxt th =
   519   if ok4nnf (Thm.concl_of th)
   519   if ok4nnf (Thm.concl_of th)
   520   then make_nnf1 ctxt (tryres(th, nnf_rls))
   520   then make_nnf1 ctxt (tryres(th, nnf_rls))
   535 (* FIXME: "let_simp" is probably redundant now that we also rewrite with
   535 (* FIXME: "let_simp" is probably redundant now that we also rewrite with
   536   "Let_def [abs_def]". *)
   536   "Let_def [abs_def]". *)
   537 val nnf_ss =
   537 val nnf_ss =
   538   simpset_of (put_simpset HOL_basic_ss @{context}
   538   simpset_of (put_simpset HOL_basic_ss @{context}
   539     addsimps nnf_extra_simps
   539     addsimps nnf_extra_simps
   540     addsimprocs [@{simproc defined_All}, @{simproc defined_Ex}, @{simproc neq},
   540     addsimprocs [\<^simproc>\<open>defined_All\<close>, \<^simproc>\<open>defined_Ex\<close>, \<^simproc>\<open>neq\<close>, \<^simproc>\<open>let_simp\<close>])
   541                  @{simproc let_simp}])
       
   542 
   541 
   543 val presimplified_consts =
   542 val presimplified_consts =
   544   [@{const_name simp_implies}, @{const_name False}, @{const_name True},
   543   [\<^const_name>\<open>simp_implies\<close>, \<^const_name>\<open>False\<close>, \<^const_name>\<open>True\<close>,
   545    @{const_name Ex1}, @{const_name Ball}, @{const_name Bex}, @{const_name If},
   544    \<^const_name>\<open>Ex1\<close>, \<^const_name>\<open>Ball\<close>, \<^const_name>\<open>Bex\<close>, \<^const_name>\<open>If\<close>,
   546    @{const_name Let}]
   545    \<^const_name>\<open>Let\<close>]
   547 
   546 
   548 fun presimplify ctxt =
   547 fun presimplify ctxt =
   549   rewrite_rule ctxt (map safe_mk_meta_eq nnf_simps)
   548   rewrite_rule ctxt (map safe_mk_meta_eq nnf_simps)
   550   #> simplify (put_simpset nnf_ss ctxt)
   549   #> simplify (put_simpset nnf_ss ctxt)
   551   #> rewrite_rule ctxt @{thms Let_def [abs_def]}
   550   #> rewrite_rule ctxt @{thms Let_def [abs_def]}
   561 (* Pull existential quantifiers to front. This accomplishes Skolemization for
   560 (* Pull existential quantifiers to front. This accomplishes Skolemization for
   562    clauses that arise from a subgoal. *)
   561    clauses that arise from a subgoal. *)
   563 fun skolemize_with_choice_theorems ctxt choice_ths =
   562 fun skolemize_with_choice_theorems ctxt choice_ths =
   564   let
   563   let
   565     fun aux th =
   564     fun aux th =
   566       if not (has_conns [@{const_name Ex}] (Thm.prop_of th)) then
   565       if not (has_conns [\<^const_name>\<open>Ex\<close>] (Thm.prop_of th)) then
   567         th
   566         th
   568       else
   567       else
   569         tryres (th, choice_ths @
   568         tryres (th, choice_ths @
   570                     [conj_exD1, conj_exD2, disj_exD, disj_exD1, disj_exD2])
   569                     [conj_exD1, conj_exD2, disj_exD, disj_exD1, disj_exD2])
   571         |> aux
   570         |> aux
   602           let val T = fastype_of t in
   601           let val T = fastype_of t in
   603             if can dest_funT T then (SOME T, Bound 0) else raise NO_F_PATTERN ()
   602             if can dest_funT T then (SOME T, Bound 0) else raise NO_F_PATTERN ()
   604           end
   603           end
   605       end
   604       end
   606   in
   605   in
   607     if T = @{typ bool} then
   606     if T = \<^typ>\<open>bool\<close> then
   608       NONE
   607       NONE
   609     else case pat t u of
   608     else case pat t u of
   610       (SOME T, p as _ $ _) => SOME (Abs (Name.uu, T, p))
   609       (SOME T, p as _ $ _) => SOME (Abs (Name.uu, T, p))
   611     | _ => NONE
   610     | _ => NONE
   612   end
   611   end
   615 val ext_cong_neq = @{thm ext_cong_neq}
   614 val ext_cong_neq = @{thm ext_cong_neq}
   616 
   615 
   617 (* Strengthens "f g ~= f h" to "f g ~= f h & (EX x. g x ~= h x)". *)
   616 (* Strengthens "f g ~= f h" to "f g ~= f h & (EX x. g x ~= h x)". *)
   618 fun cong_extensionalize_thm ctxt th =
   617 fun cong_extensionalize_thm ctxt th =
   619   (case Thm.concl_of th of
   618   (case Thm.concl_of th of
   620     @{const Trueprop} $ (@{const Not}
   619     \<^const>\<open>Trueprop\<close> $ (\<^const>\<open>Not\<close>
   621         $ (Const (@{const_name HOL.eq}, Type (_, [T, _]))
   620         $ (Const (\<^const_name>\<open>HOL.eq\<close>, Type (_, [T, _]))
   622            $ (t as _ $ _) $ (u as _ $ _))) =>
   621            $ (t as _ $ _) $ (u as _ $ _))) =>
   623     (case get_F_pattern T t u of
   622     (case get_F_pattern T t u of
   624       SOME p => th RS infer_instantiate ctxt [(("F", 0), Thm.cterm_of ctxt p)] ext_cong_neq
   623       SOME p => th RS infer_instantiate ctxt [(("F", 0), Thm.cterm_of ctxt p)] ext_cong_neq
   625     | NONE => th)
   624     | NONE => th)
   626   | _ => th)
   625   | _ => th)
   628 (* Removes the lambdas from an equation of the form "t = (%x1 ... xn. u)". It
   627 (* Removes the lambdas from an equation of the form "t = (%x1 ... xn. u)". It
   629    would be desirable to do this symmetrically but there's at least one existing
   628    would be desirable to do this symmetrically but there's at least one existing
   630    proof in "Tarski" that relies on the current behavior. *)
   629    proof in "Tarski" that relies on the current behavior. *)
   631 fun abs_extensionalize_conv ctxt ct =
   630 fun abs_extensionalize_conv ctxt ct =
   632   (case Thm.term_of ct of
   631   (case Thm.term_of ct of
   633     Const (@{const_name HOL.eq}, _) $ _ $ Abs _ =>
   632     Const (\<^const_name>\<open>HOL.eq\<close>, _) $ _ $ Abs _ =>
   634     ct |> (Conv.rewr_conv @{thm fun_eq_iff [THEN eq_reflection]}
   633     ct |> (Conv.rewr_conv @{thm fun_eq_iff [THEN eq_reflection]}
   635            then_conv abs_extensionalize_conv ctxt)
   634            then_conv abs_extensionalize_conv ctxt)
   636   | _ $ _ => Conv.comb_conv (abs_extensionalize_conv ctxt) ct
   635   | _ $ _ => Conv.comb_conv (abs_extensionalize_conv ctxt) ct
   637   | Abs _ => Conv.abs_conv (abs_extensionalize_conv o snd) ctxt ct
   636   | Abs _ => Conv.abs_conv (abs_extensionalize_conv o snd) ctxt ct
   638   | _ => Conv.all_conv ct)
   637   | _ => Conv.all_conv ct)