merged
authorhaftmann
Thu, 18 Mar 2010 13:57:00 +0100
changeset 35824 b766aad9136d
parent 35815 10e723e54076 (diff)
parent 35823 bd26885af9f4 (current diff)
child 35831 e31ec41a551b
merged
--- a/NEWS	Thu Mar 18 13:56:34 2010 +0100
+++ b/NEWS	Thu Mar 18 13:57:00 2010 +0100
@@ -221,6 +221,40 @@
 * Renamed Library/Quotient.thy to Library/Quotient_Type.thy to avoid
 clash with new theory Quotient in Main HOL.
 
+* Library/Nat_Bijection.thy is a collection of bijective functions
+between nat and other types, which supersedes the older libraries
+Library/Nat_Int_Bij.thy and HOLCF/NatIso.thy.  INCOMPATIBILITY.
+
+  Constants:
+  Nat_Int_Bij.nat2_to_nat         ~> prod_encode
+  Nat_Int_Bij.nat_to_nat2         ~> prod_decode
+  Nat_Int_Bij.int_to_nat_bij      ~> int_encode
+  Nat_Int_Bij.nat_to_int_bij      ~> int_decode
+  Countable.pair_encode           ~> prod_encode
+  NatIso.prod2nat                 ~> prod_encode
+  NatIso.nat2prod                 ~> prod_decode
+  NatIso.sum2nat                  ~> sum_encode
+  NatIso.nat2sum                  ~> sum_decode
+  NatIso.list2nat                 ~> list_encode
+  NatIso.nat2list                 ~> list_decode
+  NatIso.set2nat                  ~> set_encode
+  NatIso.nat2set                  ~> set_decode
+
+  Lemmas:
+  Nat_Int_Bij.bij_nat_to_int_bij  ~> bij_int_decode
+  Nat_Int_Bij.nat2_to_nat_inj     ~> inj_prod_encode
+  Nat_Int_Bij.nat2_to_nat_surj    ~> surj_prod_encode
+  Nat_Int_Bij.nat_to_nat2_inj     ~> inj_prod_decode
+  Nat_Int_Bij.nat_to_nat2_surj    ~> surj_prod_decode
+  Nat_Int_Bij.i2n_n2i_id          ~> int_encode_inverse
+  Nat_Int_Bij.n2i_i2n_id          ~> int_decode_inverse
+  Nat_Int_Bij.surj_nat_to_int_bij ~> surj_int_encode
+  Nat_Int_Bij.surj_int_to_nat_bij ~> surj_int_decode
+  Nat_Int_Bij.inj_nat_to_int_bij  ~> inj_int_encode
+  Nat_Int_Bij.inj_int_to_nat_bij  ~> inj_int_decode
+  Nat_Int_Bij.bij_nat_to_int_bij  ~> bij_int_encode
+  Nat_Int_Bij.bij_int_to_nat_bij  ~> bij_int_decode
+
 
 *** ML ***
 
--- a/doc-src/Nitpick/nitpick.tex	Thu Mar 18 13:56:34 2010 +0100
+++ b/doc-src/Nitpick/nitpick.tex	Thu Mar 18 13:57:00 2010 +0100
@@ -2617,6 +2617,12 @@
 where the $P_i$'s are side conditions that do not involve $c$ and $M$ is an
 optional monotonic operator. The order of the assumptions is irrelevant.
 
+\flushitem{\textit{nitpick\_choice\_spec}}
+
+\nopagebreak
+This attribute specifies the (free-form) specification of a constant defined
+using the \hbox{(\textbf{ax\_})}\allowbreak\textbf{specification} command.
+
 \end{itemize}
 
 When faced with a constant, Nitpick proceeds as follows:
@@ -2629,7 +2635,12 @@
 the constant is not empty, it uses these rules as the specification of the
 constant.
 
-\item[3.] Otherwise, it looks up the definition of the constant:
+\item[3.] Otherwise, if the constant was defined using the
+\hbox{(\textbf{ax\_})}\allowbreak\textbf{specification} command and the
+\textit{nitpick\_choice\_spec} set associated with the constant is not empty, it
+uses these theorems as the specification of the constant.
+
+\item[4.] Otherwise, it looks up the definition of the constant:
 
 \begin{enum}
 \item[1.] If the \textit{nitpick\_def} set associated with the constant
@@ -2815,6 +2826,9 @@
 representation of functions synthesized by Isabelle, which is an implementation
 detail.
 
+\item[$\bullet$] Axioms that restrict the possible values of the
+\textit{undefined} constant are in general ignored.
+
 \item[$\bullet$] Nitpick maintains a global cache of wellfoundedness conditions,
 which can become invalid if you change the definition of an inductive predicate
 that is registered in the cache. To clear the cache,
--- a/src/HOL/Divides.thy	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Divides.thy	Thu Mar 18 13:57:00 2010 +0100
@@ -588,8 +588,16 @@
   from divmod_nat_rel have divmod_nat_m_n: "divmod_nat_rel m n (m div n, m mod n)" .
   with assms have m_div_n: "m div n \<ge> 1"
     by (cases "m div n") (auto simp add: divmod_nat_rel_def)
