src/HOL/Tools/refute.ML
author wenzelm
Sat Jan 14 17:14:06 2006 +0100 (2006-01-14)
changeset 18678 dd0c569fa43d
parent 17493 cf8713d880b1
child 18708 4b3dadb4fe33
permissions -rw-r--r--
sane ERROR handling;
     1 (*  Title:      HOL/Tools/refute.ML
     2     ID:         $Id$
     3     Author:     Tjark Weber
     4     Copyright   2003-2005
     5 
     6 Finite model generation for HOL formulas, using a SAT solver.
     7 *)
     8 
     9 (* ------------------------------------------------------------------------- *)
    10 (* Declares the 'REFUTE' signature as well as a structure 'Refute'.          *)
    11 (* Documentation is available in the Isabelle/Isar theory 'HOL/Refute.thy'.  *)
    12 (* ------------------------------------------------------------------------- *)
    13 
    14 signature REFUTE =
    15 sig
    16 
    17 	exception REFUTE of string * string
    18 
    19 (* ------------------------------------------------------------------------- *)
    20 (* Model/interpretation related code (translation HOL -> propositional logic *)
    21 (* ------------------------------------------------------------------------- *)
    22 
    23 	type params
    24 	type interpretation
    25 	type model
    26 	type arguments
    27 
    28 	exception MAXVARS_EXCEEDED
    29 
    30 	val add_interpreter : string -> (theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option) -> theory -> theory
    31 	val add_printer     : string -> (theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term option) -> theory -> theory
    32 
    33 	val interpret : theory -> model -> arguments -> Term.term -> (interpretation * model * arguments)
    34 
    35 	val print       : theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term
    36 	val print_model : theory -> model -> (int -> bool) -> string
    37 
    38 (* ------------------------------------------------------------------------- *)
    39 (* Interface                                                                 *)
    40 (* ------------------------------------------------------------------------- *)
    41 
    42 	val set_default_param  : (string * string) -> theory -> theory
    43 	val get_default_param  : theory -> string -> string option
    44 	val get_default_params : theory -> (string * string) list
    45 	val actual_params      : theory -> (string * string) list -> params
    46 
    47 	val find_model : theory -> params -> Term.term -> bool -> unit
    48 
    49 	val satisfy_term   : theory -> (string * string) list -> Term.term -> unit  (* tries to find a model for a formula *)
    50 	val refute_term    : theory -> (string * string) list -> Term.term -> unit  (* tries to find a model that refutes a formula *)
    51 	val refute_subgoal : theory -> (string * string) list -> Thm.thm -> int -> unit
    52 
    53 	val setup : (theory -> theory) list
    54 end;
    55 
    56 structure Refute : REFUTE =
    57 struct
    58 
    59 	open PropLogic;
    60 
    61 	(* We use 'REFUTE' only for internal error conditions that should    *)
    62 	(* never occur in the first place (i.e. errors caused by bugs in our *)
    63 	(* code).  Otherwise (e.g. to indicate invalid input data) we use    *)
    64 	(* 'error'.                                                          *)
    65 	exception REFUTE of string * string;  (* ("in function", "cause") *)
    66 
    67 	(* should be raised by an interpreter when more variables would be *)
    68 	(* required than allowed by 'maxvars'                              *)
    69 	exception MAXVARS_EXCEEDED;
    70 
    71 (* ------------------------------------------------------------------------- *)
    72 (* TREES                                                                     *)
    73 (* ------------------------------------------------------------------------- *)
    74 
    75 (* ------------------------------------------------------------------------- *)
    76 (* tree: implements an arbitrarily (but finitely) branching tree as a list   *)
    77 (*       of (lists of ...) elements                                          *)
    78 (* ------------------------------------------------------------------------- *)
    79 
    80 	datatype 'a tree =
    81 		  Leaf of 'a
    82 		| Node of ('a tree) list;
    83 
    84 	(* ('a -> 'b) -> 'a tree -> 'b tree *)
    85 
    86 	fun tree_map f tr =
    87 		case tr of
    88 		  Leaf x  => Leaf (f x)
    89 		| Node xs => Node (map (tree_map f) xs);
    90 
    91 	(* ('a * 'b -> 'a) -> 'a * ('b tree) -> 'a *)
    92 
    93 	fun tree_foldl f =
    94 	let
    95 		fun itl (e, Leaf x)  = f(e,x)
    96 		  | itl (e, Node xs) = Library.foldl (tree_foldl f) (e,xs)
    97 	in
    98 		itl
    99 	end;
   100 
   101 	(* 'a tree * 'b tree -> ('a * 'b) tree *)
   102 
   103 	fun tree_pair (t1, t2) =
   104 		case t1 of
   105 		  Leaf x =>
   106 			(case t2 of
   107 				  Leaf y => Leaf (x,y)
   108 				| Node _ => raise REFUTE ("tree_pair", "trees are of different height (second tree is higher)"))
   109 		| Node xs =>
   110 			(case t2 of
   111 				  (* '~~' will raise an exception if the number of branches in   *)
   112 				  (* both trees is different at the current node                 *)
   113 				  Node ys => Node (map tree_pair (xs ~~ ys))
   114 				| Leaf _  => raise REFUTE ("tree_pair", "trees are of different height (first tree is higher)"));
   115 
   116 (* ------------------------------------------------------------------------- *)
   117 (* params: parameters that control the translation into a propositional      *)
   118 (*         formula/model generation                                          *)
   119 (*                                                                           *)
   120 (* The following parameters are supported (and required (!), except for      *)
   121 (* "sizes"):                                                                 *)
   122 (*                                                                           *)
   123 (* Name          Type    Description                                         *)
   124 (*                                                                           *)
   125 (* "sizes"       (string * int) list                                         *)
   126 (*                       Size of ground types (e.g. 'a=2), or depth of IDTs. *)
   127 (* "minsize"     int     If >0, minimal size of each ground type/IDT depth.  *)
   128 (* "maxsize"     int     If >0, maximal size of each ground type/IDT depth.  *)
   129 (* "maxvars"     int     If >0, use at most 'maxvars' Boolean variables      *)
   130 (*                       when transforming the term into a propositional     *)
   131 (*                       formula.                                            *)
   132 (* "maxtime"     int     If >0, terminate after at most 'maxtime' seconds.   *)
   133 (* "satsolver"   string  SAT solver to be used.                              *)
   134 (* ------------------------------------------------------------------------- *)
   135 
   136 	type params =
   137 		{
   138 			sizes    : (string * int) list,
   139 			minsize  : int,
   140 			maxsize  : int,
   141 			maxvars  : int,
   142 			maxtime  : int,
   143 			satsolver: string
   144 		};
   145 
   146 (* ------------------------------------------------------------------------- *)
   147 (* interpretation: a term's interpretation is given by a variable of type    *)
   148 (*                 'interpretation'                                          *)
   149 (* ------------------------------------------------------------------------- *)
   150 
   151 	type interpretation =
   152 		prop_formula list tree;
   153 
   154 (* ------------------------------------------------------------------------- *)
   155 (* model: a model specifies the size of types and the interpretation of      *)
   156 (*        terms                                                              *)
   157 (* ------------------------------------------------------------------------- *)
   158 
   159 	type model =
   160 		(Term.typ * int) list * (Term.term * interpretation) list;
   161 
   162 (* ------------------------------------------------------------------------- *)
   163 (* arguments: additional arguments required during interpretation of terms   *)
   164 (* ------------------------------------------------------------------------- *)
   165 
   166 	type arguments =
   167 		{
   168 			maxvars   : int,   (* just passed unchanged from 'params' *)
   169 			def_eq    : bool,  (* whether to use 'make_equality' or 'make_def_equality' *)
   170 			(* the following may change during the translation *)
   171 			next_idx  : int,
   172 			bounds    : interpretation list,
   173 			wellformed: prop_formula
   174 		};
   175 
   176 
   177 	structure RefuteDataArgs =
   178 	struct
   179 		val name = "HOL/refute";
   180 		type T =
   181 			{interpreters: (string * (theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option)) list,
   182 			 printers: (string * (theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term option)) list,
   183 			 parameters: string Symtab.table};
   184 		val empty = {interpreters = [], printers = [], parameters = Symtab.empty};
   185 		val copy = I;
   186 		val extend = I;
   187 		fun merge _
   188 			({interpreters = in1, printers = pr1, parameters = pa1},
   189 			 {interpreters = in2, printers = pr2, parameters = pa2}) =
   190 			{interpreters = rev (merge_alists (rev in1) (rev in2)),
   191 			 printers = rev (merge_alists (rev pr1) (rev pr2)),
   192 			 parameters = Symtab.merge (op=) (pa1, pa2)};
   193 		fun print sg {interpreters, printers, parameters} =
   194 			Pretty.writeln (Pretty.chunks
   195 				[Pretty.strs ("default parameters:" :: List.concat (map (fn (name, value) => [name, "=", value]) (Symtab.dest parameters))),
   196 				 Pretty.strs ("interpreters:" :: map fst interpreters),
   197 				 Pretty.strs ("printers:" :: map fst printers)]);
   198 	end;
   199 
   200 	structure RefuteData = TheoryDataFun(RefuteDataArgs);
   201 
   202 
   203 (* ------------------------------------------------------------------------- *)
   204 (* interpret: interprets the term 't' using a suitable interpreter; returns  *)
   205 (*            the interpretation and a (possibly extended) model that keeps  *)
   206 (*            track of the interpretation of subterms                        *)
   207 (* ------------------------------------------------------------------------- *)
   208 
   209 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) *)
   210 
   211 	fun interpret thy model args t =
   212 		(case get_first (fn (_, f) => f thy model args t) (#interpreters (RefuteData.get thy)) of
   213 		  NONE   => raise REFUTE ("interpret", "no interpreter for term " ^ quote (Sign.string_of_term (sign_of thy) t))
   214 		| SOME x => x);
   215 
   216 (* ------------------------------------------------------------------------- *)
   217 (* print: converts the constant denoted by the term 't' into a term using a  *)
   218 (*        suitable printer                                                   *)
   219 (* ------------------------------------------------------------------------- *)
   220 
   221 	(* theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term *)
   222 
   223 	fun print thy model t intr assignment =
   224 		(case get_first (fn (_, f) => f thy model t intr assignment) (#printers (RefuteData.get thy)) of
   225 		  NONE   => raise REFUTE ("print", "no printer for term " ^ quote (Sign.string_of_term (sign_of thy) t))
   226 		| SOME x => x);
   227 
   228 (* ------------------------------------------------------------------------- *)
   229 (* print_model: turns the model into a string, using a fixed interpretation  *)
   230 (*              (given by an assignment for Boolean variables) and suitable  *)
   231 (*              printers                                                     *)
   232 (* ------------------------------------------------------------------------- *)
   233 
   234 	(* theory -> model -> (int -> bool) -> string *)
   235 
   236 	fun print_model thy model assignment =
   237 	let
   238 		val (typs, terms) = model
   239 		val typs_msg =
   240 			if null typs then
   241 				"empty universe (no type variables in term)\n"
   242 			else
   243 				"Size of types: " ^ commas (map (fn (T, i) => Sign.string_of_typ (sign_of thy) T ^ ": " ^ string_of_int i) typs) ^ "\n"
   244 		val show_consts_msg =
   245 			if not (!show_consts) andalso Library.exists (is_Const o fst) terms then
   246 				"set \"show_consts\" to show the interpretation of constants\n"
   247 			else
   248 				""
   249 		val terms_msg =
   250 			if null terms then
   251 				"empty interpretation (no free variables in term)\n"
   252 			else
   253 				space_implode "\n" (List.mapPartial (fn (t, intr) =>
   254 					(* print constants only if 'show_consts' is true *)
   255 					if (!show_consts) orelse not (is_Const t) then
   256 						SOME (Sign.string_of_term (sign_of thy) t ^ ": " ^ Sign.string_of_term (sign_of thy) (print thy model t intr assignment))
   257 					else
   258 						NONE) terms) ^ "\n"
   259 	in
   260 		typs_msg ^ show_consts_msg ^ terms_msg
   261 	end;
   262 
   263 
   264 (* ------------------------------------------------------------------------- *)
   265 (* PARAMETER MANAGEMENT                                                      *)
   266 (* ------------------------------------------------------------------------- *)
   267 
   268 	(* string -> (theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option) -> theory -> theory *)
   269 
   270 	fun add_interpreter name f thy =
   271 	let
   272 		val {interpreters, printers, parameters} = RefuteData.get thy
   273 	in
   274 		case AList.lookup (op =) interpreters name of
   275 		  NONE   => RefuteData.put {interpreters = (name, f) :: interpreters, printers = printers, parameters = parameters} thy
   276 		| SOME _ => error ("Interpreter " ^ name ^ " already declared")
   277 	end;
   278 
   279 	(* string -> (theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term option) -> theory -> theory *)
   280 
   281 	fun add_printer name f thy =
   282 	let
   283 		val {interpreters, printers, parameters} = RefuteData.get thy
   284 	in
   285 		case AList.lookup (op =) printers name of
   286 		  NONE   => RefuteData.put {interpreters = interpreters, printers = (name, f) :: printers, parameters = parameters} thy
   287 		| SOME _ => error ("Printer " ^ name ^ " already declared")
   288 	end;
   289 
   290 (* ------------------------------------------------------------------------- *)
   291 (* set_default_param: stores the '(name, value)' pair in RefuteData's        *)
   292 (*                    parameter table                                        *)
   293 (* ------------------------------------------------------------------------- *)
   294 
   295 	(* (string * string) -> theory -> theory *)
   296 
   297 	fun set_default_param (name, value) thy =
   298 	let
   299 		val {interpreters, printers, parameters} = RefuteData.get thy
   300 	in
   301 		case Symtab.lookup parameters name of
   302 		  NONE   => RefuteData.put
   303 			{interpreters = interpreters, printers = printers, parameters = Symtab.extend (parameters, [(name, value)])} thy
   304 		| SOME _ => RefuteData.put
   305 			{interpreters = interpreters, printers = printers, parameters = Symtab.update (name, value) parameters} thy
   306 	end;
   307 
   308 (* ------------------------------------------------------------------------- *)
   309 (* get_default_param: retrieves the value associated with 'name' from        *)
   310 (*                    RefuteData's parameter table                           *)
   311 (* ------------------------------------------------------------------------- *)
   312 
   313 	(* theory -> string -> string option *)
   314 
   315 	val get_default_param = Symtab.lookup o #parameters o RefuteData.get;
   316 
   317 (* ------------------------------------------------------------------------- *)
   318 (* get_default_params: returns a list of all '(name, value)' pairs that are  *)
   319 (*                     stored in RefuteData's parameter table                *)
   320 (* ------------------------------------------------------------------------- *)
   321 
   322 	(* theory -> (string * string) list *)
   323 
   324 	val get_default_params = Symtab.dest o #parameters o RefuteData.get;
   325 
   326 (* ------------------------------------------------------------------------- *)
   327 (* actual_params: takes a (possibly empty) list 'params' of parameters that  *)
   328 (*      override the default parameters currently specified in 'thy', and    *)
   329 (*      returns a record that can be passed to 'find_model'.                 *)
   330 (* ------------------------------------------------------------------------- *)
   331 
   332 	(* theory -> (string * string) list -> params *)
   333 
   334 	fun actual_params thy override =
   335 	let
   336 		(* (string * string) list * string -> int *)
   337 		fun read_int (parms, name) =
   338 			case AList.lookup (op =) parms name of
   339 			  SOME s => (case Int.fromString s of
   340 				  SOME i => i
   341 				| NONE   => error ("parameter " ^ quote name ^ " (value is " ^ quote s ^ ") must be an integer value"))
   342 			| NONE   => error ("parameter " ^ quote name ^ " must be assigned a value")
   343 		(* (string * string) list * string -> string *)
   344 		fun read_string (parms, name) =
   345 			case AList.lookup (op =) parms name of
   346 			  SOME s => s
   347 			| NONE   => error ("parameter " ^ quote name ^ " must be assigned a value")
   348 		(* (string * string) list *)
   349 		val allparams = override @ (get_default_params thy)  (* 'override' first, defaults last *)
   350 		(* int *)
   351 		val minsize   = read_int (allparams, "minsize")
   352 		val maxsize   = read_int (allparams, "maxsize")
   353 		val maxvars   = read_int (allparams, "maxvars")
   354       val maxtime   = read_int (allparams, "maxtime")
   355 		(* string *)
   356 		val satsolver = read_string (allparams, "satsolver")
   357 		(* all remaining parameters of the form "string=int" are collected in  *)
   358 		(* 'sizes'                                                             *)
   359 		(* TODO: it is currently not possible to specify a size for a type     *)
   360 		(*       whose name is one of the other parameters (e.g. 'maxvars')    *)
   361 		(* (string * int) list *)
   362 		val sizes     = List.mapPartial
   363 			(fn (name,value) => (case Int.fromString value of SOME i => SOME (name, i) | NONE => NONE))
   364 			(List.filter (fn (name,_) => name<>"minsize" andalso name<>"maxsize" andalso name<>"maxvars" andalso name<>"maxtime" andalso name<>"satsolver")
   365 				allparams)
   366 	in
   367 		{sizes=sizes, minsize=minsize, maxsize=maxsize, maxvars=maxvars, maxtime=maxtime, satsolver=satsolver}
   368 	end;
   369 
   370 
   371 (* ------------------------------------------------------------------------- *)
   372 (* TRANSLATION HOL -> PROPOSITIONAL LOGIC, BOOLEAN ASSIGNMENT -> MODEL       *)
   373 (* ------------------------------------------------------------------------- *)
   374 
   375 (* ------------------------------------------------------------------------- *)
   376 (* typ_of_dtyp: converts a data type ('DatatypeAux.dtyp') into a type        *)
   377 (*              ('Term.typ'), given type parameters for the data type's type *)
   378 (*              arguments                                                    *)
   379 (* ------------------------------------------------------------------------- *)
   380 
   381 	(* DatatypeAux.descr -> (DatatypeAux.dtyp * Term.typ) list -> DatatypeAux.dtyp -> Term.typ *)
   382 
   383 	fun typ_of_dtyp descr typ_assoc (DatatypeAux.DtTFree a) =
   384 		(* replace a 'DtTFree' variable by the associated type *)
   385 		(the o AList.lookup (op =) typ_assoc) (DatatypeAux.DtTFree a)
   386 	  | typ_of_dtyp descr typ_assoc (DatatypeAux.DtType (s, ds)) =
   387 		Type (s, map (typ_of_dtyp descr typ_assoc) ds)
   388 	  | typ_of_dtyp descr typ_assoc (DatatypeAux.DtRec i) =
   389 		let
   390 			val (s, ds, _) = (the o AList.lookup (op =) descr) i
   391 		in
   392 			Type (s, map (typ_of_dtyp descr typ_assoc) ds)
   393 		end;
   394 
   395 (* ------------------------------------------------------------------------- *)
   396 (* collect_axioms: collects (monomorphic, universally quantified versions    *)
   397 (*                 of) all HOL axioms that are relevant w.r.t 't'            *)
   398 (* ------------------------------------------------------------------------- *)
   399 
   400 	(* Note: to make the collection of axioms more easily extensible, this    *)
   401 	(*       function could be based on user-supplied "axiom collectors",     *)
   402 	(*       similar to 'interpret'/interpreters or 'print'/printers          *)
   403 
   404 	(* theory -> Term.term -> Term.term list *)
   405 
   406 	(* Which axioms are "relevant" for a particular term/type goes hand in    *)
   407 	(* hand with the interpretation of that term/type by its interpreter (see *)
   408 	(* way below): if the interpretation respects an axiom anyway, the axiom  *)
   409 	(* does not need to be added as a constraint here.                        *)
   410 
   411 	(* When an axiom is added as relevant, further axioms may need to be      *)
   412 	(* added as well (e.g. when a constant is defined in terms of other       *)
   413 	(* constants).  To avoid infinite recursion (which should not happen for  *)
   414 	(* constants anyway, but it could happen for "typedef"-related axioms,    *)
   415 	(* since they contain the type again), we use an accumulator 'axs' and    *)
   416 	(* add a relevant axiom only if it is not in 'axs' yet.                   *)
   417 
   418 	fun collect_axioms thy t =
   419 	let
   420 		val _ = immediate_output "Adding axioms..."
   421 		(* (string * Term.term) list *)
   422 		val axioms = Theory.all_axioms_of thy;
   423 		(* string list *)
   424 		val rec_names = Symtab.foldl (fn (acc, (_, info)) =>
   425 			#rec_names info @ acc) ([], DatatypePackage.get_datatypes thy)
   426 		(* string list *)
   427 		val const_of_class_names = map Sign.const_of_class (Sign.classes (sign_of thy))
   428 		(* given a constant 's' of type 'T', which is a subterm of 't', where  *)
   429 		(* 't' has a (possibly) more general type, the schematic type          *)
   430 		(* variables in 't' are instantiated to match the type 'T' (may raise  *)
   431 		(* Type.TYPE_MATCH)                                                    *)
   432 		(* (string * Term.typ) * Term.term -> Term.term *)
   433 		fun specialize_type ((s, T), t) =
   434 		let
   435 			fun find_typeSubs (Const (s', T')) =
   436 				(if s=s' then
   437 					SOME (Sign.typ_match thy (T', T) Vartab.empty) handle Type.TYPE_MATCH => NONE
   438 				else
   439 					NONE)
   440 			  | find_typeSubs (Free _)           = NONE
   441 			  | find_typeSubs (Var _)            = NONE
   442 			  | find_typeSubs (Bound _)          = NONE
   443 			  | find_typeSubs (Abs (_, _, body)) = find_typeSubs body
   444 			  | find_typeSubs (t1 $ t2)          = (case find_typeSubs t1 of SOME x => SOME x | NONE => find_typeSubs t2)
   445 			val typeSubs = (case find_typeSubs t of
   446 				  SOME x => x
   447 				| NONE   => raise Type.TYPE_MATCH (* no match found - perhaps due to sort constraints *))
   448 		in
   449 			map_term_types
   450 				(map_type_tvar
   451 					(fn v =>
   452 						case Type.lookup (typeSubs, v) of
   453 						  NONE =>
   454 							(* schematic type variable not instantiated *)
   455 							raise REFUTE ("collect_axioms", "term " ^ Sign.string_of_term (sign_of thy) t ^ " still has a polymorphic type (after instantiating type of " ^ quote s ^ ")")
   456 						| SOME typ =>
   457 							typ))
   458 					t
   459 		end
   460 		(* applies a type substitution 'typeSubs' for all type variables in a  *)
   461 		(* term 't'                                                            *)
   462 		(* (Term.sort * Term.typ) Term.Vartab.table -> Term.term -> Term.term *)
   463 		fun monomorphic_term typeSubs t =
   464 			map_term_types (map_type_tvar
   465 				(fn v =>
   466 					case Type.lookup (typeSubs, v) of
   467 					  NONE =>
   468 						(* schematic type variable not instantiated *)
   469 						error ""
   470 					| SOME typ =>
   471 						typ)) t
   472 		(* Term.term list * Term.typ -> Term.term list *)
   473 		fun collect_sort_axioms (axs, T) =
   474 			let
   475 				(* collect the axioms for a single 'class' (but not for its superclasses) *)
   476 				(* Term.term list * string -> Term.term list *)
   477 				fun collect_class_axioms (axs, class) =
   478 					let
   479 						(* obtain the axioms generated by the "axclass" command *)
   480 						(* (string * Term.term) list *)
   481 						val class_axioms             = List.filter (fn (s, _) => String.isPrefix (Sign.const_of_class class ^ ".axioms_") s) axioms
   482 						(* replace the one schematic type variable in each axiom by the actual type 'T' *)
   483 						(* (string * Term.term) list *)
   484 						val monomorphic_class_axioms = map (fn (axname, ax) =>
   485 							let
   486 								val (idx, S) = (case term_tvars ax of
   487 									  [is] => is
   488 									| _    => raise REFUTE ("collect_axioms", "class axiom " ^ axname ^ " (" ^ Sign.string_of_term (sign_of thy) ax ^ ") does not contain exactly one type variable"))
   489 							in
   490 								(axname, monomorphic_term (Vartab.make [(idx, (S, T))]) ax)
   491 							end) class_axioms
   492 						(* Term.term list * (string * Term.term) list -> Term.term list *)
   493 						fun collect_axiom (axs, (axname, ax)) =
   494 							if mem_term (ax, axs) then
   495 								axs
   496 							else (
   497 								immediate_output (" " ^ axname);
   498 								collect_term_axioms (ax :: axs, ax)
   499 							)
   500 					in
   501 						Library.foldl collect_axiom (axs, monomorphic_class_axioms)
   502 					end
   503 				(* string list *)
   504 				val sort = (case T of
   505 					  TFree (_, sort) => sort
   506 					| TVar (_, sort)  => sort
   507 					| _               => raise REFUTE ("collect_axioms", "type " ^ Sign.string_of_typ (sign_of thy) T ^ " is not a variable"))
   508 				(* obtain all superclasses of classes in 'sort' *)
   509 				(* string list *)
   510 				val superclasses = Graph.all_succs ((#2 o #classes o Type.rep_tsig o Sign.tsig_of o sign_of) thy) sort
   511 			in
   512 				Library.foldl collect_class_axioms (axs, superclasses)
   513 			end
   514 		(* Term.term list * Term.typ -> Term.term list *)
   515 		and collect_type_axioms (axs, T) =
   516 			case T of
   517 			(* simple types *)
   518 			  Type ("prop", [])      => axs
   519 			| Type ("fun", [T1, T2]) => collect_type_axioms (collect_type_axioms (axs, T1), T2)
   520 			| Type ("set", [T1])     => collect_type_axioms (axs, T1)
   521 			| Type ("itself", [T1])  => collect_type_axioms (axs, T1)  (* axiomatic type classes *)
   522 			| Type (s, Ts)           =>
   523 				let
   524 					(* look up the definition of a type, as created by "typedef" *)
   525 					(* (string * Term.term) list -> (string * Term.term) option *)
   526 					fun get_typedefn [] =
   527 						NONE
   528 					  | get_typedefn ((axname,ax)::axms) =
   529 						(let
   530 							(* Term.term -> Term.typ option *)
   531 							fun type_of_type_definition (Const (s', T')) =
   532 								if s'="Typedef.type_definition" then
   533 									SOME T'
   534 								else
   535 									NONE
   536 							  | type_of_type_definition (Free _)           = NONE
   537 							  | type_of_type_definition (Var _)            = NONE
   538 							  | type_of_type_definition (Bound _)          = NONE
   539 							  | type_of_type_definition (Abs (_, _, body)) = type_of_type_definition body
   540 							  | type_of_type_definition (t1 $ t2)          = (case type_of_type_definition t1 of SOME x => SOME x | NONE => type_of_type_definition t2)
   541 						in
   542 							case type_of_type_definition ax of
   543 							  SOME T' =>
   544 								let
   545 									val T''      = (domain_type o domain_type) T'
   546 									val typeSubs = Sign.typ_match thy (T'', T) Vartab.empty
   547 								in
   548 									SOME (axname, monomorphic_term typeSubs ax)
   549 								end
   550 							| NONE =>
   551 								get_typedefn axms
   552 						end
   553 						handle ERROR _         => get_typedefn axms
   554 						     | MATCH           => get_typedefn axms
   555 						     | Type.TYPE_MATCH => get_typedefn axms)
   556 				in
   557 					case DatatypePackage.datatype_info thy s of
   558 					  SOME info =>  (* inductive datatype *)
   559 							(* only collect relevant type axioms for the argument types *)
   560 							Library.foldl collect_type_axioms (axs, Ts)
   561 					| NONE =>
   562 						(case get_typedefn axioms of
   563 						  SOME (axname, ax) => 
   564 							if mem_term (ax, axs) then
   565 								(* only collect relevant type axioms for the argument types *)
   566 								Library.foldl collect_type_axioms (axs, Ts)
   567 							else
   568 								(immediate_output (" " ^ axname);
   569 								collect_term_axioms (ax :: axs, ax))
   570 						| NONE =>
   571 							(* unspecified type, perhaps introduced with 'typedecl' *)
   572 							(* at least collect relevant type axioms for the argument types *)
   573 							Library.foldl collect_type_axioms (axs, Ts))
   574 				end
   575 			| TFree _                => collect_sort_axioms (axs, T)  (* axiomatic type classes *)
   576 			| TVar _                 => collect_sort_axioms (axs, T)  (* axiomatic type classes *)
   577 		(* Term.term list * Term.term -> Term.term list *)
   578 		and collect_term_axioms (axs, t) =
   579 			case t of
   580 			(* Pure *)
   581 			  Const ("all", _)                => axs
   582 			| Const ("==", _)                 => axs
   583 			| Const ("==>", _)                => axs
   584 			| Const ("TYPE", T)               => collect_type_axioms (axs, T)  (* axiomatic type classes *)
   585 			(* HOL *)
   586 			| Const ("Trueprop", _)           => axs
   587 			| Const ("Not", _)                => axs
   588 			| Const ("True", _)               => axs  (* redundant, since 'True' is also an IDT constructor *)
   589 			| Const ("False", _)              => axs  (* redundant, since 'False' is also an IDT constructor *)
   590 			| Const ("arbitrary", T)          => collect_type_axioms (axs, T)
   591 			| Const ("The", T)                =>
   592 				let
   593 					val ax = specialize_type (("The", T), (the o AList.lookup (op =) axioms) "HOL.the_eq_trivial")
   594 				in
   595 					if mem_term (ax, axs) then
   596 						collect_type_axioms (axs, T)
   597 					else
   598 						(immediate_output " HOL.the_eq_trivial";
   599 						collect_term_axioms (ax :: axs, ax))
   600 				end
   601 			| Const ("Hilbert_Choice.Eps", T) =>
   602 				let
   603 					val ax = specialize_type (("Hilbert_Choice.Eps", T),
   604                       (the o AList.lookup (op =) axioms) "Hilbert_Choice.someI")
   605 				in
   606 					if mem_term (ax, axs) then
   607 						collect_type_axioms (axs, T)
   608 					else
   609 						(immediate_output " Hilbert_Choice.someI";
   610 						collect_term_axioms (ax :: axs, ax))
   611 				end
   612 			| Const ("All", _) $ t1           => collect_term_axioms (axs, t1)
   613 			| Const ("Ex", _) $ t1            => collect_term_axioms (axs, t1)
   614 			| Const ("op =", T)               => collect_type_axioms (axs, T)
   615 			| Const ("op &", _)               => axs
   616 			| Const ("op |", _)               => axs
   617 			| Const ("op -->", _)             => axs
   618 			(* sets *)
   619 			| Const ("Collect", T)            => collect_type_axioms (axs, T)
   620 			| Const ("op :", T)               => collect_type_axioms (axs, T)
   621 			(* other optimizations *)
   622 			| Const ("Finite_Set.card", T)    => collect_type_axioms (axs, T)
   623 			| Const ("Finite_Set.Finites", T) => collect_type_axioms (axs, T)
   624 			| Const ("op <", T as Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("bool", [])])])) => collect_type_axioms (axs, T)
   625 			| Const ("op +", T as Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) => collect_type_axioms (axs, T)
   626 			| Const ("op -", T as Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) => collect_type_axioms (axs, T)
   627 			| Const ("op *", T as Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) => collect_type_axioms (axs, T)
   628 			| Const ("List.op @", T)          => collect_type_axioms (axs, T)
   629 			| Const ("Lfp.lfp", T)            => collect_type_axioms (axs, T)
   630 			| Const ("Gfp.gfp", T)            => collect_type_axioms (axs, T)
   631 			(* simply-typed lambda calculus *)
   632 			| Const (s, T)                    =>
   633 				let
   634 					(* look up the definition of a constant, as created by "constdefs" *)
   635 					(* string -> Term.typ -> (string * Term.term) list -> (string * Term.term) option *)
   636 					fun get_defn [] =
   637 						NONE
   638 					  | get_defn ((axname, ax)::axms) =
   639 						(let
   640 							val (lhs, _) = Logic.dest_equals ax  (* equations only *)
   641 							val c        = head_of lhs
   642 							val (s', T') = dest_Const c
   643 						in
   644 							if s=s' then
   645 								let
   646 									val typeSubs = Sign.typ_match thy (T', T) Vartab.empty
   647 								in
   648 									SOME (axname, monomorphic_term typeSubs ax)
   649 								end
   650 							else
   651 								get_defn axms
   652 						end
   653 						handle ERROR _         => get_defn axms
   654 						     | TERM _          => get_defn axms
   655 						     | Type.TYPE_MATCH => get_defn axms)
   656 					(* axiomatic type classes *)
   657 					(* unit -> bool *)
   658 					fun is_const_of_class () =
   659 						(* I'm not quite sure if checking the name 's' is sufficient, *)
   660 						(* or if we should also check the type 'T'                    *)
   661 						s mem const_of_class_names
   662 					(* inductive data types *)
   663 					(* unit -> bool *)
   664 					fun is_IDT_constructor () =
   665 						(case body_type T of
   666 						  Type (s', _) =>
   667 							(case DatatypePackage.constrs_of thy s' of
   668 							  SOME constrs =>
   669 								Library.exists (fn c =>
   670 									(case c of
   671 									  Const (cname, ctype) =>
   672 										cname = s andalso Sign.typ_instance thy (T, ctype)
   673 									| _ =>
   674 										raise REFUTE ("collect_axioms", "IDT constructor is not a constant")))
   675 									constrs
   676 							| NONE =>
   677 								false)
   678 						| _  =>
   679 							false)
   680 					(* unit -> bool *)
   681 					fun is_IDT_recursor () =
   682 						(* I'm not quite sure if checking the name 's' is sufficient, *)
   683 						(* or if we should also check the type 'T'                    *)
   684 						s mem rec_names
   685 				in
   686 					if is_const_of_class () then
   687 						(* axiomatic type classes: add "OFCLASS(?'a::c, c_class)" and *)
   688 						(* the introduction rule "class.intro" as axioms              *)
   689 						let
   690 							val class   = Sign.class_of_const s
   691 							val inclass = Logic.mk_inclass (TVar (("'a", 0), [class]), class)
   692 							(* Term.term option *)
   693 							val ofclass_ax = (SOME (specialize_type ((s, T), inclass)) handle Type.TYPE_MATCH => NONE)
   694 							val intro_ax   = (Option.map (fn t => specialize_type ((s, T), t))
   695 								(AList.lookup (op =) axioms (class ^ ".intro")) handle Type.TYPE_MATCH => NONE)
   696 							val axs'       = (case ofclass_ax of NONE => axs | SOME ax => if mem_term (ax, axs) then
   697 									(* collect relevant type axioms *)
   698 									collect_type_axioms (axs, T)
   699 								else
   700 									(immediate_output (" " ^ Sign.string_of_term (sign_of thy) ax);
   701 									collect_term_axioms (ax :: axs, ax)))
   702 							val axs''      = (case intro_ax of NONE => axs' | SOME ax => if mem_term (ax, axs') then
   703 									(* collect relevant type axioms *)
   704 									collect_type_axioms (axs', T)
   705 								else
   706 									(immediate_output (" " ^ s ^ ".intro");
   707 									collect_term_axioms (ax :: axs', ax)))
   708 						in
   709 							axs''
   710 						end
   711 					else if is_IDT_constructor () then
   712 						(* only collect relevant type axioms *)
   713 						collect_type_axioms (axs, T)
   714 					else if is_IDT_recursor () then
   715 						(* only collect relevant type axioms *)
   716 						collect_type_axioms (axs, T)
   717 					else (
   718 						case get_defn axioms of
   719 						  SOME (axname, ax) => 
   720 							if mem_term (ax, axs) then
   721 								(* collect relevant type axioms *)
   722 								collect_type_axioms (axs, T)
   723 							else
   724 								(immediate_output (" " ^ axname);
   725 								collect_term_axioms (ax :: axs, ax))
   726 						| NONE =>
   727 							(* collect relevant type axioms *)
   728 							collect_type_axioms (axs, T)
   729 					)
   730 				end
   731 			| Free (_, T)                     => collect_type_axioms (axs, T)
   732 			| Var (_, T)                      => collect_type_axioms (axs, T)
   733 			| Bound i                         => axs
   734 			| Abs (_, T, body)                => collect_term_axioms (collect_type_axioms (axs, T), body)
   735 			| t1 $ t2                         => collect_term_axioms (collect_term_axioms (axs, t1), t2)
   736 		(* universal closure over schematic variables *)
   737 		(* Term.term -> Term.term *)
   738 		fun close_form t =
   739 		let
   740 			(* (Term.indexname * Term.typ) list *)
   741 			val vars = sort_wrt (fst o fst) (map dest_Var (term_vars t))
   742 		in
   743 			Library.foldl
   744 				(fn (t', ((x, i), T)) => (Term.all T) $ Abs (x, T, abstract_over (Var((x, i), T), t')))
   745 				(t, vars)
   746 		end
   747 		(* Term.term list *)
   748 		val result = map close_form (collect_term_axioms ([], t))
   749 		val _ = writeln " ...done."
   750 	in
   751 		result
   752 	end;
   753 
   754 (* ------------------------------------------------------------------------- *)
   755 (* ground_types: collects all ground types in a term (including argument     *)
   756 (*               types of other types), suppressing duplicates.  Does not    *)
   757 (*               return function types, set types, non-recursive IDTs, or    *)
   758 (*               'propT'.  For IDTs, also the argument types of constructors *)
   759 (*               are considered.                                             *)
   760 (* ------------------------------------------------------------------------- *)
   761 
   762 	(* theory -> Term.term -> Term.typ list *)
   763 
   764 	fun ground_types thy t =
   765 	let
   766 		(* Term.typ * Term.typ list -> Term.typ list *)
   767 		fun collect_types (T, acc) =
   768 			if T mem acc then
   769 				acc  (* prevent infinite recursion (for IDTs) *)
   770 			else
   771 				(case T of
   772 				  Type ("fun", [T1, T2]) => collect_types (T1, collect_types (T2, acc))
   773 				| Type ("prop", [])      => acc
   774 				| Type ("set", [T1])     => collect_types (T1, acc)
   775 				| Type (s, Ts)           =>
   776 					(case DatatypePackage.datatype_info thy s of
   777 					  SOME info =>  (* inductive datatype *)
   778 						let
   779 							val index               = #index info
   780 							val descr               = #descr info
   781 							val (_, dtyps, constrs) = (the o AList.lookup (op =) descr) index
   782 							val typ_assoc           = dtyps ~~ Ts
   783 							(* sanity check: every element in 'dtyps' must be a 'DtTFree' *)
   784 							val _ = (if Library.exists (fn d =>
   785 									case d of DatatypeAux.DtTFree _ => false | _ => true) dtyps
   786 								then
   787 									raise REFUTE ("ground_types", "datatype argument (for type " ^ Sign.string_of_typ (sign_of thy) (Type (s, Ts)) ^ ") is not a variable")
   788 								else
   789 									())
   790 							(* if the current type is a recursive IDT (i.e. a depth is required), add it to 'acc' *)
   791 							val acc' = (if Library.exists (fn (_, ds) => Library.exists DatatypeAux.is_rec_type ds) constrs then
   792 									T ins acc
   793 								else
   794 									acc)
   795 							(* collect argument types *)
   796 							val acc_args = foldr collect_types acc' Ts
   797 							(* collect constructor types *)
   798 							val acc_constrs = foldr collect_types acc_args (List.concat (map (fn (_, ds) => map (typ_of_dtyp descr typ_assoc) ds) constrs))
   799 						in
   800 							acc_constrs
   801 						end
   802 					| NONE =>  (* not an inductive datatype, e.g. defined via "typedef" or "typedecl" *)
   803 						T ins (foldr collect_types acc Ts))
   804 				| TFree _                => T ins acc
   805 				| TVar _                 => T ins acc)
   806 	in
   807 		it_term_types collect_types (t, [])
   808 	end;
   809 
   810 (* ------------------------------------------------------------------------- *)
   811 (* string_of_typ: (rather naive) conversion from types to strings, used to   *)
   812 (*                look up the size of a type in 'sizes'.  Parameterized      *)
   813 (*                types with different parameters (e.g. "'a list" vs. "bool  *)
   814 (*                list") are identified.                                     *)
   815 (* ------------------------------------------------------------------------- *)
   816 
   817 	(* Term.typ -> string *)
   818 
   819 	fun string_of_typ (Type (s, _))     = s
   820 	  | string_of_typ (TFree (s, _))    = s
   821 	  | string_of_typ (TVar ((s,_), _)) = s;
   822 
   823 (* ------------------------------------------------------------------------- *)
   824 (* first_universe: returns the "first" (i.e. smallest) universe by assigning *)
   825 (*                 'minsize' to every type for which no size is specified in *)
   826 (*                 'sizes'                                                   *)
   827 (* ------------------------------------------------------------------------- *)
   828 
   829 	(* Term.typ list -> (string * int) list -> int -> (Term.typ * int) list *)
   830 
   831 	fun first_universe xs sizes minsize =
   832 	let
   833 		fun size_of_typ T =
   834 			case AList.lookup (op =) sizes (string_of_typ T) of
   835 			  SOME n => n
   836 			| NONE   => minsize
   837 	in
   838 		map (fn T => (T, size_of_typ T)) xs
   839 	end;
   840 
   841 (* ------------------------------------------------------------------------- *)
   842 (* next_universe: enumerates all universes (i.e. assignments of sizes to     *)
   843 (*                types), where the minimal size of a type is given by       *)
   844 (*                'minsize', the maximal size is given by 'maxsize', and a   *)
   845 (*                type may have a fixed size given in 'sizes'                *)
   846 (* ------------------------------------------------------------------------- *)
   847 
   848 	(* (Term.typ * int) list -> (string * int) list -> int -> int -> (Term.typ * int) list option *)
   849 
   850 	fun next_universe xs sizes minsize maxsize =
   851 	let
   852 		(* creates the "first" list of length 'len', where the sum of all list *)
   853 		(* elements is 'sum', and the length of the list is 'len'              *)
   854 		(* int -> int -> int -> int list option *)
   855 		fun make_first _ 0 sum =
   856 			if sum=0 then
   857 				SOME []
   858 			else
   859 				NONE
   860 		  | make_first max len sum =
   861 			if sum<=max orelse max<0 then
   862 				Option.map (fn xs' => sum :: xs') (make_first max (len-1) 0)
   863 			else
   864 				Option.map (fn xs' => max :: xs') (make_first max (len-1) (sum-max))
   865 		(* enumerates all int lists with a fixed length, where 0<=x<='max' for *)
   866 		(* all list elements x (unless 'max'<0)                                *)
   867 		(* int -> int -> int -> int list -> int list option *)
   868 		fun next max len sum [] =
   869 			NONE
   870 		  | next max len sum [x] =
   871 			(* we've reached the last list element, so there's no shift possible *)
   872 			make_first max (len+1) (sum+x+1)  (* increment 'sum' by 1 *)
   873 		  | next max len sum (x1::x2::xs) =
   874 			if x1>0 andalso (x2<max orelse max<0) then
   875 				(* we can shift *)
   876 				SOME (valOf (make_first max (len+1) (sum+x1-1)) @ (x2+1) :: xs)
   877 			else
   878 				(* continue search *)
   879 				next max (len+1) (sum+x1) (x2::xs)
   880 		(* only consider those types for which the size is not fixed *)
   881 		val mutables = List.filter (not o (AList.defined (op =) sizes) o string_of_typ o fst) xs
   882 		(* subtract 'minsize' from every size (will be added again at the end) *)
   883 		val diffs = map (fn (_, n) => n-minsize) mutables
   884 	in
   885 		case next (maxsize-minsize) 0 0 diffs of
   886 		  SOME diffs' =>
   887 			(* merge with those types for which the size is fixed *)
   888 			SOME (snd (foldl_map (fn (ds, (T, _)) =>
   889 				case AList.lookup (op =) sizes (string_of_typ T) of
   890 				  SOME n => (ds, (T, n))                    (* return the fixed size *)
   891 				| NONE   => (tl ds, (T, minsize + hd ds)))  (* consume the head of 'ds', add 'minsize' *)
   892 				(diffs', xs)))
   893 		| NONE =>
   894 			NONE
   895 	end;
   896 
   897 (* ------------------------------------------------------------------------- *)
   898 (* toTrue: converts the interpretation of a Boolean value to a propositional *)
   899 (*         formula that is true iff the interpretation denotes "true"        *)
   900 (* ------------------------------------------------------------------------- *)
   901 
   902 	(* interpretation -> prop_formula *)
   903 
   904 	fun toTrue (Leaf [fm, _]) = fm
   905 	  | toTrue _              = raise REFUTE ("toTrue", "interpretation does not denote a Boolean value");
   906 
   907 (* ------------------------------------------------------------------------- *)
   908 (* toFalse: converts the interpretation of a Boolean value to a              *)
   909 (*          propositional formula that is true iff the interpretation        *)
   910 (*          denotes "false"                                                  *)
   911 (* ------------------------------------------------------------------------- *)
   912 
   913 	(* interpretation -> prop_formula *)
   914 
   915 	fun toFalse (Leaf [_, fm]) = fm
   916 	  | toFalse _              = raise REFUTE ("toFalse", "interpretation does not denote a Boolean value");
   917 
   918 (* ------------------------------------------------------------------------- *)
   919 (* find_model: repeatedly calls 'interpret' with appropriate parameters,     *)
   920 (*             applies a SAT solver, and (in case a model is found) displays *)
   921 (*             the model to the user by calling 'print_model'                *)
   922 (* thy       : the current theory                                            *)
   923 (* {...}     : parameters that control the translation/model generation      *)
   924 (* t         : term to be translated into a propositional formula            *)
   925 (* negate    : if true, find a model that makes 't' false (rather than true) *)
   926 (* Note: exception 'TimeOut' is raised if the algorithm does not terminate   *)
   927 (*       within 'maxtime' seconds (if 'maxtime' >0)                          *)
   928 (* ------------------------------------------------------------------------- *)
   929 
   930 	(* theory -> params -> Term.term -> bool -> unit *)
   931 
   932 	fun find_model thy {sizes, minsize, maxsize, maxvars, maxtime, satsolver} t negate =
   933 	let
   934 		(* unit -> unit *)
   935 		fun wrapper () =
   936 		let
   937 			(* Term.term list *)
   938 			val axioms = collect_axioms thy t
   939 			(* Term.typ list *)
   940 			val types  = Library.foldl (fn (acc, t') => acc union (ground_types thy t')) ([], t :: axioms)
   941 			val _      = writeln ("Ground types: "
   942 				^ (if null types then "none."
   943 				   else commas (map (Sign.string_of_typ (sign_of thy)) types)))
   944 			(* we can only consider fragments of recursive IDTs, so we issue a  *)
   945 			(* warning if the formula contains a recursive IDT                  *)
   946 			(* TODO: no warning needed for /positive/ occurrences of IDTs       *)
   947 			val _ = if Library.exists (fn
   948 				  Type (s, _) =>
   949 					(case DatatypePackage.datatype_info thy s of
   950 					  SOME info =>  (* inductive datatype *)
   951 						let
   952 							val index           = #index info
   953 							val descr           = #descr info
   954 							val (_, _, constrs) = (the o AList.lookup (op =) descr) index
   955 						in
   956 							(* recursive datatype? *)
   957 							Library.exists (fn (_, ds) => Library.exists DatatypeAux.is_rec_type ds) constrs
   958 						end
   959 					| NONE => false)
   960 				| _ => false) types then
   961 					warning "Term contains a recursive datatype; countermodel(s) may be spurious!"
   962 				else
   963 					()
   964 			(* (Term.typ * int) list -> unit *)
   965 			fun find_model_loop universe =
   966 			let
   967 				val init_model             = (universe, [])
   968 				val init_args              = {maxvars = maxvars, def_eq = false, next_idx = 1, bounds = [], wellformed = True}
   969 				val _                      = immediate_output ("Translating term (sizes: " ^ commas (map (fn (_, n) => string_of_int n) universe) ^ ") ...")
   970 				(* translate 't' and all axioms *)
   971 				val ((model, args), intrs) = foldl_map (fn ((m, a), t') =>
   972 					let
   973 						val (i, m', a') = interpret thy m a t'
   974 					in
   975 						(* set 'def_eq' to 'true' *)
   976 						((m', {maxvars = #maxvars a', def_eq = true, next_idx = #next_idx a', bounds = #bounds a', wellformed = #wellformed a'}), i)
   977 					end) ((init_model, init_args), t :: axioms)
   978 				(* make 't' either true or false, and make all axioms true, and *)
   979 				(* add the well-formedness side condition                       *)
   980 				val fm_t  = (if negate then toFalse else toTrue) (hd intrs)
   981 				val fm_ax = PropLogic.all (map toTrue (tl intrs))
   982 				val fm    = PropLogic.all [#wellformed args, fm_ax, fm_t]
   983 			in
   984 				immediate_output " invoking SAT solver...";
   985 				(case SatSolver.invoke_solver satsolver fm of
   986 				  SatSolver.SATISFIABLE assignment =>
   987 					(writeln " model found!";
   988 					writeln ("*** Model found: ***\n" ^ print_model thy model (fn i => case assignment i of SOME b => b | NONE => true)))
   989 				| SatSolver.UNSATISFIABLE _ =>
   990 					(immediate_output " no model exists.\n";
   991 					case next_universe universe sizes minsize maxsize of
   992 					  SOME universe' => find_model_loop universe'
   993 					| NONE           => writeln "Search terminated, no larger universe within the given limits.")
   994 				| SatSolver.UNKNOWN =>
   995 					(immediate_output " no model found.\n";
   996 					case next_universe universe sizes minsize maxsize of
   997 					  SOME universe' => find_model_loop universe'
   998 					| NONE           => writeln "Search terminated, no larger universe within the given limits.")
   999 				) handle SatSolver.NOT_CONFIGURED =>
  1000 					error ("SAT solver " ^ quote satsolver ^ " is not configured.")
  1001 			end handle MAXVARS_EXCEEDED =>
  1002 				writeln ("\nSearch terminated, number of Boolean variables (" ^ string_of_int maxvars ^ " allowed) exceeded.")
  1003 			in
  1004 				find_model_loop (first_universe types sizes minsize)
  1005 			end
  1006 		in
  1007 			(* some parameter sanity checks *)
  1008 			assert (minsize>=1) ("\"minsize\" is " ^ string_of_int minsize ^ ", must be at least 1");
  1009 			assert (maxsize>=1) ("\"maxsize\" is " ^ string_of_int maxsize ^ ", must be at least 1");
  1010 			assert (maxsize>=minsize) ("\"maxsize\" (=" ^ string_of_int maxsize ^ ") is less than \"minsize\" (=" ^ string_of_int minsize ^ ").");
  1011 			assert (maxvars>=0) ("\"maxvars\" is " ^ string_of_int maxvars ^ ", must be at least 0");
  1012 			assert (maxtime>=0) ("\"maxtime\" is " ^ string_of_int maxtime ^ ", must be at least 0");
  1013 			(* enter loop with or without time limit *)
  1014 			writeln ("Trying to find a model that " ^ (if negate then "refutes" else "satisfies") ^ ": "
  1015 				^ Sign.string_of_term (sign_of thy) t);
  1016 			if maxtime>0 then (
  1017 				TimeLimit.timeLimit (Time.fromSeconds (Int.toLarge maxtime))
  1018 					wrapper ()
  1019 				handle TimeLimit.TimeOut =>
  1020 					writeln ("\nSearch terminated, time limit ("
  1021 						^ string_of_int maxtime ^ (if maxtime=1 then " second" else " seconds")
  1022 						^ ") exceeded.")
  1023 			) else
  1024 				wrapper ()
  1025 		end;
  1026 
  1027 
  1028 (* ------------------------------------------------------------------------- *)
  1029 (* INTERFACE, PART 2: FINDING A MODEL                                        *)
  1030 (* ------------------------------------------------------------------------- *)
  1031 
  1032 (* ------------------------------------------------------------------------- *)
  1033 (* satisfy_term: calls 'find_model' to find a model that satisfies 't'       *)
  1034 (* params      : list of '(name, value)' pairs used to override default      *)
  1035 (*               parameters                                                  *)
  1036 (* ------------------------------------------------------------------------- *)
  1037 
  1038 	(* theory -> (string * string) list -> Term.term -> unit *)
  1039 
  1040 	fun satisfy_term thy params t =
  1041 		find_model thy (actual_params thy params) t false;
  1042 
  1043 (* ------------------------------------------------------------------------- *)
  1044 (* refute_term: calls 'find_model' to find a model that refutes 't'          *)
  1045 (* params     : list of '(name, value)' pairs used to override default       *)
  1046 (*              parameters                                                   *)
  1047 (* ------------------------------------------------------------------------- *)
  1048 
  1049 	(* theory -> (string * string) list -> Term.term -> unit *)
  1050 
  1051 	fun refute_term thy params t =
  1052 	let
  1053 		(* disallow schematic type variables, since we cannot properly negate  *)
  1054 		(* terms containing them (their logical meaning is that there EXISTS a *)
  1055 		(* type s.t. ...; to refute such a formula, we would have to show that *)
  1056 		(* for ALL types, not ...)                                             *)
  1057 		val _ = assert (null (term_tvars t)) "Term to be refuted contains schematic type variables"
  1058 		(* existential closure over schematic variables *)
  1059 		(* (Term.indexname * Term.typ) list *)
  1060 		val vars = sort_wrt (fst o fst) (map dest_Var (term_vars t))
  1061 		(* Term.term *)
  1062 		val ex_closure = Library.foldl
  1063 			(fn (t', ((x, i), T)) => (HOLogic.exists_const T) $ Abs (x, T, abstract_over (Var ((x, i), T), t')))
  1064 			(t, vars)
  1065 		(* If 't' is of type 'propT' (rather than 'boolT'), applying  *)
  1066 		(* 'HOLogic.exists_const' is not type-correct.  However, this *)
  1067 		(* is not really a problem as long as 'find_model' still      *)
  1068 		(* interprets the resulting term correctly, without checking  *)
  1069 		(* its type.                                                  *)
  1070 	in
  1071 		find_model thy (actual_params thy params) ex_closure true
  1072 	end;
  1073 
  1074 (* ------------------------------------------------------------------------- *)
  1075 (* refute_subgoal: calls 'refute_term' on a specific subgoal                 *)
  1076 (* params        : list of '(name, value)' pairs used to override default    *)
  1077 (*                 parameters                                                *)
  1078 (* subgoal       : 0-based index specifying the subgoal number               *)
  1079 (* ------------------------------------------------------------------------- *)
  1080 
  1081 	(* theory -> (string * string) list -> Thm.thm -> int -> unit *)
  1082 
  1083 	fun refute_subgoal thy params thm subgoal =
  1084 		refute_term thy params (List.nth (prems_of thm, subgoal));
  1085 
  1086 
  1087 (* ------------------------------------------------------------------------- *)
  1088 (* INTERPRETERS: Auxiliary Functions                                         *)
  1089 (* ------------------------------------------------------------------------- *)
  1090 
  1091 (* ------------------------------------------------------------------------- *)
  1092 (* make_constants: returns all interpretations that have the same tree       *)
  1093 (*                 structure as 'intr', but consist of unit vectors with     *)
  1094 (*                 'True'/'False' only (no Boolean variables)                *)
  1095 (* ------------------------------------------------------------------------- *)
  1096 
  1097 	(* interpretation -> interpretation list *)
  1098 
  1099 	fun make_constants intr =
  1100 	let
  1101 		(* returns a list with all unit vectors of length n *)
  1102 		(* int -> interpretation list *)
  1103 		fun unit_vectors n =
  1104 		let
  1105 			(* returns the k-th unit vector of length n *)
  1106 			(* int * int -> interpretation *)
  1107 			fun unit_vector (k,n) =
  1108 				Leaf ((replicate (k-1) False) @ (True :: (replicate (n-k) False)))
  1109 			(* int -> interpretation list -> interpretation list *)
  1110 			fun unit_vectors_acc k vs =
  1111 				if k>n then [] else (unit_vector (k,n))::(unit_vectors_acc (k+1) vs)
  1112 		in
  1113 			unit_vectors_acc 1 []
  1114 		end
  1115 		(* concatenates 'x' with every list in 'xss', returning a new list of lists *)
  1116 		(* 'a -> 'a list list -> 'a list list *)
  1117 		fun cons_list x xss =
  1118 			map (fn xs => x::xs) xss
  1119 		(* returns a list of lists, each one consisting of n (possibly identical) elements from 'xs' *)
  1120 		(* int -> 'a list -> 'a list list *)
  1121 		fun pick_all 1 xs =
  1122 			map (fn x => [x]) xs
  1123 		  | pick_all n xs =
  1124 			let val rec_pick = pick_all (n-1) xs in
  1125 				Library.foldl (fn (acc, x) => (cons_list x rec_pick) @ acc) ([], xs)
  1126 			end
  1127 	in
  1128 		case intr of
  1129 		  Leaf xs => unit_vectors (length xs)
  1130 		| Node xs => map (fn xs' => Node xs') (pick_all (length xs) (make_constants (hd xs)))
  1131 	end;
  1132 
  1133 (* ------------------------------------------------------------------------- *)
  1134 (* size_of_type: returns the number of constants in a type (i.e. 'length     *)
  1135 (*               (make_constants intr)', but implemented more efficiently)   *)
  1136 (* ------------------------------------------------------------------------- *)
  1137 
  1138 	(* interpretation -> int *)
  1139 
  1140 	fun size_of_type intr =
  1141 	let
  1142 		(* power (a, b) computes a^b, for a>=0, b>=0 *)
  1143 		(* int * int -> int *)
  1144 		fun power (a, 0) = 1
  1145 		  | power (a, 1) = a
  1146 		  | power (a, b) = let val ab = power(a, b div 2) in ab * ab * power(a, b mod 2) end
  1147 	in
  1148 		case intr of
  1149 		  Leaf xs => length xs
  1150 		| Node xs => power (size_of_type (hd xs), length xs)
  1151 	end;
  1152 
  1153 (* ------------------------------------------------------------------------- *)
  1154 (* TT/FF: interpretations that denote "true" or "false", respectively        *)
  1155 (* ------------------------------------------------------------------------- *)
  1156 
  1157 	(* interpretation *)
  1158 
  1159 	val TT = Leaf [True, False];
  1160 
  1161 	val FF = Leaf [False, True];
  1162 
  1163 (* ------------------------------------------------------------------------- *)
  1164 (* make_equality: returns an interpretation that denotes (extensional)       *)
  1165 (*                equality of two interpretations                            *)
  1166 (* - two interpretations are 'equal' iff they are both defined and denote    *)
  1167 (*   the same value                                                          *)
  1168 (* - two interpretations are 'not_equal' iff they are both defined at least  *)
  1169 (*   partially, and a defined part denotes different values                  *)
  1170 (* - a completely undefined interpretation is neither 'equal' nor            *)
  1171 (*   'not_equal' to another interpretation                                   *)
  1172 (* ------------------------------------------------------------------------- *)
  1173 
  1174 	(* We could in principle represent '=' on a type T by a particular        *)
  1175 	(* interpretation.  However, the size of that interpretation is quadratic *)
  1176 	(* in the size of T.  Therefore comparing the interpretations 'i1' and    *)
  1177 	(* 'i2' directly is more efficient than constructing the interpretation   *)
  1178 	(* for equality on T first, and "applying" this interpretation to 'i1'    *)
  1179 	(* and 'i2' in the usual way (cf. 'interpretation_apply') then.           *)
  1180 
  1181 	(* interpretation * interpretation -> interpretation *)
  1182 
  1183 	fun make_equality (i1, i2) =
  1184 	let
  1185 		(* interpretation * interpretation -> prop_formula *)
  1186 		fun equal (i1, i2) =
  1187 			(case i1 of
  1188 			  Leaf xs =>
  1189 				(case i2 of
  1190 				  Leaf ys => PropLogic.dot_product (xs, ys)  (* defined and equal *)
  1191 				| Node _  => raise REFUTE ("make_equality", "second interpretation is higher"))
  1192 			| Node xs =>
  1193 				(case i2 of
  1194 				  Leaf _  => raise REFUTE ("make_equality", "first interpretation is higher")
  1195 				| Node ys => PropLogic.all (map equal (xs ~~ ys))))
  1196 		(* interpretation * interpretation -> prop_formula *)
  1197 		fun not_equal (i1, i2) =
  1198 			(case i1 of
  1199 			  Leaf xs =>
  1200 				(case i2 of
  1201 				  Leaf ys => PropLogic.all ((PropLogic.exists xs) :: (PropLogic.exists ys) ::
  1202 					(map (fn (x,y) => SOr (SNot x, SNot y)) (xs ~~ ys)))  (* defined and not equal *)
  1203 				| Node _  => raise REFUTE ("make_equality", "second interpretation is higher"))
  1204 			| Node xs =>
  1205 				(case i2 of
  1206 				  Leaf _  => raise REFUTE ("make_equality", "first interpretation is higher")
  1207 				| Node ys => PropLogic.exists (map not_equal (xs ~~ ys))))
  1208 	in
  1209 		(* a value may be undefined; therefore 'not_equal' is not just the     *)
  1210 		(* negation of 'equal'                                                 *)
  1211 		Leaf [equal (i1, i2), not_equal (i1, i2)]
  1212 	end;
  1213 
  1214 (* ------------------------------------------------------------------------- *)
  1215 (* make_def_equality: returns an interpretation that denotes (extensional)   *)
  1216 (*                    equality of two interpretations                        *)
  1217 (* This function treats undefined/partially defined interpretations          *)
  1218 (* different from 'make_equality': two undefined interpretations are         *)
  1219 (* considered equal, while a defined interpretation is considered not equal  *)
  1220 (* to an undefined interpretation.                                           *)
  1221 (* ------------------------------------------------------------------------- *)
  1222 
  1223 	(* interpretation * interpretation -> interpretation *)
  1224 
  1225 	fun make_def_equality (i1, i2) =
  1226 	let
  1227 		(* interpretation * interpretation -> prop_formula *)
  1228 		fun equal (i1, i2) =
  1229 			(case i1 of
  1230 			  Leaf xs =>
  1231 				(case i2 of
  1232 				  Leaf ys => SOr (PropLogic.dot_product (xs, ys),  (* defined and equal, or both undefined *)
  1233 					SAnd (PropLogic.all (map SNot xs), PropLogic.all (map SNot ys)))
  1234 				| Node _  => raise REFUTE ("make_def_equality", "second interpretation is higher"))
  1235 			| Node xs =>
  1236 				(case i2 of
  1237 				  Leaf _  => raise REFUTE ("make_def_equality", "first interpretation is higher")
  1238 				| Node ys => PropLogic.all (map equal (xs ~~ ys))))
  1239 		(* interpretation *)
  1240 		val eq = equal (i1, i2)
  1241 	in
  1242 		Leaf [eq, SNot eq]
  1243 	end;
  1244 
  1245 (* ------------------------------------------------------------------------- *)
  1246 (* interpretation_apply: returns an interpretation that denotes the result   *)
  1247 (*                       of applying the function denoted by 'i2' to the     *)
  1248 (*                       argument denoted by 'i2'                            *)
  1249 (* ------------------------------------------------------------------------- *)
  1250 
  1251 	(* interpretation * interpretation -> interpretation *)
  1252 
  1253 	fun interpretation_apply (i1, i2) =
  1254 	let
  1255 		(* interpretation * interpretation -> interpretation *)
  1256 		fun interpretation_disjunction (tr1,tr2) =
  1257 			tree_map (fn (xs,ys) => map (fn (x,y) => SOr(x,y)) (xs ~~ ys)) (tree_pair (tr1,tr2))
  1258 		(* prop_formula * interpretation -> interpretation *)
  1259 		fun prop_formula_times_interpretation (fm,tr) =
  1260 			tree_map (map (fn x => SAnd (fm,x))) tr
  1261 		(* prop_formula list * interpretation list -> interpretation *)
  1262 		fun prop_formula_list_dot_product_interpretation_list ([fm],[tr]) =
  1263 			prop_formula_times_interpretation (fm,tr)
  1264 		  | prop_formula_list_dot_product_interpretation_list (fm::fms,tr::trees) =
  1265 			interpretation_disjunction (prop_formula_times_interpretation (fm,tr), prop_formula_list_dot_product_interpretation_list (fms,trees))
  1266 		  | prop_formula_list_dot_product_interpretation_list (_,_) =
  1267 			raise REFUTE ("interpretation_apply", "empty list (in dot product)")
  1268 		(* concatenates 'x' with every list in 'xss', returning a new list of lists *)
  1269 		(* 'a -> 'a list list -> 'a list list *)
  1270 		fun cons_list x xss =
  1271 			map (fn xs => x::xs) xss
  1272 		(* returns a list of lists, each one consisting of one element from each element of 'xss' *)
  1273 		(* 'a list list -> 'a list list *)
  1274 		fun pick_all [xs] =
  1275 			map (fn x => [x]) xs
  1276 		  | pick_all (xs::xss) =
  1277 			let val rec_pick = pick_all xss in
  1278 				Library.foldl (fn (acc, x) => (cons_list x rec_pick) @ acc) ([], xs)
  1279 			end
  1280 		  | pick_all _ =
  1281 			raise REFUTE ("interpretation_apply", "empty list (in pick_all)")
  1282 		(* interpretation -> prop_formula list *)
  1283 		fun interpretation_to_prop_formula_list (Leaf xs) =
  1284 			xs
  1285 		  | interpretation_to_prop_formula_list (Node trees) =
  1286 			map PropLogic.all (pick_all (map interpretation_to_prop_formula_list trees))
  1287 	in
  1288 		case i1 of
  1289 		  Leaf _ =>
  1290 			raise REFUTE ("interpretation_apply", "first interpretation is a leaf")
  1291 		| Node xs =>
  1292 			prop_formula_list_dot_product_interpretation_list (interpretation_to_prop_formula_list i2, xs)
  1293 	end;
  1294 
  1295 (* ------------------------------------------------------------------------- *)
  1296 (* eta_expand: eta-expands a term 't' by adding 'i' lambda abstractions      *)
  1297 (* ------------------------------------------------------------------------- *)
  1298 
  1299 	(* Term.term -> int -> Term.term *)
  1300 
  1301 	fun eta_expand t i =
  1302 	let
  1303 		val Ts = binder_types (fastype_of t)
  1304 	in
  1305 		foldr (fn (T, t) => Abs ("<eta_expand>", T, t))
  1306 			(list_comb (t, map Bound (i-1 downto 0))) (Library.take (i, Ts))
  1307 	end;
  1308 
  1309 (* ------------------------------------------------------------------------- *)
  1310 (* sum: returns the sum of a list 'xs' of integers                           *)
  1311 (* ------------------------------------------------------------------------- *)
  1312 
  1313 	(* int list -> int *)
  1314 
  1315 	fun sum xs = foldl op+ 0 xs;
  1316 
  1317 (* ------------------------------------------------------------------------- *)
  1318 (* product: returns the product of a list 'xs' of integers                   *)
  1319 (* ------------------------------------------------------------------------- *)
  1320 
  1321 	(* int list -> int *)
  1322 
  1323 	fun product xs = foldl op* 1 xs;
  1324 
  1325 (* ------------------------------------------------------------------------- *)
  1326 (* size_of_dtyp: the size of (an initial fragment of) an inductive data type *)
  1327 (*               is the sum (over its constructors) of the product (over     *)
  1328 (*               their arguments) of the size of the argument types          *)
  1329 (* ------------------------------------------------------------------------- *)
  1330 
  1331 	(* theory -> (Term.typ * int) list -> DatatypeAux.descr -> (DatatypeAux.dtyp * Term.typ) list -> (string * DatatypeAux.dtyp list) list -> int *)
  1332 
  1333 	fun size_of_dtyp thy typ_sizes descr typ_assoc constructors =
  1334 		sum (map (fn (_, dtyps) =>
  1335 			product (map (fn dtyp =>
  1336 				let
  1337 					val T         = typ_of_dtyp descr typ_assoc dtyp
  1338 					val (i, _, _) = interpret thy (typ_sizes, []) {maxvars=0, def_eq = false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1339 				in
  1340 					size_of_type i
  1341 				end) dtyps)) constructors);
  1342 
  1343 
  1344 (* ------------------------------------------------------------------------- *)
  1345 (* INTERPRETERS: Actual Interpreters                                         *)
  1346 (* ------------------------------------------------------------------------- *)
  1347 
  1348 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1349 
  1350 	(* simply typed lambda calculus: Isabelle's basic term syntax, with type  *)
  1351 	(* variables, function types, and propT                                   *)
  1352 
  1353 	fun stlc_interpreter thy model args t =
  1354 	let
  1355 		val (typs, terms)                                   = model
  1356 		val {maxvars, def_eq, next_idx, bounds, wellformed} = args
  1357 		(* Term.typ -> (interpretation * model * arguments) option *)
  1358 		fun interpret_groundterm T =
  1359 		let
  1360 			(* unit -> (interpretation * model * arguments) option *)
  1361 			fun interpret_groundtype () =
  1362 			let
  1363 				val size = (if T = Term.propT then 2 else (the o AList.lookup (op =) typs) T)                    (* the model MUST specify a size for ground types *)
  1364 				val next = next_idx+size
  1365 				val _    = (if next-1>maxvars andalso maxvars>0 then raise MAXVARS_EXCEEDED else ())  (* check if 'maxvars' is large enough *)
  1366 				(* prop_formula list *)
  1367 				val fms  = map BoolVar (next_idx upto (next_idx+size-1))
  1368 				(* interpretation *)
  1369 				val intr = Leaf fms
  1370 				(* prop_formula list -> prop_formula *)
  1371 				fun one_of_two_false []      = True
  1372 				  | one_of_two_false (x::xs) = SAnd (PropLogic.all (map (fn x' => SOr (SNot x, SNot x')) xs), one_of_two_false xs)
  1373 				(* prop_formula *)
  1374 				val wf   = one_of_two_false fms
  1375 			in
  1376 				(* extend the model, increase 'next_idx', add well-formedness condition *)
  1377 				SOME (intr, (typs, (t, intr)::terms), {maxvars = maxvars, def_eq = def_eq, next_idx = next, bounds = bounds, wellformed = SAnd (wellformed, wf)})
  1378 			end
  1379 		in
  1380 			case T of
  1381 			  Type ("fun", [T1, T2]) =>
  1382 				let
  1383 					(* we create 'size_of_type (interpret (... T1))' different copies *)
  1384 					(* of the interpretation for 'T2', which are then combined into a *)
  1385 					(* single new interpretation                                      *)
  1386 					val (i1, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T1))
  1387 					(* make fresh copies, with different variable indices *)
  1388 					(* 'idx': next variable index                         *)
  1389 					(* 'n'  : number of copies                            *)
  1390 					(* int -> int -> (int * interpretation list * prop_formula *)
  1391 					fun make_copies idx 0 =
  1392 						(idx, [], True)
  1393 					  | make_copies idx n =
  1394 						let
  1395 							val (copy, _, new_args) = interpret thy (typs, []) {maxvars = maxvars, def_eq = false, next_idx = idx, bounds = [], wellformed = True} (Free ("dummy", T2))
  1396 							val (idx', copies, wf') = make_copies (#next_idx new_args) (n-1)
  1397 						in
  1398 							(idx', copy :: copies, SAnd (#wellformed new_args, wf'))
  1399 						end
  1400 					val (next, copies, wf) = make_copies next_idx (size_of_type i1)
  1401 					(* combine copies into a single interpretation *)
  1402 					val intr = Node copies
  1403 				in
  1404 					(* extend the model, increase 'next_idx', add well-formedness condition *)
  1405 					SOME (intr, (typs, (t, intr)::terms), {maxvars = maxvars, def_eq = def_eq, next_idx = next, bounds = bounds, wellformed = SAnd (wellformed, wf)})
  1406 				end
  1407 			| Type _  => interpret_groundtype ()
  1408 			| TFree _ => interpret_groundtype ()
  1409 			| TVar  _ => interpret_groundtype ()
  1410 		end
  1411 	in
  1412 		case AList.lookup (op =) terms t of
  1413 		  SOME intr =>
  1414 			(* return an existing interpretation *)
  1415 			SOME (intr, model, args)
  1416 		| NONE =>
  1417 			(case t of
  1418 			  Const (_, T)     =>
  1419 				interpret_groundterm T
  1420 			| Free (_, T)      =>
  1421 				interpret_groundterm T
  1422 			| Var (_, T)       =>
  1423 				interpret_groundterm T
  1424 			| Bound i          =>
  1425 				SOME (List.nth (#bounds args, i), model, args)
  1426 			| Abs (x, T, body) =>
  1427 				let
  1428 					(* create all constants of type 'T' *)
  1429 					val (i, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1430 					val constants = make_constants i
  1431 					(* interpret the 'body' separately for each constant *)
  1432 					val ((model', args'), bodies) = foldl_map
  1433 						(fn ((m, a), c) =>
  1434 							let
  1435 								(* add 'c' to 'bounds' *)
  1436 								val (i', m', a') = interpret thy m {maxvars = #maxvars a, def_eq = #def_eq a, next_idx = #next_idx a, bounds = (c :: #bounds a), wellformed = #wellformed a} body
  1437 							in
  1438 								(* keep the new model m' and 'next_idx' and 'wellformed', but use old 'bounds' *)
  1439 								((m', {maxvars = maxvars, def_eq = def_eq, next_idx = #next_idx a', bounds = bounds, wellformed = #wellformed a'}), i')
  1440 							end)
  1441 						((model, args), constants)
  1442 				in
  1443 					SOME (Node bodies, model', args')
  1444 				end
  1445 			| t1 $ t2          =>
  1446 				let
  1447 					(* interpret 't1' and 't2' separately *)
  1448 					val (intr1, model1, args1) = interpret thy model args t1
  1449 					val (intr2, model2, args2) = interpret thy model1 args1 t2
  1450 				in
  1451 					SOME (interpretation_apply (intr1, intr2), model2, args2)
  1452 				end)
  1453 	end;
  1454 
  1455 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1456 
  1457 	fun Pure_interpreter thy model args t =
  1458 		case t of
  1459 		  Const ("all", _) $ t1 =>  (* in the meta-logic, 'all' MUST be followed by an argument term *)
  1460 			let
  1461 				val (i, m, a) = interpret thy model args t1
  1462 			in
  1463 				case i of
  1464 				  Node xs =>
  1465 					let
  1466 						val fmTrue  = PropLogic.all (map toTrue xs)
  1467 						val fmFalse = PropLogic.exists (map toFalse xs)
  1468 					in
  1469 						SOME (Leaf [fmTrue, fmFalse], m, a)
  1470 					end
  1471 				| _ =>
  1472 					raise REFUTE ("Pure_interpreter", "\"all\" is not followed by a function")
  1473 			end
  1474 		| Const ("==", _) $ t1 $ t2 =>
  1475 			let
  1476 				val (i1, m1, a1) = interpret thy model args t1
  1477 				val (i2, m2, a2) = interpret thy m1 a1 t2
  1478 			in
  1479 				(* we use either 'make_def_equality' or 'make_equality' *)
  1480 				SOME ((if #def_eq args then make_def_equality else make_equality) (i1, i2), m2, a2)
  1481 			end
  1482 		| Const ("==>", _) =>  (* simpler than translating 'Const ("==>", _) $ t1 $ t2' *)
  1483 			SOME (Node [Node [TT, FF], Node [TT, TT]], model, args)
  1484 		| _ => NONE;
  1485 
  1486 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1487 
  1488 	fun HOLogic_interpreter thy model args t =
  1489 	(* ------------------------------------------------------------------------- *)
  1490 	(* Providing interpretations directly is more efficient than unfolding the   *)
  1491 	(* logical constants.  In HOL however, logical constants can themselves be   *)
  1492 	(* arguments.  "All" and "Ex" are then translated just like any other        *)
  1493 	(* constant, with the relevant axiom being added by 'collect_axioms'.        *)
  1494 	(* ------------------------------------------------------------------------- *)
  1495 		case t of
  1496 		  Const ("Trueprop", _) =>
  1497 			SOME (Node [TT, FF], model, args)
  1498 		| Const ("Not", _) =>
  1499 			SOME (Node [FF, TT], model, args)
  1500 		| Const ("True", _) =>  (* redundant, since 'True' is also an IDT constructor *)
  1501 			SOME (TT, model, args)
  1502 		| Const ("False", _) =>  (* redundant, since 'False' is also an IDT constructor *)
  1503 			SOME (FF, model, args)
  1504 		| Const ("All", _) $ t1 =>
  1505 		(* if "All" occurs without an argument (i.e. as argument to a higher-order *)
  1506 		(* function or predicate), it is handled by the 'stlc_interpreter' (i.e.   *)
  1507 		(* by unfolding its definition)                                            *)
  1508 			let
  1509 				val (i, m, a) = interpret thy model args t1
  1510 			in
  1511 				case i of
  1512 				  Node xs =>
  1513 					let
  1514 						val fmTrue  = PropLogic.all (map toTrue xs)
  1515 						val fmFalse = PropLogic.exists (map toFalse xs)
  1516 					in
  1517 						SOME (Leaf [fmTrue, fmFalse], m, a)
  1518 					end
  1519 				| _ =>
  1520 					raise REFUTE ("HOLogic_interpreter", "\"All\" is followed by a non-function")
  1521 			end
  1522 		| Const ("Ex", _) $ t1 =>
  1523 		(* if "Ex" occurs without an argument (i.e. as argument to a higher-order  *)
  1524 		(* function or predicate), it is handled by the 'stlc_interpreter' (i.e.   *)
  1525 		(* by unfolding its definition)                                            *)
  1526 			let
  1527 				val (i, m, a) = interpret thy model args t1
  1528 			in
  1529 				case i of
  1530 				  Node xs =>
  1531 					let
  1532 						val fmTrue  = PropLogic.exists (map toTrue xs)
  1533 						val fmFalse = PropLogic.all (map toFalse xs)
  1534 					in
  1535 						SOME (Leaf [fmTrue, fmFalse], m, a)
  1536 					end
  1537 				| _ =>
  1538 					raise REFUTE ("HOLogic_interpreter", "\"Ex\" is followed by a non-function")
  1539 			end
  1540 		| Const ("op =", _) $ t1 $ t2 =>
  1541 			let
  1542 				val (i1, m1, a1) = interpret thy model args t1
  1543 				val (i2, m2, a2) = interpret thy m1 a1 t2
  1544 			in
  1545 				SOME (make_equality (i1, i2), m2, a2)
  1546 			end
  1547 		| Const ("op =", _) $ t1 =>
  1548 			SOME (interpret thy model args (eta_expand t 1))
  1549 		| Const ("op =", _) =>
  1550 			SOME (interpret thy model args (eta_expand t 2))
  1551 		| Const ("op &", _) $ t1 $ t2 =>
  1552 			(* 3-valued logic *)
  1553 			let
  1554 				val (i1, m1, a1) = interpret thy model args t1
  1555 				val (i2, m2, a2) = interpret thy m1 a1 t2
  1556 				val fmTrue       = PropLogic.SAnd (toTrue i1, toTrue i2)
  1557 				val fmFalse      = PropLogic.SOr (toFalse i1, toFalse i2)
  1558 			in
  1559 				SOME (Leaf [fmTrue, fmFalse], m2, a2)
  1560 			end
  1561 		| Const ("op &", _) $ t1 =>
  1562 			SOME (interpret thy model args (eta_expand t 1))
  1563 		| Const ("op &", _) =>
  1564 			SOME (interpret thy model args (eta_expand t 2))
  1565 			(* SOME (Node [Node [TT, FF], Node [FF, FF]], model, args) *)
  1566 		| Const ("op |", _) $ t1 $ t2 =>
  1567 			(* 3-valued logic *)
  1568 			let
  1569 				val (i1, m1, a1) = interpret thy model args t1
  1570 				val (i2, m2, a2) = interpret thy m1 a1 t2
  1571 				val fmTrue       = PropLogic.SOr (toTrue i1, toTrue i2)
  1572 				val fmFalse      = PropLogic.SAnd (toFalse i1, toFalse i2)
  1573 			in
  1574 				SOME (Leaf [fmTrue, fmFalse], m2, a2)
  1575 			end
  1576 		| Const ("op |", _) $ t1 =>
  1577 			SOME (interpret thy model args (eta_expand t 1))
  1578 		| Const ("op |", _) =>
  1579 			SOME (interpret thy model args (eta_expand t 2))
  1580 			(* SOME (Node [Node [TT, TT], Node [TT, FF]], model, args) *)
  1581 		| Const ("op -->", _) $ t1 $ t2 =>
  1582 			(* 3-valued logic *)
  1583 			let
  1584 				val (i1, m1, a1) = interpret thy model args t1
  1585 				val (i2, m2, a2) = interpret thy m1 a1 t2
  1586 				val fmTrue       = PropLogic.SOr (toFalse i1, toTrue i2)
  1587 				val fmFalse      = PropLogic.SAnd (toTrue i1, toFalse i2)
  1588 			in
  1589 				SOME (Leaf [fmTrue, fmFalse], m2, a2)
  1590 			end
  1591 		| Const ("op -->", _) =>
  1592 			(* SOME (Node [Node [TT, FF], Node [TT, TT]], model, args) *)
  1593 			SOME (interpret thy model args (eta_expand t 2))
  1594 		| _ => NONE;
  1595 
  1596 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1597 
  1598 	fun set_interpreter thy model args t =
  1599 	(* "T set" is isomorphic to "T --> bool" *)
  1600 	let
  1601 		val (typs, terms) = model
  1602 	in
  1603 		case AList.lookup (op =) terms t of
  1604 		  SOME intr =>
  1605 			(* return an existing interpretation *)
  1606 			SOME (intr, model, args)
  1607 		| NONE =>
  1608 			(case t of
  1609 			  Free (x, Type ("set", [T])) =>
  1610 				let
  1611 					val (intr, _, args') = interpret thy (typs, []) args (Free (x, T --> HOLogic.boolT))
  1612 				in
  1613 					SOME (intr, (typs, (t, intr)::terms), args')
  1614 				end
  1615 			| Var ((x, i), Type ("set", [T])) =>
  1616 				let
  1617 					val (intr, _, args') = interpret thy (typs, []) args (Var ((x,i), T --> HOLogic.boolT))
  1618 				in
  1619 					SOME (intr, (typs, (t, intr)::terms), args')
  1620 				end
  1621 			| Const (s, Type ("set", [T])) =>
  1622 				let
  1623 					val (intr, _, args') = interpret thy (typs, []) args (Const (s, T --> HOLogic.boolT))
  1624 				in
  1625 					SOME (intr, (typs, (t, intr)::terms), args')
  1626 				end
  1627 			(* 'Collect' == identity *)
  1628 			| Const ("Collect", _) $ t1 =>
  1629 				SOME (interpret thy model args t1)
  1630 			| Const ("Collect", _) =>
  1631 				SOME (interpret thy model args (eta_expand t 1))
  1632 			(* 'op :' == application *)
  1633 			| Const ("op :", _) $ t1 $ t2 =>
  1634 				SOME (interpret thy model args (t2 $ t1))
  1635 			| Const ("op :", _) $ t1 =>
  1636 				SOME (interpret thy model args (eta_expand t 1))
  1637 			| Const ("op :", _) =>
  1638 				SOME (interpret thy model args (eta_expand t 2))
  1639 			| _ => NONE)
  1640 	end;
  1641 
  1642 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1643 
  1644 	(* interprets variables and constants whose type is an IDT; constructors of  *)
  1645 	(* IDTs are properly interpreted by 'IDT_constructor_interpreter' however    *)
  1646 
  1647 	fun IDT_interpreter thy model args t =
  1648 	let
  1649 		val (typs, terms) = model
  1650 		(* Term.typ -> (interpretation * model * arguments) option *)
  1651 		fun interpret_term (Type (s, Ts)) =
  1652 			(case DatatypePackage.datatype_info thy s of
  1653 			  SOME info =>  (* inductive datatype *)
  1654 				let
  1655 					(* int option -- only recursive IDTs have an associated depth *)
  1656 					val depth = AList.lookup (op =) typs (Type (s, Ts))
  1657 				in
  1658 					if depth = (SOME 0) then  (* termination condition to avoid infinite recursion *)
  1659 						(* return a leaf of size 0 *)
  1660 						SOME (Leaf [], model, args)
  1661 					else
  1662 						let
  1663 							val index               = #index info
  1664 							val descr               = #descr info
  1665 							val (_, dtyps, constrs) = (the o AList.lookup (op =) descr) index
  1666 							val typ_assoc           = dtyps ~~ Ts
  1667 							(* sanity check: every element in 'dtyps' must be a 'DtTFree' *)
  1668 							val _ = (if Library.exists (fn d =>
  1669 									case d of DatatypeAux.DtTFree _ => false | _ => true) dtyps
  1670 								then
  1671 									raise REFUTE ("IDT_interpreter", "datatype argument (for type " ^ Sign.string_of_typ (sign_of thy) (Type (s, Ts)) ^ ") is not a variable")
  1672 								else
  1673 									())
  1674 							(* if the model specifies a depth for the current type, decrement it to avoid infinite recursion *)
  1675 							val typs'    = case depth of NONE => typs | SOME n =>
  1676 								AList.update (op =) (Type (s, Ts), n-1) typs
  1677 							(* recursively compute the size of the datatype *)
  1678 							val size     = size_of_dtyp thy typs' descr typ_assoc constrs
  1679 							val next_idx = #next_idx args
  1680 							val next     = next_idx+size
  1681 							val _        = (if next-1>(#maxvars args) andalso (#maxvars args)>0 then raise MAXVARS_EXCEEDED else ())  (* check if 'maxvars' is large enough *)
  1682 							(* prop_formula list *)
  1683 							val fms      = map BoolVar (next_idx upto (next_idx+size-1))
  1684 							(* interpretation *)
  1685 							val intr     = Leaf fms
  1686 							(* prop_formula list -> prop_formula *)
  1687 							fun one_of_two_false []      = True
  1688 							  | one_of_two_false (x::xs) = SAnd (PropLogic.all (map (fn x' => SOr (SNot x, SNot x')) xs), one_of_two_false xs)
  1689 							(* prop_formula *)
  1690 							val wf       = one_of_two_false fms
  1691 						in
  1692 							(* extend the model, increase 'next_idx', add well-formedness condition *)
  1693 							SOME (intr, (typs, (t, intr)::terms), {maxvars = #maxvars args, def_eq = #def_eq args, next_idx = next, bounds = #bounds args, wellformed = SAnd (#wellformed args, wf)})
  1694 						end
  1695 				end
  1696 			| NONE =>  (* not an inductive datatype *)
  1697 				NONE)
  1698 		  | interpret_term _ =  (* a (free or schematic) type variable *)
  1699 			NONE
  1700 	in
  1701 		case AList.lookup (op =) terms t of
  1702 		  SOME intr =>
  1703 			(* return an existing interpretation *)
  1704 			SOME (intr, model, args)
  1705 		| NONE =>
  1706 			(case t of
  1707 			  Free (_, T)  => interpret_term T
  1708 			| Var (_, T)   => interpret_term T
  1709 			| Const (_, T) => interpret_term T
  1710 			| _            => NONE)
  1711 	end;
  1712 
  1713 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1714 
  1715 	fun IDT_constructor_interpreter thy model args t =
  1716 	let
  1717 		val (typs, terms) = model
  1718 	in
  1719 		case AList.lookup (op =) terms t of
  1720 		  SOME intr =>
  1721 			(* return an existing interpretation *)
  1722 			SOME (intr, model, args)
  1723 		| NONE =>
  1724 			(case t of
  1725 			  Const (s, T) =>
  1726 				(case body_type T of
  1727 				  Type (s', Ts') =>
  1728 					(case DatatypePackage.datatype_info thy s' of
  1729 					  SOME info =>  (* body type is an inductive datatype *)
  1730 						let
  1731 							val index               = #index info
  1732 							val descr               = #descr info
  1733 							val (_, dtyps, constrs) = (the o AList.lookup (op =) descr) index
  1734 							val typ_assoc           = dtyps ~~ Ts'
  1735 							(* sanity check: every element in 'dtyps' must be a 'DtTFree' *)
  1736 							val _ = (if Library.exists (fn d =>
  1737 									case d of DatatypeAux.DtTFree _ => false | _ => true) dtyps
  1738 								then
  1739 									raise REFUTE ("IDT_constructor_interpreter", "datatype argument (for type " ^ Sign.string_of_typ (sign_of thy) (Type (s', Ts')) ^ ") is not a variable")
  1740 								else
  1741 									())
  1742 							(* split the constructors into those occuring before/after 'Const (s, T)' *)
  1743 							val (constrs1, constrs2) = take_prefix (fn (cname, ctypes) =>
  1744 								not (cname = s andalso Sign.typ_instance thy (T,
  1745 									map (typ_of_dtyp descr typ_assoc) ctypes ---> Type (s', Ts')))) constrs
  1746 						in
  1747 							case constrs2 of
  1748 							  [] =>
  1749 								(* 'Const (s, T)' is not a constructor of this datatype *)
  1750 								NONE
  1751 							| (_, ctypes)::cs =>
  1752 								let
  1753 									(* compute the total size of the datatype (with the current depth) *)
  1754 									val (i, _, _) = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type (s', Ts')))
  1755 									val total     = size_of_type i
  1756 									(* int option -- only recursive IDTs have an associated depth *)
  1757 									val depth = AList.lookup (op =) typs (Type (s', Ts'))
  1758 									val typs' = (case depth of NONE => typs | SOME n =>
  1759 										AList.update (op =) (Type (s', Ts'), n-1) typs)
  1760 									(* returns an interpretation where everything is mapped to "undefined" *)
  1761 									(* DatatypeAux.dtyp list -> interpretation *)
  1762 									fun make_undef [] =
  1763 										Leaf (replicate total False)
  1764 									  | make_undef (d::ds) =
  1765 										let
  1766 											(* compute the current size of the type 'd' *)
  1767 											val T           = typ_of_dtyp descr typ_assoc d
  1768 											val (i, _, _)   = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1769 											val size        = size_of_type i
  1770 										in
  1771 											Node (replicate size (make_undef ds))
  1772 										end
  1773 									(* returns the interpretation for a constructor at depth 1 *)
  1774 									(* int * DatatypeAux.dtyp list -> int * interpretation *)
  1775 									fun make_constr (offset, []) =
  1776 										if offset<total then
  1777 											(offset+1, Leaf ((replicate offset False) @ True :: (replicate (total-offset-1) False)))
  1778 										else
  1779 											raise REFUTE ("IDT_constructor_interpreter", "offset >= total")
  1780 									  | make_constr (offset, d::ds) =
  1781 										let
  1782 											(* compute the current and the old size of the type 'd' *)
  1783 											val T           = typ_of_dtyp descr typ_assoc d
  1784 											val (i, _, _)   = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1785 											val size        = size_of_type i
  1786 											val (i', _, _)  = interpret thy (typs', []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1787 											val size'       = size_of_type i'
  1788 											(* sanity check *)
  1789 											val _           = if size < size' then
  1790 													raise REFUTE ("IDT_constructor_interpreter", "current size is less than old size")
  1791 												else
  1792 													()
  1793 											(* int * interpretation list *)
  1794 											val (new_offset, intrs) = foldl_map make_constr (offset, replicate size' ds)
  1795 											(* interpretation list *)
  1796 											val undefs              = replicate (size - size') (make_undef ds)
  1797 										in
  1798 											(* elements that exist at the previous depth are mapped to a defined *)
  1799 											(* value, while new elements are mapped to "undefined" by the        *)
  1800 											(* recursive constructor                                             *)
  1801 											(new_offset, Node (intrs @ undefs))
  1802 										end
  1803 									(* extends the interpretation for a constructor (both recursive *)
  1804 									(* and non-recursive) obtained at depth n (n>=1) to depth n+1   *)
  1805 									(* int * DatatypeAux.dtyp list * interpretation -> int * interpretation *)
  1806 									fun extend_constr (offset, [], Leaf xs) =
  1807 										let
  1808 											(* returns the k-th unit vector of length n *)
  1809 											(* int * int -> interpretation *)
  1810 											fun unit_vector (k, n) =
  1811 												Leaf ((replicate (k-1) False) @ (True :: (replicate (n-k) False)))
  1812 											(* int *)
  1813 											val k = find_index_eq True xs
  1814 										in
  1815 											if k=(~1) then
  1816 												(* if the element was mapped to "undefined" before, map it to   *)
  1817 												(* the value given by 'offset' now (and extend the length of    *)
  1818 												(* the leaf)                                                    *)
  1819 												(offset+1, unit_vector (offset+1, total))
  1820 											else
  1821 												(* if the element was already mapped to a defined value, map it *)
  1822 												(* to the same value again, just extend the length of the leaf, *)
  1823 												(* do not increment the 'offset'                                *)
  1824 												(offset, unit_vector (k+1, total))
  1825 										end
  1826 									  | extend_constr (_, [], Node _) =
  1827 										raise REFUTE ("IDT_constructor_interpreter", "interpretation for constructor (with no arguments left) is a node")
  1828 									  | extend_constr (offset, d::ds, Node xs) =
  1829 										let
  1830 											(* compute the size of the type 'd' *)
  1831 											val T          = typ_of_dtyp descr typ_assoc d
  1832 											val (i, _, _)  = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1833 											val size       = size_of_type i
  1834 											(* sanity check *)
  1835 											val _          = if size < length xs then
  1836 													raise REFUTE ("IDT_constructor_interpreter", "new size of type is less than old size")
  1837 												else
  1838 													()
  1839 											(* extend the existing interpretations *)
  1840 											(* int * interpretation list *)
  1841 											val (new_offset, intrs) = foldl_map (fn (off, i) => extend_constr (off, ds, i)) (offset, xs)
  1842 											(* new elements of the type 'd' are mapped to "undefined" *)
  1843 											val undefs = replicate (size - length xs) (make_undef ds)
  1844 										in
  1845 											(new_offset, Node (intrs @ undefs))
  1846 										end
  1847 									  | extend_constr (_, d::ds, Leaf _) =
  1848 										raise REFUTE ("IDT_constructor_interpreter", "interpretation for constructor (with arguments left) is a leaf")
  1849 									(* returns 'true' iff the constructor has a recursive argument *)
  1850 									(* DatatypeAux.dtyp list -> bool *)
  1851 									fun is_rec_constr ds =
  1852 										Library.exists DatatypeAux.is_rec_type ds
  1853 									(* constructors before 'Const (s, T)' generate elements of the datatype *)
  1854 									val offset = size_of_dtyp thy typs' descr typ_assoc constrs1
  1855 								in
  1856 									case depth of
  1857 									  NONE =>  (* equivalent to a depth of 1 *)
  1858 										SOME (snd (make_constr (offset, ctypes)), model, args)
  1859 									| SOME 0 =>
  1860 										raise REFUTE ("IDT_constructor_interpreter", "depth is 0")
  1861 									| SOME 1 =>
  1862 										SOME (snd (make_constr (offset, ctypes)), model, args)
  1863 									| SOME n =>  (* n > 1 *)
  1864 										let
  1865 											(* interpret the constructor at depth-1 *)
  1866 											val (iC, _, _) = interpret thy (typs', []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Const (s, T))
  1867 											(* elements generated by the constructor at depth-1 must be added to 'offset' *)
  1868 											(* interpretation -> int *)
  1869 											fun number_of_defined_elements (Leaf xs) =
  1870 												if find_index_eq True xs = (~1) then 0 else 1
  1871 											  | number_of_defined_elements (Node xs) =
  1872 												sum (map number_of_defined_elements xs)
  1873 											(* int *)
  1874 											val offset' = offset + number_of_defined_elements iC
  1875 										in
  1876 											SOME (snd (extend_constr (offset', ctypes, iC)), model, args)
  1877 										end
  1878 								end
  1879 						end
  1880 					| NONE =>  (* body type is not an inductive datatype *)
  1881 						NONE)
  1882 				| _ =>  (* body type is a (free or schematic) type variable *)
  1883 					NONE)
  1884 			| _ =>  (* term is not a constant *)
  1885 				NONE)
  1886 	end;
  1887 
  1888 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  1889 
  1890 	(* Difficult code ahead.  Make sure you understand the 'IDT_constructor_interpreter' *)
  1891 	(* and the order in which it enumerates elements of an IDT before you try to         *)
  1892 	(* understand this function.                                                         *)
  1893 
  1894 	fun IDT_recursion_interpreter thy model args t =
  1895 		case strip_comb t of  (* careful: here we descend arbitrarily deep into 't', *)
  1896 		                      (* possibly before any other interpreter for atomic    *)
  1897 		                      (* terms has had a chance to look at 't'               *)
  1898 		  (Const (s, T), params) =>
  1899 			(* iterate over all datatypes in 'thy' *)
  1900 			Symtab.foldl (fn (result, (_, info)) =>
  1901 				case result of
  1902 				  SOME _ =>
  1903 					result  (* just keep 'result' *)
  1904 				| NONE =>
  1905 					if s mem (#rec_names info) then
  1906 						(* we do have a recursion operator of the datatype given by 'info', *)
  1907 						(* or of a mutually recursive datatype                              *)
  1908 						let
  1909 							val index              = #index info
  1910 							val descr              = #descr info
  1911 							val (dtname, dtyps, _) = (the o AList.lookup (op =) descr) index
  1912 							(* number of all constructors, including those of different           *)
  1913 							(* (mutually recursive) datatypes within the same descriptor 'descr'  *)
  1914 							val mconstrs_count     = sum (map (fn (_, (_, _, cs)) => length cs) descr)
  1915 							val params_count       = length params
  1916 							(* the type of a recursion operator: [T1, ..., Tn, IDT] ---> Tresult *)
  1917 							val IDT = List.nth (binder_types T, mconstrs_count)
  1918 						in
  1919 							if (fst o dest_Type) IDT <> dtname then
  1920 								(* recursion operator of a mutually recursive datatype *)
  1921 								NONE
  1922 							else if mconstrs_count < params_count then
  1923 								(* too many actual parameters; for now we'll use the *)
  1924 								(* 'stlc_interpreter' to strip off one application   *)
  1925 								NONE
  1926 							else if mconstrs_count > params_count then
  1927 								(* too few actual parameters; we use eta expansion            *)
  1928 								(* Note that the resulting expansion of lambda abstractions   *)
  1929 								(* by the 'stlc_interpreter' may be rather slow (depending on *)
  1930 								(* the argument types and the size of the IDT, of course).    *)
  1931 								SOME (interpret thy model args (eta_expand t (mconstrs_count - params_count)))
  1932 							else  (* mconstrs_count = params_count *)
  1933 								let
  1934 									(* interpret each parameter separately *)
  1935 									val ((model', args'), p_intrs) = foldl_map (fn ((m, a), p) =>
  1936 										let
  1937 											val (i, m', a') = interpret thy m a p
  1938 										in
  1939 											((m', a'), i)
  1940 										end) ((model, args), params)
  1941 									val (typs, _) = model'
  1942 									val typ_assoc = dtyps ~~ (snd o dest_Type) IDT
  1943 									(* interpret each constructor in the descriptor (including *)
  1944 									(* those of mutually recursive datatypes)                  *)
  1945 									(* (int * interpretation list) list *)
  1946 									val mc_intrs = map (fn (idx, (_, _, cs)) =>
  1947 										let
  1948 											val c_return_typ = typ_of_dtyp descr typ_assoc (DatatypeAux.DtRec idx)
  1949 										in
  1950 											(idx, map (fn (cname, cargs) =>
  1951 												(#1 o interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True})
  1952 													(Const (cname, map (typ_of_dtyp descr typ_assoc) cargs ---> c_return_typ))) cs)
  1953 										end) descr
  1954 									(* the recursion operator is a function that maps every element of *)
  1955 									(* the inductive datatype (and of mutually recursive types) to an  *)
  1956 									(* element of some result type; an array entry of NONE means that  *)
  1957 									(* the actual result has not been computed yet                     *)
  1958 									(* (int * interpretation option Array.array) list *)
  1959 									val INTRS = map (fn (idx, _) =>
  1960 										let
  1961 											val T         = typ_of_dtyp descr typ_assoc (DatatypeAux.DtRec idx)
  1962 											val (i, _, _) = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  1963 											val size      = size_of_type i
  1964 										in
  1965 											(idx, Array.array (size, NONE))
  1966 										end) descr
  1967 									(* takes an interpretation, and if some leaf of this interpretation   *)
  1968 									(* is the 'elem'-th element of the type, the indices of the arguments *)
  1969 									(* leading to this leaf are returned                                  *)
  1970 									(* interpretation -> int -> int list option *)
  1971 									fun get_args (Leaf xs) elem =
  1972 										if find_index_eq True xs = elem then
  1973 											SOME []
  1974 										else
  1975 											NONE
  1976 									  | get_args (Node xs) elem =
  1977 										let
  1978 											(* interpretation * int -> int list option *)
  1979 											fun search ([], _) =
  1980 												NONE
  1981 											  | search (x::xs, n) =
  1982 												(case get_args x elem of
  1983 												  SOME result => SOME (n::result)
  1984 												| NONE        => search (xs, n+1))
  1985 										in
  1986 											search (xs, 0)
  1987 										end
  1988 									(* returns the index of the constructor and indices for its      *)
  1989 									(* arguments that generate the 'elem'-th element of the datatype *)
  1990 									(* given by 'idx'                                                *)
  1991 									(* int -> int -> int * int list *)
  1992 									fun get_cargs idx elem =
  1993 										let
  1994 											(* int * interpretation list -> int * int list *)
  1995 											fun get_cargs_rec (_, []) =
  1996 												raise REFUTE ("IDT_recursion_interpreter", "no matching constructor found for element " ^ string_of_int elem ^ " in datatype " ^ Sign.string_of_typ (sign_of thy) IDT ^ " (datatype index " ^ string_of_int idx ^ ")")
  1997 											  | get_cargs_rec (n, x::xs) =
  1998 												(case get_args x elem of
  1999 												  SOME args => (n, args)
  2000 												| NONE      => get_cargs_rec (n+1, xs))
  2001 										in
  2002 											get_cargs_rec (0, (the o AList.lookup (op =) mc_intrs) idx)
  2003 										end
  2004 									(* returns the number of constructors in datatypes that occur in *)
  2005 									(* the descriptor 'descr' before the datatype given by 'idx'     *)
  2006 									fun get_coffset idx =
  2007 										let
  2008 											fun get_coffset_acc _ [] =
  2009 												raise REFUTE ("IDT_recursion_interpreter", "index " ^ string_of_int idx ^ " not found in descriptor")
  2010 											  | get_coffset_acc sum ((i, (_, _, cs))::descr') =
  2011 												if i=idx then
  2012 													sum
  2013 												else
  2014 													get_coffset_acc (sum + length cs) descr'
  2015 										in
  2016 											get_coffset_acc 0 descr
  2017 										end
  2018 									(* computes one entry in INTRS, and recursively all entries needed for it, *)
  2019 									(* where 'idx' gives the datatype and 'elem' the element of it             *)
  2020 									(* int -> int -> interpretation *)
  2021 									fun compute_array_entry idx elem =
  2022 										case Array.sub ((the o AList.lookup (op =) INTRS) idx, elem) of
  2023 										  SOME result =>
  2024 											(* simply return the previously computed result *)
  2025 											result
  2026 										| NONE =>
  2027 											let
  2028 												(* int * int list *)
  2029 												val (c, args) = get_cargs idx elem
  2030 												(* interpretation * int list -> interpretation *)
  2031 												fun select_subtree (tr, []) =
  2032 													tr  (* return the whole tree *)
  2033 												  | select_subtree (Leaf _, _) =
  2034 													raise REFUTE ("IDT_recursion_interpreter", "interpretation for parameter is a leaf; cannot select a subtree")
  2035 												  | select_subtree (Node tr, x::xs) =
  2036 													select_subtree (List.nth (tr, x), xs)
  2037 												(* select the correct subtree of the parameter corresponding to constructor 'c' *)
  2038 												val p_intr = select_subtree (List.nth (p_intrs, get_coffset idx + c), args)
  2039 												(* find the indices of the constructor's recursive arguments *)
  2040 												val (_, _, constrs) = (the o AList.lookup (op =) descr) idx
  2041 												val constr_args     = (snd o List.nth) (constrs, c)
  2042 												val rec_args        = List.filter (DatatypeAux.is_rec_type o fst) (constr_args ~~ args)
  2043 												val rec_args'       = map (fn (dtyp, elem) => (DatatypeAux.dest_DtRec dtyp, elem)) rec_args
  2044 												(* apply 'p_intr' to recursively computed results *)
  2045 												val result = foldl (fn ((idx, elem), intr) =>
  2046 													interpretation_apply (intr, compute_array_entry idx elem)) p_intr rec_args'
  2047 												(* update 'INTRS' *)
  2048 												val _ = Array.update ((the o AList.lookup (op =) INTRS) idx, elem, SOME result)
  2049 											in
  2050 												result
  2051 											end
  2052 									(* compute all entries in INTRS for the current datatype (given by 'index') *)
  2053 									(* TODO: we can use Array.modify instead once PolyML conforms to the ML standard *)
  2054 									(* (int * 'a -> 'a) -> 'a array -> unit *)
  2055 									fun modifyi f arr =
  2056 										let
  2057 											val size = Array.length arr
  2058 											fun modifyi_loop i =
  2059 												if i < size then (
  2060 													Array.update (arr, i, f (i, Array.sub (arr, i)));
  2061 													modifyi_loop (i+1)
  2062 												) else
  2063 													()
  2064 										in
  2065 											modifyi_loop 0
  2066 										end
  2067 									val _ = modifyi (fn (i, _) => SOME (compute_array_entry index i)) ((the o AList.lookup (op =) INTRS) index)
  2068 									(* 'a Array.array -> 'a list *)
  2069 									fun toList arr =
  2070 										Array.foldr op:: [] arr
  2071 								in
  2072 									(* return the part of 'INTRS' that corresponds to the current datatype *)
  2073 									SOME ((Node o map the o toList o the o AList.lookup (op =) INTRS) index, model', args')
  2074 								end
  2075 						end
  2076 					else
  2077 						NONE  (* not a recursion operator of this datatype *)
  2078 				) (NONE, DatatypePackage.get_datatypes thy)
  2079 		| _ =>  (* head of term is not a constant *)
  2080 			NONE;
  2081 
  2082 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2083 
  2084 	(* only an optimization: 'card' could in principle be interpreted with    *)
  2085 	(* interpreters available already (using its definition), but the code    *)
  2086 	(* below is more efficient                                                *)
  2087 
  2088 	fun Finite_Set_card_interpreter thy model args t =
  2089 		case t of
  2090 		  Const ("Finite_Set.card", Type ("fun", [Type ("set", [T]), Type ("nat", [])])) =>
  2091 			let
  2092 				val (i_nat, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("nat", [])))
  2093 				val size_nat      = size_of_type i_nat
  2094 				val (i_set, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("set", [T])))
  2095 				val constants     = make_constants i_set
  2096 				(* interpretation -> int *)
  2097 				fun number_of_elements (Node xs) =
  2098 					Library.foldl (fn (n, x) =>
  2099 						if x=TT then
  2100 							n+1
  2101 						else if x=FF then
  2102 							n
  2103 						else
  2104 							raise REFUTE ("Finite_Set_card_interpreter", "interpretation for set type does not yield a Boolean")) (0, xs)
  2105 				  | number_of_elements (Leaf _) =
  2106 					raise REFUTE ("Finite_Set_card_interpreter", "interpretation for set type is a leaf")
  2107 				(* takes an interpretation for a set and returns an interpretation for a 'nat' *)
  2108 				(* interpretation -> interpretation *)
  2109 				fun card i =
  2110 					let
  2111 						val n = number_of_elements i
  2112 					in
  2113 						if n<size_nat then
  2114 							Leaf ((replicate n False) @ True :: (replicate (size_nat-n-1) False))
  2115 						else
  2116 							Leaf (replicate size_nat False)
  2117 					end
  2118 			in
  2119 				SOME (Node (map card constants), model, args)
  2120 			end
  2121 		| _ =>
  2122 			NONE;
  2123 
  2124 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2125 
  2126 	(* only an optimization: 'Finites' could in principle be interpreted with *)
  2127 	(* interpreters available already (using its definition), but the code    *)
  2128 	(* below is more efficient                                                *)
  2129 
  2130 	fun Finite_Set_Finites_interpreter thy model args t =
  2131 		case t of
  2132 		  Const ("Finite_Set.Finites", Type ("set", [Type ("set", [T])])) =>
  2133 			let
  2134 				val (i_set, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("set", [T])))
  2135 				val size_set      = size_of_type i_set
  2136 			in
  2137 				(* we only consider finite models anyway, hence EVERY set is in "Finites" *)
  2138 				SOME (Node (replicate size_set TT), model, args)
  2139 			end
  2140 		| _ =>
  2141 			NONE;
  2142 
  2143 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2144 
  2145 	(* only an optimization: 'op <' could in principle be interpreted with    *)
  2146 	(* interpreters available already (using its definition), but the code    *)
  2147 	(* below is more efficient                                                *)
  2148 
  2149 	fun Nat_less_interpreter thy model args t =
  2150 		case t of
  2151 		  Const ("op <", Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("bool", [])])])) =>
  2152 			let
  2153 				val (i_nat, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("nat", [])))
  2154 				val size_nat      = size_of_type i_nat
  2155 				(* int -> interpretation *)
  2156 				(* the 'n'-th nat is not less than the first 'n' nats, while it *)
  2157 				(* is less than the remaining 'size_nat - n' nats               *)
  2158 				fun less n = Node ((replicate n FF) @ (replicate (size_nat - n) TT))
  2159 			in
  2160 				SOME (Node (map less (1 upto size_nat)), model, args)
  2161 			end
  2162 		| _ =>
  2163 			NONE;
  2164 
  2165 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2166 
  2167 	(* only an optimization: 'op +' could in principle be interpreted with    *)
  2168 	(* interpreters available already (using its definition), but the code    *)
  2169 	(* below is more efficient                                                *)
  2170 
  2171 	fun Nat_plus_interpreter thy model args t =
  2172 		case t of
  2173 		  Const ("op +", Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) =>
  2174 			let
  2175 				val (i_nat, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("nat", [])))
  2176 				val size_nat      = size_of_type i_nat
  2177 				(* int -> int -> interpretation *)
  2178 				fun plus m n =
  2179 					let
  2180 						val element = (m+n)+1
  2181 					in
  2182 						if element > size_nat then
  2183 							Leaf (replicate size_nat False)
  2184 						else
  2185 							Leaf ((replicate (element-1) False) @ True :: (replicate (size_nat - element) False))
  2186 					end
  2187 			in
  2188 				SOME (Node (map (fn m => Node (map (plus m) (0 upto size_nat-1))) (0 upto size_nat-1)), model, args)
  2189 			end
  2190 		| _ =>
  2191 			NONE;
  2192 
  2193 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2194 
  2195 	(* only an optimization: 'op -' could in principle be interpreted with    *)
  2196 	(* interpreters available already (using its definition), but the code    *)
  2197 	(* below is more efficient                                                *)
  2198 
  2199 	fun Nat_minus_interpreter thy model args t =
  2200 		case t of
  2201 		  Const ("op -", Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) =>
  2202 			let
  2203 				val (i_nat, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("nat", [])))
  2204 				val size_nat      = size_of_type i_nat
  2205 				(* int -> int -> interpretation *)
  2206 				fun minus m n =
  2207 					let
  2208 						val element = Int.max (m-n, 0) + 1
  2209 					in
  2210 						Leaf ((replicate (element-1) False) @ True :: (replicate (size_nat - element) False))
  2211 					end
  2212 			in
  2213 				SOME (Node (map (fn m => Node (map (minus m) (0 upto size_nat-1))) (0 upto size_nat-1)), model, args)
  2214 			end
  2215 		| _ =>
  2216 			NONE;
  2217 
  2218 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2219 
  2220 	(* only an optimization: 'op *' could in principle be interpreted with    *)
  2221 	(* interpreters available already (using its definition), but the code    *)
  2222 	(* below is more efficient                                                *)
  2223 
  2224 	fun Nat_mult_interpreter thy model args t =
  2225 		case t of
  2226 		  Const ("op *", Type ("fun", [Type ("nat", []), Type ("fun", [Type ("nat", []), Type ("nat", [])])])) =>
  2227 			let
  2228 				val (i_nat, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("nat", [])))
  2229 				val size_nat      = size_of_type i_nat
  2230 				(* nat -> nat -> interpretation *)
  2231 				fun mult m n =
  2232 					let
  2233 						val element = (m*n)+1
  2234 					in
  2235 						if element > size_nat then
  2236 							Leaf (replicate size_nat False)
  2237 						else
  2238 							Leaf ((replicate (element-1) False) @ True :: (replicate (size_nat - element) False))
  2239 					end
  2240 			in
  2241 				SOME (Node (map (fn m => Node (map (mult m) (0 upto size_nat-1))) (0 upto size_nat-1)), model, args)
  2242 			end
  2243 		| _ =>
  2244 			NONE;
  2245 
  2246 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2247 
  2248 	(* only an optimization: 'op @' could in principle be interpreted with    *)
  2249 	(* interpreters available already (using its definition), but the code    *)
  2250 	(* below is more efficient                                                *)
  2251 
  2252 	fun List_append_interpreter thy model args t =
  2253 		case t of
  2254 		  Const ("List.op @", Type ("fun", [Type ("List.list", [T]), Type ("fun", [Type ("List.list", [_]), Type ("List.list", [_])])])) =>
  2255 			let
  2256 				val (i_elem, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  2257 				val size_elem      = size_of_type i_elem
  2258 				val (i_list, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("List.list", [T])))
  2259 				val size_list      = size_of_type i_list
  2260 				(* power (a, b) computes a^b, for a>=0, b>=0 *)
  2261 				(* int * int -> int *)
  2262 				fun power (a, 0) = 1
  2263 				  | power (a, 1) = a
  2264 				  | power (a, b) = let val ab = power(a, b div 2) in ab * ab * power(a, b mod 2) end
  2265 				(* log (a, b) computes floor(log_a(b)), i.e. the largest integer x s.t. a^x <= b, for a>=2, b>=1 *)
  2266 				(* int * int -> int *)
  2267 				fun log (a, b) =
  2268 					let
  2269 						fun logloop (ax, x) =
  2270 							if ax > b then x-1 else logloop (a * ax, x+1)
  2271 					in
  2272 						logloop (1, 0)
  2273 					end
  2274 				(* nat -> nat -> interpretation *)
  2275 				fun append m n =
  2276 					let
  2277 						(* The following formula depends on the order in which lists are *)
  2278 						(* enumerated by the 'IDT_constructor_interpreter'.  It took me  *)
  2279 						(* a while to come up with this formula.                         *)
  2280 						val element = n + m * (if size_elem = 1 then 1 else power (size_elem, log (size_elem, n+1))) + 1
  2281 					in
  2282 						if element > size_list then
  2283 							Leaf (replicate size_list False)
  2284 						else
  2285 							Leaf ((replicate (element-1) False) @ True :: (replicate (size_list - element) False))
  2286 					end
  2287 			in
  2288 				SOME (Node (map (fn m => Node (map (append m) (0 upto size_list-1))) (0 upto size_list-1)), model, args)
  2289 			end
  2290 		| _ =>
  2291 			NONE;
  2292 
  2293 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2294 
  2295 	(* only an optimization: 'lfp' could in principle be interpreted with     *)
  2296 	(* interpreters available already (using its definition), but the code    *)
  2297 	(* below is more efficient                                                *)
  2298 
  2299 	fun Lfp_lfp_interpreter thy model args t =
  2300 		case t of
  2301 		  Const ("Lfp.lfp", Type ("fun", [Type ("fun", [Type ("set", [T]), Type ("set", [_])]), Type ("set", [_])])) =>
  2302 			let
  2303 				val (i_elem, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  2304 				val size_elem      = size_of_type i_elem
  2305 				(* the universe (i.e. the set that contains every element) *)
  2306 				val i_univ         = Node (replicate size_elem TT)
  2307 				(* all sets with elements from type 'T' *)
  2308 				val (i_set, _, _)  = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("set", [T])))
  2309 				val i_sets         = make_constants i_set
  2310 				(* all functions that map sets to sets *)
  2311 				val (i_fun, _, _)  = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("fun", [Type ("set", [T]), Type ("set", [T])])))
  2312 				val i_funs         = make_constants i_fun
  2313 				(* "lfp(f) == Inter({u. f(u) <= u})" *)
  2314 				(* interpretation * interpretation -> bool *)
  2315 				fun is_subset (Node subs, Node sups) =
  2316 					List.all (fn (sub, sup) => (sub = FF) orelse (sup = TT)) (subs ~~ sups)
  2317 				  | is_subset (_, _) =
  2318 					raise REFUTE ("Lfp_lfp_interpreter", "is_subset: interpretation for set is not a node")
  2319 				(* interpretation * interpretation -> interpretation *)
  2320 				fun intersection (Node xs, Node ys) =
  2321 					Node (map (fn (x, y) => if (x = TT) andalso (y = TT) then TT else FF) (xs ~~ ys))
  2322 				  | intersection (_, _) =
  2323 					raise REFUTE ("Lfp_lfp_interpreter", "intersection: interpretation for set is not a node")
  2324 				(* interpretation -> interpretaion *)
  2325 				fun lfp (Node resultsets) =
  2326 					foldl (fn ((set, resultset), acc) =>
  2327 						if is_subset (resultset, set) then
  2328 							intersection (acc, set)
  2329 						else
  2330 							acc) i_univ (i_sets ~~ resultsets)
  2331 				  | lfp _ =
  2332 						raise REFUTE ("Lfp_lfp_interpreter", "lfp: interpretation for function is not a node")
  2333 			in
  2334 				SOME (Node (map lfp i_funs), model, args)
  2335 			end
  2336 		| _ =>
  2337 			NONE;
  2338 
  2339 	(* theory -> model -> arguments -> Term.term -> (interpretation * model * arguments) option *)
  2340 
  2341 	(* only an optimization: 'gfp' could in principle be interpreted with     *)
  2342 	(* interpreters available already (using its definition), but the code    *)
  2343 	(* below is more efficient                                                *)
  2344 
  2345 	fun Gfp_gfp_interpreter thy model args t =
  2346 		case t of
  2347 		  Const ("Gfp.gfp", Type ("fun", [Type ("fun", [Type ("set", [T]), Type ("set", [_])]), Type ("set", [_])])) =>
  2348 			let nonfix union (*because "union" is used below*)
  2349 				val (i_elem, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  2350 				val size_elem      = size_of_type i_elem
  2351 				(* the universe (i.e. the set that contains every element) *)
  2352 				val i_univ         = Node (replicate size_elem TT)
  2353 				(* all sets with elements from type 'T' *)
  2354 				val (i_set, _, _)  = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("set", [T])))
  2355 				val i_sets         = make_constants i_set
  2356 				(* all functions that map sets to sets *)
  2357 				val (i_fun, _, _)  = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", Type ("fun", [Type ("set", [T]), Type ("set", [T])])))
  2358 				val i_funs         = make_constants i_fun
  2359 				(* "gfp(f) == Union({u. u <= f(u)})" *)
  2360 				(* interpretation * interpretation -> bool *)
  2361 				fun is_subset (Node subs, Node sups) =
  2362 					List.all (fn (sub, sup) => (sub = FF) orelse (sup = TT)) (subs ~~ sups)
  2363 				  | is_subset (_, _) =
  2364 					raise REFUTE ("Gfp_gfp_interpreter", "is_subset: interpretation for set is not a node")
  2365 				(* interpretation * interpretation -> interpretation *)
  2366 				fun union (Node xs, Node ys) =
  2367 					  Node (map (fn (x,y) => if x=TT orelse y=TT then TT else FF) 
  2368 					       (xs ~~ ys))
  2369 				  | union (_, _) =
  2370 					raise REFUTE ("Gfp_gfp_interpreter", "union: interpretation for set is not a node")
  2371 				(* interpretation -> interpretaion *)
  2372 				fun gfp (Node resultsets) =
  2373 					foldl (fn ((set, resultset), acc) =>
  2374 						   if is_subset (set, resultset) then union (acc, set)
  2375 						   else acc) 
  2376 				  	      i_univ  (i_sets ~~ resultsets)
  2377 				  | gfp _ =
  2378 						raise REFUTE ("Gfp_gfp_interpreter", "gfp: interpretation for function is not a node")
  2379 			in
  2380 				SOME (Node (map gfp i_funs), model, args)
  2381 			end
  2382 		| _ =>
  2383 			NONE;
  2384 
  2385 
  2386 (* ------------------------------------------------------------------------- *)
  2387 (* PRINTERS                                                                  *)
  2388 (* ------------------------------------------------------------------------- *)
  2389 
  2390 	(* theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term option *)
  2391 
  2392 	fun stlc_printer thy model t intr assignment =
  2393 	let
  2394 		(* Term.term -> Term.typ option *)
  2395 		fun typeof (Free (_, T))  = SOME T
  2396 		  | typeof (Var (_, T))   = SOME T
  2397 		  | typeof (Const (_, T)) = SOME T
  2398 		  | typeof _              = NONE
  2399 		(* string -> string *)
  2400 		fun strip_leading_quote s =
  2401 			(implode o (fn ss => case ss of [] => [] | x::xs => if x="'" then xs else ss) o explode) s
  2402 		(* Term.typ -> string *)
  2403 		fun string_of_typ (Type (s, _))     = s
  2404 		  | string_of_typ (TFree (x, _))    = strip_leading_quote x
  2405 		  | string_of_typ (TVar ((x,i), _)) = strip_leading_quote x ^ string_of_int i
  2406 		(* interpretation -> int *)
  2407 		fun index_from_interpretation (Leaf xs) =
  2408 			find_index (PropLogic.eval assignment) xs
  2409 		  | index_from_interpretation _ =
  2410 			raise REFUTE ("stlc_printer", "interpretation for ground type is not a leaf")
  2411 	in
  2412 		case typeof t of
  2413 		  SOME T =>
  2414 			(case T of
  2415 			  Type ("fun", [T1, T2]) =>
  2416 				let
  2417 					(* create all constants of type 'T1' *)
  2418 					val (i, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T1))
  2419 					val constants = make_constants i
  2420 					(* interpretation list *)
  2421 					val results = (case intr of
  2422 						  Node xs => xs
  2423 						| _       => raise REFUTE ("stlc_printer", "interpretation for function type is a leaf"))
  2424 					(* Term.term list *)
  2425 					val pairs = map (fn (arg, result) =>
  2426 						HOLogic.mk_prod
  2427 							(print thy model (Free ("dummy", T1)) arg assignment,
  2428 							 print thy model (Free ("dummy", T2)) result assignment))
  2429 						(constants ~~ results)
  2430 					(* Term.typ *)
  2431 					val HOLogic_prodT = HOLogic.mk_prodT (T1, T2)
  2432 					val HOLogic_setT  = HOLogic.mk_setT HOLogic_prodT
  2433 					(* Term.term *)
  2434 					val HOLogic_empty_set = Const ("{}", HOLogic_setT)
  2435 					val HOLogic_insert    = Const ("insert", HOLogic_prodT --> HOLogic_setT --> HOLogic_setT)
  2436 				in
  2437 					SOME (foldr (fn (pair, acc) => HOLogic_insert $ pair $ acc) HOLogic_empty_set pairs)
  2438 				end
  2439 			| Type ("prop", [])      =>
  2440 				(case index_from_interpretation intr of
  2441 				  (~1) => SOME (HOLogic.mk_Trueprop (Const ("arbitrary", HOLogic.boolT)))
  2442 				| 0    => SOME (HOLogic.mk_Trueprop HOLogic.true_const)
  2443 				| 1    => SOME (HOLogic.mk_Trueprop HOLogic.false_const)
  2444 				| _    => raise REFUTE ("stlc_interpreter", "illegal interpretation for a propositional value"))
  2445 			| Type _  => if index_from_interpretation intr = (~1) then
  2446 					SOME (Const ("arbitrary", T))
  2447 				else
  2448 					SOME (Const (string_of_typ T ^ string_of_int (index_from_interpretation intr), T))
  2449 			| TFree _ => if index_from_interpretation intr = (~1) then
  2450 					SOME (Const ("arbitrary", T))
  2451 				else
  2452 					SOME (Const (string_of_typ T ^ string_of_int (index_from_interpretation intr), T))
  2453 			| TVar _  => if index_from_interpretation intr = (~1) then
  2454 					SOME (Const ("arbitrary", T))
  2455 				else
  2456 					SOME (Const (string_of_typ T ^ string_of_int (index_from_interpretation intr), T)))
  2457 		| NONE =>
  2458 			NONE
  2459 	end;
  2460 
  2461 	(* theory -> model -> Term.term -> interpretation -> (int -> bool) -> string option *)
  2462 
  2463 	fun set_printer thy model t intr assignment =
  2464 	let
  2465 		(* Term.term -> Term.typ option *)
  2466 		fun typeof (Free (_, T))  = SOME T
  2467 		  | typeof (Var (_, T))   = SOME T
  2468 		  | typeof (Const (_, T)) = SOME T
  2469 		  | typeof _              = NONE
  2470 	in
  2471 		case typeof t of
  2472 		  SOME (Type ("set", [T])) =>
  2473 			let
  2474 				(* create all constants of type 'T' *)
  2475 				val (i, _, _) = interpret thy model {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", T))
  2476 				val constants = make_constants i
  2477 				(* interpretation list *)
  2478 				val results = (case intr of
  2479 					  Node xs => xs
  2480 					| _       => raise REFUTE ("set_printer", "interpretation for set type is a leaf"))
  2481 				(* Term.term list *)
  2482 				val elements = List.mapPartial (fn (arg, result) =>
  2483 					case result of
  2484 					  Leaf [fmTrue, fmFalse] =>
  2485 						if PropLogic.eval assignment fmTrue then
  2486 							SOME (print thy model (Free ("dummy", T)) arg assignment)
  2487 						else (*if PropLogic.eval assignment fmFalse then*)
  2488 							NONE
  2489 					| _ =>
  2490 						raise REFUTE ("set_printer", "illegal interpretation for a Boolean value"))
  2491 					(constants ~~ results)
  2492 				(* Term.typ *)
  2493 				val HOLogic_setT  = HOLogic.mk_setT T
  2494 				(* Term.term *)
  2495 				val HOLogic_empty_set = Const ("{}", HOLogic_setT)
  2496 				val HOLogic_insert    = Const ("insert", T --> HOLogic_setT --> HOLogic_setT)
  2497 			in
  2498 				SOME (Library.foldl (fn (acc, elem) => HOLogic_insert $ elem $ acc) (HOLogic_empty_set, elements))
  2499 			end
  2500 		| _ =>
  2501 			NONE
  2502 	end;
  2503 
  2504 	(* theory -> model -> Term.term -> interpretation -> (int -> bool) -> Term.term option *)
  2505 
  2506 	fun IDT_printer thy model t intr assignment =
  2507 	let
  2508 		(* Term.term -> Term.typ option *)
  2509 		fun typeof (Free (_, T))  = SOME T
  2510 		  | typeof (Var (_, T))   = SOME T
  2511 		  | typeof (Const (_, T)) = SOME T
  2512 		  | typeof _              = NONE
  2513 	in
  2514 		case typeof t of
  2515 		  SOME (Type (s, Ts)) =>
  2516 			(case DatatypePackage.datatype_info thy s of
  2517 			  SOME info =>  (* inductive datatype *)
  2518 				let
  2519 					val (typs, _)           = model
  2520 					val index               = #index info
  2521 					val descr               = #descr info
  2522 					val (_, dtyps, constrs) = (the o AList.lookup (op =) descr) index
  2523 					val typ_assoc           = dtyps ~~ Ts
  2524 					(* sanity check: every element in 'dtyps' must be a 'DtTFree' *)
  2525 					val _ = (if Library.exists (fn d =>
  2526 							case d of DatatypeAux.DtTFree _ => false | _ => true) dtyps
  2527 						then
  2528 							raise REFUTE ("IDT_printer", "datatype argument (for type " ^ Sign.string_of_typ (sign_of thy) (Type (s, Ts)) ^ ") is not a variable")
  2529 						else
  2530 							())
  2531 					(* the index of the element in the datatype *)
  2532 					val element = (case intr of
  2533 						  Leaf xs => find_index (PropLogic.eval assignment) xs
  2534 						| Node _  => raise REFUTE ("IDT_printer", "interpretation is not a leaf"))
  2535 				in
  2536 					if element < 0 then
  2537 						SOME (Const ("arbitrary", Type (s, Ts)))
  2538 					else let
  2539 						(* takes a datatype constructor, and if for some arguments this constructor *)
  2540 						(* generates the datatype's element that is given by 'element', returns the *)
  2541 						(* constructor (as a term) as well as the indices of the arguments          *)
  2542 						(* string * DatatypeAux.dtyp list -> (Term.term * int list) option *)
  2543 						fun get_constr_args (cname, cargs) =
  2544 							let
  2545 								val cTerm      = Const (cname, (map (typ_of_dtyp descr typ_assoc) cargs) ---> Type (s, Ts))
  2546 								val (iC, _, _) = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} cTerm
  2547 								(* interpretation -> int list option *)
  2548 								fun get_args (Leaf xs) =
  2549 									if find_index_eq True xs = element then
  2550 										SOME []
  2551 									else
  2552 										NONE
  2553 								  | get_args (Node xs) =
  2554 									let
  2555 										(* interpretation * int -> int list option *)
  2556 										fun search ([], _) =
  2557 											NONE
  2558 										  | search (x::xs, n) =
  2559 											(case get_args x of
  2560 											  SOME result => SOME (n::result)
  2561 											| NONE        => search (xs, n+1))
  2562 									in
  2563 										search (xs, 0)
  2564 									end
  2565 							in
  2566 								Option.map (fn args => (cTerm, cargs, args)) (get_args iC)
  2567 							end
  2568 						(* Term.term * DatatypeAux.dtyp list * int list *)
  2569 						val (cTerm, cargs, args) = (case get_first get_constr_args constrs of
  2570 							  SOME x => x
  2571 							| NONE   => raise REFUTE ("IDT_printer", "no matching constructor found for element " ^ string_of_int element))
  2572 						val argsTerms = map (fn (d, n) =>
  2573 							let
  2574 								val dT        = typ_of_dtyp descr typ_assoc d
  2575 								val (i, _, _) = interpret thy (typs, []) {maxvars=0, def_eq=false, next_idx=1, bounds=[], wellformed=True} (Free ("dummy", dT))
  2576 								val consts    = make_constants i  (* we only need the n-th element of this *)
  2577 									(* list, so there might be a more efficient implementation that does    *)
  2578 									(* not generate all constants                                           *)
  2579 							in
  2580 								print thy (typs, []) (Free ("dummy", dT)) (List.nth (consts, n)) assignment
  2581 							end) (cargs ~~ args)
  2582 					in
  2583 						SOME (Library.foldl op$ (cTerm, argsTerms))
  2584 					end
  2585 				end
  2586 			| NONE =>  (* not an inductive datatype *)
  2587 				NONE)
  2588 		| _ =>  (* a (free or schematic) type variable *)
  2589 			NONE
  2590 	end;
  2591 
  2592 
  2593 (* ------------------------------------------------------------------------- *)
  2594 (* use 'setup Refute.setup' in an Isabelle theory to initialize the 'Refute' *)
  2595 (* structure                                                                 *)
  2596 (* ------------------------------------------------------------------------- *)
  2597 
  2598 (* ------------------------------------------------------------------------- *)
  2599 (* Note: the interpreters and printers are used in reverse order; however,   *)
  2600 (*       an interpreter that can handle non-atomic terms ends up being       *)
  2601 (*       applied before the 'stlc_interpreter' breaks the term apart into    *)
  2602 (*       subterms that are then passed to other interpreters!                *)
  2603 (* ------------------------------------------------------------------------- *)
  2604 
  2605 	(* (theory -> theory) list *)
  2606 
  2607 	val setup =
  2608 		[RefuteData.init,
  2609 		 add_interpreter "stlc"    stlc_interpreter,
  2610 		 add_interpreter "Pure"    Pure_interpreter,
  2611 		 add_interpreter "HOLogic" HOLogic_interpreter,
  2612 		 add_interpreter "set"     set_interpreter,
  2613 		 add_interpreter "IDT"             IDT_interpreter,
  2614 		 add_interpreter "IDT_constructor" IDT_constructor_interpreter,
  2615 		 add_interpreter "IDT_recursion"   IDT_recursion_interpreter,
  2616 		 add_interpreter "Finite_Set.card"    Finite_Set_card_interpreter,
  2617 		 add_interpreter "Finite_Set.Finites" Finite_Set_Finites_interpreter,
  2618 		 add_interpreter "Nat.op <" Nat_less_interpreter,
  2619 		 add_interpreter "Nat.op +" Nat_plus_interpreter,
  2620 		 add_interpreter "Nat.op -" Nat_minus_interpreter,
  2621 		 add_interpreter "Nat.op *" Nat_mult_interpreter,
  2622 		 add_interpreter "List.op @" List_append_interpreter,
  2623 		 add_interpreter "Lfp.lfp" Lfp_lfp_interpreter,
  2624 		 add_interpreter "Gfp.gfp" Gfp_gfp_interpreter,
  2625 		 add_printer "stlc" stlc_printer,
  2626 		 add_printer "set"  set_printer,
  2627 		 add_printer "IDT"  IDT_printer];
  2628 
  2629 end