src/HOL/Tools/sat_solver.ML
changeset 16899 ee4d620bcc1c
parent 16270 4280d6bbc1bb
child 16911 20a139ca2f62
equal deleted inserted replaced
16898:543ee8fabe1a 16899:ee4d620bcc1c
    22 	val parse_std_result_file : Path.T -> string * string * string -> result
    22 	val parse_std_result_file : Path.T -> string * string * string -> result
    23 	val make_external_solver  : string -> (PropLogic.prop_formula -> unit) -> (unit -> result) -> solver
    23 	val make_external_solver  : string -> (PropLogic.prop_formula -> unit) -> (unit -> result) -> solver
    24 
    24 
    25 	val read_dimacs_cnf_file : Path.T -> PropLogic.prop_formula
    25 	val read_dimacs_cnf_file : Path.T -> PropLogic.prop_formula
    26 
    26 
    27 	(* generic interface *)
    27 	(* generic solver interface *)
    28 	val solvers       : (string * solver) list ref
    28 	val solvers       : (string * solver) list ref
    29 	val add_solver    : string * solver -> unit
    29 	val add_solver    : string * solver -> unit
    30 	val invoke_solver : string -> solver  (* exception Option *)
    30 	val invoke_solver : string -> solver  (* exception Option *)
    31 end;
    31 end;
    32 
    32 
   145 			  | sat_string_acc False acc =
   145 			  | sat_string_acc False acc =
   146 				"+()" :: acc
   146 				"+()" :: acc
   147 			  | sat_string_acc (BoolVar i) acc =
   147 			  | sat_string_acc (BoolVar i) acc =
   148 				(assert (i>=1) "formula contains a variable index less than 1";
   148 				(assert (i>=1) "formula contains a variable index less than 1";
   149 				string_of_int i :: acc)
   149 				string_of_int i :: acc)
       
   150 			  | sat_string_acc (Not (BoolVar i)) acc =
       
   151 				"-" :: sat_string_acc (BoolVar i) acc
   150 			  | sat_string_acc (Not fm) acc =
   152 			  | sat_string_acc (Not fm) acc =
   151 				"-(" :: sat_string_acc fm (")" :: acc)
   153 				"-(" :: sat_string_acc fm (")" :: acc)
   152 			  | sat_string_acc (Or (fm1,fm2)) acc =
   154 			  | sat_string_acc (Or (fm1,fm2)) acc =
   153 				"+(" :: sat_string_acc fm1 (" " :: sat_string_acc fm2 (")" :: acc))
   155 				"+(" :: sat_string_acc_or fm1 (" " :: sat_string_acc_or fm2 (")" :: acc))
   154 			  | sat_string_acc (And (fm1,fm2)) acc =
   156 			  | sat_string_acc (And (fm1,fm2)) acc =
   155 				"*(" :: sat_string_acc fm1 (" " :: sat_string_acc fm2 (")" :: acc))
   157 				"*(" :: sat_string_acc_and fm1 (" " :: sat_string_acc_and fm2 (")" :: acc))
       
   158 			(* optimization to make use of n-ary disjunction/conjunction *)
       
   159 			(* prop_formula -> string list -> string list *)
       
   160 			and sat_string_acc_or (Or (fm1,fm2)) acc =
       
   161 				sat_string_acc_or fm1 (" " :: sat_string_acc_or fm2 acc)
       
   162 			  | sat_string_acc_or fm acc =
       
   163 				sat_string_acc fm acc
       
   164 			(* prop_formula -> string list -> string list *)
       
   165 			and sat_string_acc_and (And (fm1,fm2)) acc =
       
   166 				sat_string_acc_and fm1 (" " :: sat_string_acc_and fm2 acc)
       
   167 			  | sat_string_acc_and fm acc =
       
   168 				sat_string_acc fm acc
   156 		in
   169 		in
   157 			concat (sat_string_acc fm [])
   170 			concat (sat_string_acc fm [])
   158 		end
   171 		end
   159 	in
   172 	in
   160 		File.write path
   173 		File.write path
   162 				val number_of_vars = Int.max (maxidx fm, 1)
   175 				val number_of_vars = Int.max (maxidx fm, 1)
   163 			in
   176 			in
   164 				"c This file was generated by SatSolver.write_dimacs_sat_file\n" ^
   177 				"c This file was generated by SatSolver.write_dimacs_sat_file\n" ^
   165 				"c (c) Tjark Weber\n" ^
   178 				"c (c) Tjark Weber\n" ^
   166 				"p sat " ^ string_of_int number_of_vars ^ "\n" ^
   179 				"p sat " ^ string_of_int number_of_vars ^ "\n" ^
   167 				"(" ^ sat_string fm ^ ")\n"
   180 				(*"(" ^*) sat_string fm ^ "\n" (*")\n"*)
   168 			end)
   181 			end)
   169 	end;
   182 	end;
   170 
   183 
   171 (* ------------------------------------------------------------------------- *)
   184 (* ------------------------------------------------------------------------- *)
   172 (* parse_std_result_file: scans a SAT solver's output file for a satisfying  *)
   185 (* parse_std_result_file: scans a SAT solver's output file for a satisfying  *)
   519 		val _          = if (getenv "ZCHAFF_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
   532 		val _          = if (getenv "ZCHAFF_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
   520 		val _          = if (getenv "ZCHAFF_VERSION") <> "2004.5.13" andalso
   533 		val _          = if (getenv "ZCHAFF_VERSION") <> "2004.5.13" andalso
   521 		                    (getenv "ZCHAFF_VERSION") <> "2004.11.15" then raise SatSolver.NOT_CONFIGURED else ()
   534 		                    (getenv "ZCHAFF_VERSION") <> "2004.11.15" then raise SatSolver.NOT_CONFIGURED else ()
   522 			(* both versions of zChaff appear to have the same interface, so we do *)
   535 			(* both versions of zChaff appear to have the same interface, so we do *)
   523 			(* not actually need to distinguish between them in the following code *)
   536 			(* not actually need to distinguish between them in the following code *)
       
   537 		val satpath    = File.tmp_path (Path.unpack "isabelle.sat")
   524 		val inpath     = File.tmp_path (Path.unpack "isabelle.cnf")
   538 		val inpath     = File.tmp_path (Path.unpack "isabelle.cnf")
   525 		val outpath    = File.tmp_path (Path.unpack "result")
   539 		val outpath    = File.tmp_path (Path.unpack "result")
   526 		val cmd        = (getenv "ZCHAFF_HOME") ^ "/zchaff " ^ (Path.pack inpath) ^ " > " ^ (Path.pack outpath)
   540 		val cmd        = (getenv "ZCHAFF_HOME") ^ "/zchaff " ^ (Path.pack inpath) ^ " > " ^ (Path.pack outpath)
   527 		fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm)
   541 		fun writefn fm = (SatSolver.write_dimacs_sat_file satpath fm; SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm))
   528 		fun readfn ()  = SatSolver.parse_std_result_file outpath ("Instance Satisfiable", "", "Instance Unsatisfiable")
   542 		fun readfn ()  = SatSolver.parse_std_result_file outpath ("Instance Satisfiable", "", "Instance Unsatisfiable")
   529 		val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.pack inpath)) else ()
   543 		val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.pack inpath)) else ()
   530 		val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.pack outpath)) else ()
   544 		val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.pack outpath)) else ()
   531 		val result     = SatSolver.make_external_solver cmd writefn readfn fm
   545 		val result     = SatSolver.make_external_solver cmd writefn readfn fm
   532 		val _          = try File.rm inpath
   546 		val _          = try File.rm inpath