-  from assms divmod_nat_m_n have "divmod_nat_rel (m - n) n (m div n - Suc 0, m mod n)"
-    by (cases "m div n") (auto simp add: divmod_nat_rel_def)
+  have "divmod_nat_rel (m - n) n (m div n - Suc 0, m mod n)"
+  proof -
+    from assms have
+      "n \<noteq> 0"
+      "\<And>k. m = Suc k * n + m mod n ==> m - n = (Suc k - Suc 0) * n + m mod n"
+      by simp_all
+    then show ?thesis using assms divmod_nat_m_n 
+      by (cases "m div n")
+         (simp_all only: divmod_nat_rel_def fst_conv snd_conv, simp_all)
+  qed
   with divmod_nat_eq have "divmod_nat (m - n) n = (m div n - Suc 0, m mod n)" by simp
   moreover from divmod_nat_div_mod have "divmod_nat (m - n) n = ((m - n) div n, (m - n) mod n)" .
   ultimately have "m div n = Suc ((m - n) div n)"
@@ -1122,7 +1130,7 @@
 
 lemma mod2_gr_0 [simp]: "0 < (m\<Colon>nat) mod 2 \<longleftrightarrow> m mod 2 = 1"
 proof -
-  { fix n :: nat have  "(n::nat) < 2 \<Longrightarrow> n = 0 \<or> n = 1" by (induct n) simp_all }
+  { fix n :: nat have  "(n::nat) < 2 \<Longrightarrow> n = 0 \<or> n = 1" by (cases n) simp_all }
   moreover have "m mod 2 < 2" by simp
   ultimately have "m mod 2 = 0 \<or> m mod 2 = 1" .
   then show ?thesis by auto
@@ -1166,8 +1174,11 @@
 lemma Suc_n_div_2_gt_zero [simp]: "(0::nat) < n ==> 0 < (n + 1) div 2"
 by (cases n) simp_all
 
-lemma div_2_gt_zero [simp]: "(1::nat) < n ==> 0 < n div 2" 
-using Suc_n_div_2_gt_zero [of "n - 1"] by simp
+lemma div_2_gt_zero [simp]: assumes A: "(1::nat) < n" shows "0 < n div 2"
+proof -
+  from A have B: "0 < n - 1" and C: "n - 1 + 1 = n" by simp_all
+  from Suc_n_div_2_gt_zero [OF B] C show ?thesis by simp 
+qed
 
   (* Potential use of algebra : Equality modulo n*)
 lemma mod_mult_self3 [simp]: "(k*n + m) mod n = m mod (n::nat)"
@@ -2092,15 +2103,16 @@
                   div_pos_pos_trivial)
 qed
 
-lemma neg_zdiv_mult_2: "a \<le> (0::int) ==> (1 + 2*b) div (2*a) = (b+1) div a"
-apply (subgoal_tac " (1 + 2* (-b - 1)) div (2 * (-a)) = (-b - 1) div (-a) ")
-apply (rule_tac [2] pos_zdiv_mult_2)
-apply (auto simp add: right_diff_distrib)
-apply (subgoal_tac " (-1 - (2 * b)) = - (1 + (2 * b))")
-apply (simp only: zdiv_zminus_zminus diff_minus minus_add_distrib [symmetric])
-apply (simp_all add: algebra_simps)
-apply (simp only: ab_diff_minus minus_add_distrib [symmetric] number_of_Min zdiv_zminus_zminus)
-done
+lemma neg_zdiv_mult_2: 
+  assumes A: "a \<le> (0::int)" shows "(1 + 2*b) div (2*a) = (b+1) div a"
+proof -
+  have R: "1 + - (2 * (b + 1)) = - (1 + 2 * b)" by simp
+  have "(1 + 2 * (-b - 1)) div (2 * (-a)) = (-b - 1) div (-a)"
+    by (rule pos_zdiv_mult_2, simp add: A)
+  thus ?thesis
+    by (simp only: R zdiv_zminus_zminus diff_minus
+      minus_add_distrib [symmetric] mult_minus_right)
+qed
 
 lemma zdiv_number_of_Bit0 [simp]:
      "number_of (Int.Bit0 v) div number_of (Int.Bit0 w) =  
--- a/src/HOL/HOL.thy	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/HOL.thy	Thu Mar 18 13:57:00 2010 +0100
@@ -2022,7 +2022,7 @@
 )
 structure Nitpick_Choice_Specs = Named_Thms
 (
-  val name = "nitpick_choice_specs"
+  val name = "nitpick_choice_spec"
   val description = "choice specification of constants as needed by Nitpick"
 )
 *}
--- a/src/HOL/Int.thy	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Int.thy	Thu Mar 18 13:57:00 2010 +0100
@@ -1829,11 +1829,12 @@
 lemma pos_zmult_eq_1_iff_lemma: "(m * n = 1) ==> m = (1::int) | m = -1"
 by (insert abs_zmult_eq_1 [of m n], arith)
 
-lemma pos_zmult_eq_1_iff: "0 < (m::int) ==> (m * n = 1) = (m = 1 & n = 1)"
-apply (auto dest: pos_zmult_eq_1_iff_lemma) 
-apply (simp add: mult_commute [of m]) 
-apply (frule pos_zmult_eq_1_iff_lemma, auto) 
-done
+lemma pos_zmult_eq_1_iff:
+  assumes "0 < (m::int)" shows "(m * n = 1) = (m = 1 & n = 1)"
+proof -
+  from assms have "m * n = 1 ==> m = 1" by (auto dest: pos_zmult_eq_1_iff_lemma)
+  thus ?thesis by (auto dest: pos_zmult_eq_1_iff_lemma)
+qed
 
 lemma zmult_eq_1_iff: "(m*n = (1::int)) = ((m = 1 & n = 1) | (m = -1 & n = -1))"
 apply (rule iffI) 
--- a/src/HOL/Nat_Numeral.thy	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Nat_Numeral.thy	Thu Mar 18 13:57:00 2010 +0100
@@ -643,8 +643,9 @@
   fixes z :: "'a::number_ring"
   shows "z ^ number_of (Int.Bit1 w) = (if (0::int) <= number_of w
      then (let w = z ^ (number_of w) in z * w * w) else 1)"
-apply (auto simp add: Let_def Bit1_def nat_number_of_def number_of_is_id
-  mult_assoc nat_add_distrib power_add not_le simp del: nat_number_of)
+unfolding Let_def Bit1_def nat_number_of_def number_of_is_id
+apply (cases "0 <= w")
+apply (simp only: mult_assoc nat_add_distrib power_add, simp)
 apply (simp add: not_le mult_2 [symmetric] add_assoc)
 done
 
@@ -673,9 +674,10 @@
   "number_of (Int.Bit1 w) =
     (if neg (number_of w :: int) then 0
      else let n = number_of w in Suc (n + n))"
-apply (auto simp add: Let_def Bit1_def nat_number_of_def number_of_is_id neg_def
-  nat_add_distrib simp del: nat_number_of)
+unfolding Let_def Bit1_def nat_number_of_def number_of_is_id neg_def
+apply (cases "w < 0")
 apply (simp add: mult_2 [symmetric] add_assoc)
+apply (simp only: nat_add_distrib, simp)
 done
 
 lemmas nat_number =
--- a/src/HOL/Nitpick_Examples/Mono_Nits.thy	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Nitpick_Examples/Mono_Nits.thy	Thu Mar 18 13:57:00 2010 +0100
@@ -31,7 +31,8 @@
    unrolled_preds = Unsynchronized.ref [], wf_cache = Unsynchronized.ref [],
    constr_cache = Unsynchronized.ref []}
 (* term -> bool *)
-fun is_mono t = Nitpick_Mono.formulas_monotonic hol_ctxt false @{typ 'a} ([t], [])
+fun is_mono t =
+  Nitpick_Mono.formulas_monotonic hol_ctxt false @{typ 'a} ([t], [])
 fun is_const t =
   let val T = fastype_of t in
     is_mono (Logic.mk_implies (Logic.mk_equals (Free ("dummyP", T), t),
--- a/src/HOL/Tools/Nitpick/HISTORY	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Tools/Nitpick/HISTORY	Thu Mar 18 13:57:00 2010 +0100
@@ -14,6 +14,7 @@
   * Fixed soundness bugs related to "destroy_constrs" optimization and record
     getters
   * Fixed soundness bug related to higher-order constructors
+  * Added cache to speed up repeated Kodkod invocations on the same problems
   * Renamed "MiniSatJNI", "zChaffJNI", "BerkMinAlloy", and "SAT4JLight" to
  	"MiniSat_JNI", "zChaff_JNI", "BerkMin_Alloy", and "SAT4J_Light"
 
--- a/src/HOL/Tools/Nitpick/kodkod.ML	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Tools/Nitpick/kodkod.ML	Thu Mar 18 13:57:00 2010 +0100
@@ -169,7 +169,7 @@
   val max_arity : int -> int
   val arity_of_rel_expr : rel_expr -> int
   val is_problem_trivially_false : problem -> bool
-  val problems_equivalent : problem -> problem -> bool
+  val problems_equivalent : problem * problem -> bool
   val solve_any_problem :
     bool -> Time.time option -> int -> int -> problem list -> outcome
 end;
@@ -500,19 +500,28 @@
 fun is_problem_trivially_false ({formula = False, ...} : problem) = true
   | is_problem_trivially_false _ = false
 
-(* string -> bool *)
-val is_relevant_setting = not o member (op =) ["solver", "delay"]
+(* string -> string list *)
+val chop_solver = take 2 o space_explode ","
 
-(* problem -> problem -> bool *)
-fun problems_equivalent (p1 : problem) (p2 : problem) =
+(* setting list * setting list -> bool *)
+fun settings_equivalent ([], []) = true
+  | settings_equivalent ((key1, value1) :: settings1,
+                         (key2, value2) :: settings2) =
+    key1 = key2 andalso
+    (value1 = value2 orelse key1 = "delay" orelse
+     (key1 = "solver" andalso chop_solver value1 = chop_solver value2)) andalso
+    settings_equivalent (settings1, settings2)
+  | settings_equivalent _ = false
+
+(* problem * problem -> bool *)
+fun problems_equivalent (p1 : problem, p2 : problem) =
   #univ_card p1 = #univ_card p2 andalso
   #formula p1 = #formula p2 andalso
   #bounds p1 = #bounds p2 andalso
   #expr_assigns p1 = #expr_assigns p2 andalso
   #tuple_assigns p1 = #tuple_assigns p2 andalso
   #int_bounds p1 = #int_bounds p2 andalso
-  filter (is_relevant_setting o fst) (#settings p1)
-  = filter (is_relevant_setting o fst) (#settings p2)
+  settings_equivalent (#settings p1, #settings p2)
 
 (** Serialization of problem **)
 
@@ -1005,10 +1014,6 @@
           |>> rev ||> rev)
   handle IO.Io _ => (true, ([], [])) | OS.SysErr _ => (true, ([], []))
 
-(* The fudge term below is to account for Kodkodi's slow start-up time, which
-   is partly due to the JVM and partly due to the ML "bash" function. *)
-val fudge_ms = 250
-
 (** Main Kodkod entry point **)
 
 val created_temp_dir = Unsynchronized.ref false
@@ -1024,8 +1029,20 @@
               else (created_temp_dir := true; File.mkdir (Path.explode dir))
     in (serial_string (), dir) end
 
+(* The fudge term below is to account for Kodkodi's slow start-up time, which
+   is partly due to the JVM and partly due to the ML "bash" function. *)
+val fudge_ms = 250
+
+(* Time.time option -> int *)
+fun milliseconds_until_deadline deadline =
+  case deadline of
+    NONE => ~1
+  | SOME time =>
+    Int.max (0, Time.toMilliseconds (Time.- (time, Time.now ())) - fudge_ms)
+
 (* bool -> Time.time option -> int -> int -> problem list -> outcome *)
-fun solve_any_problem overlord deadline max_threads max_solutions problems =
+fun uncached_solve_any_problem overlord deadline max_threads max_solutions
+                               problems =
   let
     val j = find_index (curry (op =) True o #formula) problems
     val indexed_problems = if j >= 0 then
@@ -1061,12 +1078,7 @@
           else List.app (K () o try File.rm) [in_path, out_path, err_path]
       in
         let
-          val ms =
-            case deadline of
-              NONE => ~1
-            | SOME time =>
-              Int.max (0, Time.toMilliseconds (Time.- (time, Time.now ()))
-                          - fudge_ms)
+          val ms = milliseconds_until_deadline deadline
           val outcome =
             let
               val code =
@@ -1135,4 +1147,35 @@
       end
   end
 
+val cached_outcome =
+  Synchronized.var "Kodkod.cached_outcome"
+                   (NONE : ((int * problem list) * outcome) option)
+
+(* bool -> Time.time option -> int -> int -> problem list -> outcome *)
+fun solve_any_problem overlord deadline max_threads max_solutions problems =
+  let
+    (* unit -> outcome *)
+    fun do_solve () = uncached_solve_any_problem overlord deadline max_threads
+                                                 max_solutions problems
+  in
+    if overlord then
+      do_solve ()
+    else
+      case AList.lookup (fn ((max1, ps1), (max2, ps2)) =>
+                            max1 = max2 andalso length ps1 = length ps2 andalso
+                            forall problems_equivalent (ps1 ~~ ps2))
+                        (the_list (Synchronized.value cached_outcome))
+                        (max_solutions, problems) of
+        SOME outcome => outcome
+      | NONE =>
+        let val outcome = do_solve () in
+          (case outcome of
+             Normal (ps, js, "") =>
+             Synchronized.change cached_outcome
+                                 (K (SOME ((max_solutions, problems), outcome)))
+           | _ => ());
+          outcome
+        end
+  end
+
 end;
--- a/src/HOL/Tools/Nitpick/nitpick.ML	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Tools/Nitpick/nitpick.ML	Thu Mar 18 13:57:00 2010 +0100
@@ -777,8 +777,8 @@
                         |> filter (fn j =>
                                       j >= 0 andalso
                                       scopes_equivalent
-                                          (#scope (snd (nth problems j)))
-                                          (#scope (snd (nth problems (j + 1)))))
+                                          (#scope (snd (nth problems j)),
+                                           #scope (snd (nth problems (j + 1)))))
                       val bye_js = sort_distinct int_ord (map fst sat_ps @
                                                           unsat_js @ co_js)
                       val problems =
@@ -862,8 +862,7 @@
              SOME problem =>
              (problems
               |> (null problems orelse
-                  not (KK.problems_equivalent (fst problem)
-                                              (fst (hd problems))))
+                  not (KK.problems_equivalent (fst problem, fst (hd problems))))
                   ? cons problem, donno)
            | NONE => (problems, donno + 1))
         val (problems, donno) =
@@ -904,7 +903,7 @@
 
     (* rich_problem list -> scope -> int *)
     fun scope_count (problems : rich_problem list) scope =
-      length (filter (scopes_equivalent scope o #scope o snd) problems)
+      length (filter (curry scopes_equivalent scope o #scope o snd) problems)
     (* string -> string *)
     fun excipit did_so_and_so =
       let
--- a/src/HOL/Tools/Nitpick/nitpick_mono.ML	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Tools/Nitpick/nitpick_mono.ML	Thu Mar 18 13:57:00 2010 +0100
@@ -50,6 +50,7 @@
    datatype_mcache: ((string * typ list) * mtyp) list Unsynchronized.ref,
    constr_mcache: (styp * mtyp) list Unsynchronized.ref}
 
+exception UNSOLVABLE of unit
 exception MTYPE of string * mtyp list * typ list
 exception MTERM of string * mterm list
 
@@ -381,9 +382,7 @@
 type comp = sign_atom * sign_atom * comp_op * var list
 type sign_expr = literal list
 
-datatype constraint_set =
-  UnsolvableCSet |
-  CSet of literal list * comp list * sign_expr list
+type constraint_set = literal list * comp list * sign_expr list
 
 (* comp_op -> string *)
 fun string_for_comp_op Eq = "="
@@ -394,9 +393,6 @@
   | string_for_sign_expr lits =
     space_implode " \<or> " (map string_for_literal lits)
 
-(* constraint_set *)
-val slack = CSet ([], [], [])
-
 (* literal -> literal list option -> literal list option *)
 fun do_literal _ NONE = NONE
   | do_literal (x, sn) (SOME lits) =
@@ -455,13 +451,12 @@
                  [M1, M2], [])
 
 (* comp_op -> mtyp -> mtyp -> constraint_set -> constraint_set *)
-fun add_mtype_comp _ _ _ UnsolvableCSet = UnsolvableCSet
-  | add_mtype_comp cmp M1 M2 (CSet (lits, comps, sexps)) =
+fun add_mtype_comp cmp M1 M2 (lits, comps, sexps) =
     (print_g ("*** Add " ^ string_for_mtype M1 ^ " " ^ string_for_comp_op cmp ^
               " " ^ string_for_mtype M2);
      case do_mtype_comp cmp [] M1 M2 (SOME (lits, comps)) of
-       NONE => (print_g "**** Unsolvable"; UnsolvableCSet)
-     | SOME (lits, comps) => CSet (lits, comps, sexps))
+       NONE => (print_g "**** Unsolvable"; raise UNSOLVABLE ())
+     | SOME (lits, comps) => (lits, comps, sexps))
 
 (* mtyp -> mtyp -> constraint_set -> constraint_set *)
 val add_mtypes_equal = add_mtype_comp Eq
@@ -505,13 +500,12 @@
     raise MTYPE ("Nitpick_Mono.do_notin_mtype_fv", [M], [])
 
 (* sign -> mtyp -> constraint_set -> constraint_set *)
-fun add_notin_mtype_fv _ _ UnsolvableCSet = UnsolvableCSet
-  | add_notin_mtype_fv sn M (CSet (lits, comps, sexps)) =
+fun add_notin_mtype_fv sn M (lits, comps, sexps) =
     (print_g ("*** Add " ^ string_for_mtype M ^ " is " ^
               (case sn of Minus => "concrete" | Plus => "complete") ^ ".");
      case do_notin_mtype_fv sn [] M (SOME (lits, sexps)) of
-       NONE => (print_g "**** Unsolvable"; UnsolvableCSet)
-     | SOME (lits, sexps) => CSet (lits, comps, sexps))
+       NONE => (print_g "**** Unsolvable"; raise UNSOLVABLE ())
+     | SOME (lits, sexps) => (lits, comps, sexps))
 
 (* mtyp -> constraint_set -> constraint_set *)
 val add_mtype_is_concrete = add_notin_mtype_fv Minus
@@ -576,8 +570,7 @@
   end
 
 (* var -> constraint_set -> literal list option *)
-fun solve _ UnsolvableCSet = (print_g "*** Problem: Unsolvable"; NONE)
-  | solve max_var (CSet (lits, comps, sexps)) =
+fun solve max_var (lits, comps, sexps) =
     let
       (* (int -> bool option) -> literal list option *)
       fun do_assigns assigns =
@@ -613,7 +606,6 @@
 type accumulator = mtype_context * constraint_set
 
 val initial_gamma = {bound_Ts = [], bound_Ms = [], frees = [], consts = []}
-val unsolvable_accum = (initial_gamma, UnsolvableCSet)
 
 (* typ -> mtyp -> mtype_context -> mtype_context *)
 fun push_bound T M {bound_Ts, bound_Ms, frees, consts} =
@@ -684,10 +676,6 @@
         M as MPair (a_M, b_M) =>
         pair (MFun (M, S Minus, if n = 0 then a_M else b_M))
       | M => raise MTYPE ("Nitpick_Mono.consider_term.do_nth_pair_sel", [M], [])
-    (* mtyp * accumulator *)
-    val mtype_unsolvable = (dummy_M, unsolvable_accum)
-    (* term -> mterm * accumulator *)
-    fun mterm_unsolvable t = (MRaw (t, dummy_M), unsolvable_accum)
     (* term -> string -> typ -> term -> term -> term -> accumulator
        -> mterm * accumulator *)
     fun do_bounded_quantifier t0 abs_s abs_T connective_t bound_t body_t accum =
@@ -710,8 +698,7 @@
                            body_m))), accum)
       end
     (* term -> accumulator -> mterm * accumulator *)
-    and do_term t (_, UnsolvableCSet) = mterm_unsolvable t
-      | do_term t (accum as (gamma as {bound_Ts, bound_Ms, frees, consts},
+    and do_term t (accum as (gamma as {bound_Ts, bound_Ms, frees, consts},
                              cset)) =
         (case t of
            Const (x as (s, T)) =>
@@ -734,8 +721,8 @@
                   |>> mtype_of_mterm
                 end
               | @{const_name "op ="} => do_equals T accum
-              | @{const_name The} => (print_g "*** The"; mtype_unsolvable)
-              | @{const_name Eps} => (print_g "*** Eps"; mtype_unsolvable)
+              | @{const_name The} => (print_g "*** The"; raise UNSOLVABLE ())
+              | @{const_name Eps} => (print_g "*** Eps"; raise UNSOLVABLE ())
               | @{const_name If} =>
                 do_robust_set_operation (range_type T) accum
                 |>> curry3 MFun bool_M (S Minus)
@@ -855,7 +842,7 @@
                 (M, ({bound_Ts = bound_Ts, bound_Ms = bound_Ms,
                       frees = (x, M) :: frees, consts = consts}, cset))
               end) |>> curry MRaw t
-         | Var _ => (print_g "*** Var"; mterm_unsolvable t)
+         | Var _ => (print_g "*** Var"; raise UNSOLVABLE ())
          | Bound j => (MRaw (t, nth bound_Ms j), accum)
          | Abs (s, T, t') =>
            (case fin_fun_body T (fastype_of1 (T :: bound_Ts, t')) t' of
@@ -893,27 +880,17 @@
              val (m1, accum) = do_term t1 accum
              val (m2, accum) = do_term t2 accum
            in
-             case accum of
-               (_, UnsolvableCSet) => mterm_unsolvable t
-             | _ =>
-               let
-                 val T11 = domain_type (fastype_of1 (bound_Ts, t1))
-                 val T2 = fastype_of1 (bound_Ts, t2)
-                 val M11 = mtype_of_mterm m1 |> dest_MFun |> #1
-                 val M2 = mtype_of_mterm m2
-               in (MApp (m1, m2), accum ||> add_is_sub_mtype M2 M11) end
+             let
+               val T11 = domain_type (fastype_of1 (bound_Ts, t1))
+               val T2 = fastype_of1 (bound_Ts, t2)
+               val M11 = mtype_of_mterm m1 |> dest_MFun |> #1
+               val M2 = mtype_of_mterm m2
+             in (MApp (m1, m2), accum ||> add_is_sub_mtype M2 M11) end
            end)
         |> tap (fn (m, _) => print_g ("  \<Gamma> \<turnstile> " ^
                                       string_for_mterm ctxt m))
   in do_term end
 
-(*
-    accum |> (case a of
-                S Minus => accum 
-              | S Plus => unsolvable_accum
-              | V x => do_literal (x, Minus) lits)
-*)
-
 (* int -> mtyp -> accumulator -> accumulator *)
 fun force_minus_funs 0 _ = I
   | force_minus_funs n (M as MFun (M1, _, M2)) =
@@ -949,9 +926,7 @@
     (* term -> accumulator -> mterm * accumulator *)
     val do_term = consider_term mdata
     (* sign -> term -> accumulator -> mterm * accumulator *)
-    fun do_formula _ t (_, UnsolvableCSet) =
-        (MRaw (t, dummy_M), unsolvable_accum)
-      | do_formula sn t accum =
+    fun do_formula sn t accum =
         let
           (* styp -> string -> typ -> term -> mterm * accumulator *)
           fun do_quantifier (quant_x as (quant_s, _)) abs_s abs_T body_t =
@@ -1084,9 +1059,7 @@
           (MApp (MApp (MRaw (t0, mtype_for (fastype_of t0)), m1), m2), accum)
         end
       (* term -> accumulator -> accumulator *)
-      and do_formula t (_, UnsolvableCSet) =
-          (MRaw (t, dummy_M), unsolvable_accum)
-        | do_formula t accum =
+      and do_formula t accum =
           case t of
             (t0 as Const (@{const_name all}, _)) $ Abs (s1, T1, t1) =>
             do_all t0 s1 T1 t1 accum
@@ -1134,7 +1107,7 @@
                      Syntax.string_of_typ ctxt alpha_T)
     val mdata as {max_fresh, constr_mcache, ...} =
       initial_mdata hol_ctxt binarize no_harmless alpha_T
-    val accum = (initial_gamma, slack)
+    val accum = (initial_gamma, ([], [], []))
     val (nondef_ms, accum) =
       ([], accum) |> amass (consider_general_formula mdata Plus) (hd nondef_ts)
                   |> fold (amass (consider_nondefinitional_axiom mdata))
@@ -1147,7 +1120,8 @@
                     SOME (lits, (nondef_ms, def_ms), !constr_mcache))
     | _ => NONE
   end
-  handle MTYPE (loc, Ms, Ts) =>
+  handle UNSOLVABLE () => NONE
+       | MTYPE (loc, Ms, Ts) =>
          raise BAD (loc, commas (map string_for_mtype Ms @
                                  map (Syntax.string_of_typ ctxt) Ts))
        | MTERM (loc, ms) =>
@@ -1166,108 +1140,112 @@
                   binarize finitizes alpha_T tsp =
   case infer "Finiteness" true hol_ctxt binarize alpha_T tsp of
     SOME (lits, msp, constr_mtypes) =>
-    let
-      (* typ -> sign_atom -> bool *)
-      fun should_finitize T a =
-        case triple_lookup (type_match thy) finitizes T of
-          SOME (SOME false) => false
-        | _ => resolve_sign_atom lits a = S Plus
-      (* typ -> mtyp -> typ *)
-      fun type_from_mtype T M =
-        case (M, T) of
-          (MAlpha, _) => T
-        | (MFun (M1, a, M2), Type (@{type_name fun}, Ts)) =>
-          Type (if should_finitize T a then @{type_name fin_fun}
-                else @{type_name fun}, map2 type_from_mtype Ts [M1, M2])
-        | (MPair (M1, M2), Type (@{type_name "*"}, Ts)) =>
-          Type (@{type_name "*"}, map2 type_from_mtype Ts [M1, M2])
-        | (MType _, _) => T
-        | _ => raise MTYPE ("Nitpick_Mono.finitize_funs.type_from_mtype",
-                            [M], [T])
-      (* styp -> styp *)
-      fun finitize_constr (x as (s, T)) =
-        (s, case AList.lookup (op =) constr_mtypes x of
-              SOME M => type_from_mtype T M
-            | NONE => T)
-      (* typ list -> mterm -> term *)
-      fun term_from_mterm Ts m =
-        case m of
-          MRaw (t, M) =>
-          let
-            val T = fastype_of1 (Ts, t)
-            val T' = type_from_mtype T M
-          in
-            case t of
-              Const (x as (s, _)) =>
-              if s = @{const_name insert} then
-                case nth_range_type 2 T' of
-                  set_T' as Type (@{type_name fin_fun}, [elem_T', _]) =>
-                    Abs (Name.uu, elem_T', Abs (Name.uu, set_T',
-                        Const (@{const_name If},
-                               bool_T --> set_T' --> set_T' --> set_T')
-                        $ (Const (@{const_name is_unknown}, elem_T' --> bool_T)
-                           $ Bound 1)
-                        $ (Const (@{const_name unknown}, set_T'))
-                        $ (coerce_term hol_ctxt Ts T' T (Const x)
-                           $ Bound 1 $ Bound 0)))
-                | _ => Const (s, T')
-              else if s = @{const_name finite} then
-                case domain_type T' of
-                  set_T' as Type (@{type_name fin_fun}, _) =>
-                  Abs (Name.uu, set_T', @{const True})
-                | _ => Const (s, T')
-              else if s = @{const_name "=="} orelse
-                      s = @{const_name "op ="} then
-                Const (s, T')
-              else if is_built_in_const thy stds fast_descrs x then
-                coerce_term hol_ctxt Ts T' T t
-              else if is_constr thy stds x then
-                Const (finitize_constr x)
-              else if is_sel s then
-                let
-                  val n = sel_no_from_name s
-                  val x' = x |> binarized_and_boxed_constr_for_sel hol_ctxt
-                                                                   binarize
-                             |> finitize_constr
-                  val x'' = binarized_and_boxed_nth_sel_for_constr hol_ctxt
-                                                                   binarize x' n
-                in Const x'' end
-              else
-                Const (s, T')
-            | Free (s, T) => Free (s, type_from_mtype T M)
-            | Bound _ => t
-            | _ => raise MTERM ("Nitpick_Mono.finitize_funs.term_from_mterm",
-                                [m])
-          end
-        | MApp (m1, m2) =>
-          let
-            val (t1, t2) = pairself (term_from_mterm Ts) (m1, m2)
-            val (T1, T2) = pairself (curry fastype_of1 Ts) (t1, t2)
-            val (t1', T2') =
-              case T1 of
-                Type (s, [T11, T12]) => 
-                (if s = @{type_name fin_fun} then
-                   select_nth_constr_arg thy stds (fin_fun_constr T11 T12) t1 0
-                                         (T11 --> T12)
-                 else
-                   t1, T11)
-              | _ => raise TYPE ("Nitpick_Mono.finitize_funs.term_from_mterm",
-                                 [T1], [])
-          in betapply (t1', coerce_term hol_ctxt Ts T2' T2 t2) end
-        | MAbs (s, T, M, a, m') =>
-          let
-            val T = type_from_mtype T M
-            val t' = term_from_mterm (T :: Ts) m'
-            val T' = fastype_of1 (T :: Ts, t')
-          in
-            Abs (s, T, t')
-            |> should_finitize (T --> T') a
-               ? construct_value thy stds (fin_fun_constr T T') o single
-          end
-    in
-      Unsynchronized.change constr_cache (map (apsnd (map finitize_constr)));
-      pairself (map (term_from_mterm [])) msp
-    end
+    if forall (curry (op =) Minus o snd) lits then
+      tsp
+    else
+      let
+        (* typ -> sign_atom -> bool *)
+        fun should_finitize T a =
+          case triple_lookup (type_match thy) finitizes T of
+            SOME (SOME false) => false
+          | _ => resolve_sign_atom lits a = S Plus
+        (* typ -> mtyp -> typ *)
+        fun type_from_mtype T M =
+          case (M, T) of
+            (MAlpha, _) => T
+          | (MFun (M1, a, M2), Type (@{type_name fun}, Ts)) =>
+            Type (if should_finitize T a then @{type_name fin_fun}
+                  else @{type_name fun}, map2 type_from_mtype Ts [M1, M2])
+          | (MPair (M1, M2), Type (@{type_name "*"}, Ts)) =>
+            Type (@{type_name "*"}, map2 type_from_mtype Ts [M1, M2])
+          | (MType _, _) => T
+          | _ => raise MTYPE ("Nitpick_Mono.finitize_funs.type_from_mtype",
+                              [M], [T])
+        (* styp -> styp *)
+        fun finitize_constr (x as (s, T)) =
+          (s, case AList.lookup (op =) constr_mtypes x of
+                SOME M => type_from_mtype T M
+              | NONE => T)
+        (* typ list -> mterm -> term *)
+        fun term_from_mterm Ts m =
+          case m of
+            MRaw (t, M) =>
+            let
+              val T = fastype_of1 (Ts, t)
+              val T' = type_from_mtype T M
+            in
+              case t of
+                Const (x as (s, _)) =>
+                if s = @{const_name insert} then
+                  case nth_range_type 2 T' of
+                    set_T' as Type (@{type_name fin_fun}, [elem_T', _]) =>
+                      Abs (Name.uu, elem_T', Abs (Name.uu, set_T',
+                          Const (@{const_name If},
+                                 bool_T --> set_T' --> set_T' --> set_T')
+                          $ (Const (@{const_name is_unknown},
+                                    elem_T' --> bool_T) $ Bound 1)
+                          $ (Const (@{const_name unknown}, set_T'))
+                          $ (coerce_term hol_ctxt Ts T' T (Const x)
+                             $ Bound 1 $ Bound 0)))
+                  | _ => Const (s, T')
+                else if s = @{const_name finite} then
+                  case domain_type T' of
+                    set_T' as Type (@{type_name fin_fun}, _) =>
+                    Abs (Name.uu, set_T', @{const True})
+                  | _ => Const (s, T')
+                else if s = @{const_name "=="} orelse
+                        s = @{const_name "op ="} then
+                  Const (s, T')
+                else if is_built_in_const thy stds fast_descrs x then
+                  coerce_term hol_ctxt Ts T' T t
+                else if is_constr thy stds x then
+                  Const (finitize_constr x)
+                else if is_sel s then
+                  let
+                    val n = sel_no_from_name s
+                    val x' =
+                      x |> binarized_and_boxed_constr_for_sel hol_ctxt binarize
+                        |> finitize_constr
+                    val x'' =
+                      binarized_and_boxed_nth_sel_for_constr hol_ctxt binarize
+                                                             x' n
+                  in Const x'' end
+                else
+                  Const (s, T')
+              | Free (s, T) => Free (s, type_from_mtype T M)
+              | Bound _ => t
+              | _ => raise MTERM ("Nitpick_Mono.finitize_funs.term_from_mterm",
+                                  [m])
+            end
+          | MApp (m1, m2) =>
+            let
+              val (t1, t2) = pairself (term_from_mterm Ts) (m1, m2)
+              val (T1, T2) = pairself (curry fastype_of1 Ts) (t1, t2)
+              val (t1', T2') =
+                case T1 of
+                  Type (s, [T11, T12]) => 
+                  (if s = @{type_name fin_fun} then
+                     select_nth_constr_arg thy stds (fin_fun_constr T11 T12) t1
+                                           0 (T11 --> T12)
+                   else
+                     t1, T11)
+                | _ => raise TYPE ("Nitpick_Mono.finitize_funs.term_from_mterm",
+                                   [T1], [])
+            in betapply (t1', coerce_term hol_ctxt Ts T2' T2 t2) end
+          | MAbs (s, T, M, a, m') =>
+            let
+              val T = type_from_mtype T M
+              val t' = term_from_mterm (T :: Ts) m'
+              val T' = fastype_of1 (T :: Ts, t')
+            in
+              Abs (s, T, t')
+              |> should_finitize (T --> T') a
+                 ? construct_value thy stds (fin_fun_constr T T') o single
+            end
+      in
+        Unsynchronized.change constr_cache (map (apsnd (map finitize_constr)));
+        pairself (map (term_from_mterm [])) msp
+      end
   | NONE => tsp
 
 end;
--- a/src/HOL/Tools/Nitpick/nitpick_scope.ML	Thu Mar 18 13:56:34 2010 +0100
+++ b/src/HOL/Tools/Nitpick/nitpick_scope.ML	Thu Mar 18 13:57:00 2010 +0100
@@ -46,7 +46,7 @@
   val spec_of_type : scope -> typ -> int * int
   val pretties_for_scope : scope -> bool -> Pretty.T list
   val multiline_string_for_scope : scope -> string
-  val scopes_equivalent : scope -> scope -> bool
+  val scopes_equivalent : scope * scope -> bool
   val scope_less_eq : scope -> scope -> bool
   val all_scopes :
     hol_context -> bool -> int -> (typ option * int list) list
@@ -213,8 +213,8 @@
     | lines => space_implode "\n" lines
   end
 
-(* scope -> scope -> bool *)
-fun scopes_equivalent (s1 : scope) (s2 : scope) =
+(* scope * scope -> bool *)
+fun scopes_equivalent (s1 : scope, s2 : scope) =
   #datatypes s1 = #datatypes s2 andalso #card_assigns s1 = #card_assigns s2
 fun scope_less_eq (s1 : scope) (s2 : scope) =
   (s1, s2) |> pairself (map snd o #card_assigns) |> op ~~ |> forall (op <=)