src/HOL/Tools/sat_solver.ML
author blanchet
Tue, 24 Feb 2009 16:12:27 +0100
changeset 30237 e6f76bf0e067
parent 29872 14e208d607af
child 30240 5b25fee0362c
permissions -rw-r--r--
Eliminated ZCHAFF_VERSION configuration variable, since zChaff's output format is identical in all versions since March 2003 (at least), and also because it forces users who want to use the latest versions to lie about the version number. I also made the BERKMIN_EXE variable optional, defaulting to BerkMin561 (a reasonable name with no platform encoded in it). These changes have no inpacts on already working Isabelle installations.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     1
(*  Title:      HOL/Tools/sat_solver.ML
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     2
    ID:         $Id$
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     3
    Author:     Tjark Weber
21267
5294ecae6708 interpreters for fst and snd added
webertj
parents: 20463
diff changeset
     4
    Copyright   2004-2006
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     5
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     6
Interface to external SAT solvers, and (simple) built-in SAT solvers.
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     7
*)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     8
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     9
signature SAT_SOLVER =
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    10
sig
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    11
  exception NOT_CONFIGURED
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    12
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    13
  type assignment = int -> bool option
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    14
  type proof      = int list Inttab.table * int
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    15
  datatype result = SATISFIABLE of assignment
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    16
                  | UNSATISFIABLE of proof option
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    17
                  | UNKNOWN
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    18
  type solver     = PropLogic.prop_formula -> result
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    19
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    20
  (* auxiliary functions to create external SAT solvers *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    21
  val write_dimacs_cnf_file : Path.T -> PropLogic.prop_formula -> unit
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    22
  val write_dimacs_sat_file : Path.T -> PropLogic.prop_formula -> unit
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    23
  val read_std_result_file  : Path.T -> string * string * string -> result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    24
  val make_external_solver  : string -> (PropLogic.prop_formula -> unit) -> (unit -> result) -> solver
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    25
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    26
  val read_dimacs_cnf_file : Path.T -> PropLogic.prop_formula
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
    27
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    28
  (* generic solver interface *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    29
  val solvers       : (string * solver) list ref
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    30
  val add_solver    : string * solver -> unit
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    31
  val invoke_solver : string -> solver  (* exception Option *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    32
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    33
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    34
structure SatSolver : SAT_SOLVER =
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    35
struct
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    36
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    37
  open PropLogic;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    38
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    39
(* ------------------------------------------------------------------------- *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    40
(* should be raised by an external SAT solver to indicate that the solver is *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    41
(* not configured properly                                                   *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    42
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    43
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    44
  exception NOT_CONFIGURED;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    45
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    46
(* ------------------------------------------------------------------------- *)
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15332
diff changeset
    47
(* type of partial (satisfying) assignments: 'a i = NONE' means that 'a' is  *)
19190
7c311c513bae fixed a typo in a comment
webertj
parents: 18678
diff changeset
    48
(*      a satisfying assignment regardless of the value of variable 'i'      *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    49
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    50
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    51
  type assignment = int -> bool option;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    52
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    53
(* ------------------------------------------------------------------------- *)
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    54
(* a proof of unsatisfiability, to be interpreted as follows: each integer   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    55
(*      is a clause ID, each list 'xs' stored under the key 'x' in the table *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    56
(*      contains the IDs of clauses that must be resolved (in the given      *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    57
(*      order) to obtain the new clause 'x'.  Each list 'xs' must be         *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    58
(*      non-empty, and the literal to be resolved upon must always be unique *)
17494
e70600834f44 using curried Inttab.update_new function now
webertj
parents: 17493
diff changeset
    59
(*      (e.g. "A | ~B" must not be resolved with "~A | B").  Circular        *)
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    60
(*      dependencies of clauses are not allowed.  (At least) one of the      *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    61
(*      clauses in the table must be the empty clause (i.e. contain no       *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    62
(*      literals); its ID is given by the second component of the proof.     *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    63
(*      The clauses of the original problem passed to the SAT solver have    *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    64
(*      consecutive IDs starting with 0.  Clause IDs must be non-negative,   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    65
(*      but do not need to be consecutive.                                   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    66
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    67
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    68
  type proof = int list Inttab.table * int;
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    69
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    70
(* ------------------------------------------------------------------------- *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    71
(* return type of SAT solvers: if the result is 'SATISFIABLE', a satisfying  *)
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    72
(*      assignment must be returned as well; if the result is                *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    73
(*      'UNSATISFIABLE', a proof of unsatisfiability may be returned         *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    74
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    75
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    76
  datatype result = SATISFIABLE of assignment
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    77
                  | UNSATISFIABLE of proof option
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    78
                  | UNKNOWN;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    79
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    80
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    81
(* type of SAT solvers: given a propositional formula, a satisfying          *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    82
(*      assignment may be returned                                           *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    83
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    84
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    85
  type solver = prop_formula -> result;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    86
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    87
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    88
(* write_dimacs_cnf_file: serializes a formula 'fm' of propositional logic   *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    89
(*      to a file in DIMACS CNF format (see "Satisfiability Suggested        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    90
(*      Format", May 8 1993, Section 2.1)                                    *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    91
(* Note: 'fm' must not contain a variable index less than 1.                 *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    92
(* Note: 'fm' must be given in CNF.                                          *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    93
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    94
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    95
  (* Path.T -> prop_formula -> unit *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    96
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    97
  fun write_dimacs_cnf_file path fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    98
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    99
    (* prop_formula -> prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   100
    fun cnf_True_False_elim True =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   101
      Or (BoolVar 1, Not (BoolVar 1))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   102
      | cnf_True_False_elim False =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   103
      And (BoolVar 1, Not (BoolVar 1))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   104
      | cnf_True_False_elim fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   105
      fm  (* since 'fm' is in CNF, either 'fm'='True'/'False', or 'fm' does not contain 'True'/'False' at all *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   106
    (* prop_formula -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   107
    fun cnf_number_of_clauses (And (fm1,fm2)) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   108
      (cnf_number_of_clauses fm1) + (cnf_number_of_clauses fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   109
      | cnf_number_of_clauses _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   110
      1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   111
    (* prop_formula -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   112
    fun cnf_string fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   113
    let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   114
      (* prop_formula -> string list -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   115
      fun cnf_string_acc True acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   116
        error "formula is not in CNF"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   117
        | cnf_string_acc False acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   118
        error "formula is not in CNF"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   119
        | cnf_string_acc (BoolVar i) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   120
        (i>=1 orelse error "formula contains a variable index less than 1";
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   121
        string_of_int i :: acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   122
        | cnf_string_acc (Not (BoolVar i)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   123
        "-" :: cnf_string_acc (BoolVar i) acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   124
        | cnf_string_acc (Not _) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   125
        error "formula is not in CNF"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   126
        | cnf_string_acc (Or (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   127
        cnf_string_acc fm1 (" " :: cnf_string_acc fm2 acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   128
        | cnf_string_acc (And (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   129
        cnf_string_acc fm1 (" 0\n" :: cnf_string_acc fm2 acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   130
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   131
      cnf_string_acc fm []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   132
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   133
    val fm'               = cnf_True_False_elim fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   134
    val number_of_vars    = maxidx fm'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   135
    val number_of_clauses = cnf_number_of_clauses fm'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   136
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   137
    File.write path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   138
      ("c This file was generated by SatSolver.write_dimacs_cnf_file\n" ^
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   139
       "p cnf " ^ string_of_int number_of_vars ^ " " ^ string_of_int number_of_clauses ^ "\n");
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   140
    File.append_list path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   141
      (cnf_string fm');
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   142
    File.append path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   143
      " 0\n"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   144
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   145
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   146
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   147
(* write_dimacs_sat_file: serializes a formula 'fm' of propositional logic   *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   148
(*      to a file in DIMACS SAT format (see "Satisfiability Suggested        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   149
(*      Format", May 8 1993, Section 2.2)                                    *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   150
(* Note: 'fm' must not contain a variable index less than 1.                 *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   151
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   152
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   153
  (* Path.T -> prop_formula -> unit *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   154
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   155
  fun write_dimacs_sat_file path fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   156
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   157
    (* prop_formula -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   158
    fun sat_string fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   159
    let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   160
      (* prop_formula -> string list -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   161
      fun sat_string_acc True acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   162
        "*()" :: acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   163
        | sat_string_acc False acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   164
        "+()" :: acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   165
        | sat_string_acc (BoolVar i) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   166
        (i>=1 orelse error "formula contains a variable index less than 1";
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   167
        string_of_int i :: acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   168
        | sat_string_acc (Not (BoolVar i)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   169
        "-" :: sat_string_acc (BoolVar i) acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   170
        | sat_string_acc (Not fm) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   171
        "-(" :: sat_string_acc fm (")" :: acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   172
        | sat_string_acc (Or (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   173
        "+(" :: sat_string_acc_or fm1 (" " :: sat_string_acc_or fm2 (")" :: acc))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   174
        | sat_string_acc (And (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   175
        "*(" :: sat_string_acc_and fm1 (" " :: sat_string_acc_and fm2 (")" :: acc))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   176
      (* optimization to make use of n-ary disjunction/conjunction *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   177
      (* prop_formula -> string list -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   178
      and sat_string_acc_or (Or (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   179
        sat_string_acc_or fm1 (" " :: sat_string_acc_or fm2 acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   180
        | sat_string_acc_or fm acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   181
        sat_string_acc fm acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   182
      (* prop_formula -> string list -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   183
      and sat_string_acc_and (And (fm1,fm2)) acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   184
        sat_string_acc_and fm1 (" " :: sat_string_acc_and fm2 acc)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   185
        | sat_string_acc_and fm acc =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   186
        sat_string_acc fm acc
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   187
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   188
      sat_string_acc fm []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   189
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   190
    val number_of_vars = Int.max (maxidx fm, 1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   191
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   192
    File.write path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   193
      ("c This file was generated by SatSolver.write_dimacs_sat_file\n" ^
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   194
       "p sat " ^ string_of_int number_of_vars ^ "\n" ^
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   195
       "(");
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   196
    File.append_list path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   197
      (sat_string fm);
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   198
    File.append path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   199
      ")\n"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   200
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   201
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   202
(* ------------------------------------------------------------------------- *)
17620
49568e5e0450 parse_std_result_file renamed to read_std_result_file
webertj
parents: 17581
diff changeset
   203
(* read_std_result_file: scans a SAT solver's output file for a satisfying   *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   204
(*      variable assignment.  Returns the assignment, or 'UNSATISFIABLE' if  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   205
(*      the file contains 'unsatisfiable', or 'UNKNOWN' if the file contains *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   206
(*      neither 'satisfiable' nor 'unsatisfiable'.  Empty lines are ignored. *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   207
(*      The assignment must be given in one or more lines immediately after  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   208
(*      the line that contains 'satisfiable'.  These lines must begin with   *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   209
(*      'assignment_prefix'.  Variables must be separated by " ".  Non-      *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   210
(*      integer strings are ignored.  If variable i is contained in the      *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   211
(*      assignment, then i is interpreted as 'true'.  If ~i is contained in  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   212
(*      the assignment, then i is interpreted as 'false'.  Otherwise the     *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   213
(*      value of i is taken to be unspecified.                               *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   214
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   215
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   216
  (* Path.T -> string * string * string -> result *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   217
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   218
  fun read_std_result_file path (satisfiable, assignment_prefix, unsatisfiable) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   219
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   220
    (* string -> int list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   221
    fun int_list_from_string s =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   222
      List.mapPartial Int.fromString (space_explode " " s)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   223
    (* int list -> assignment *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   224
    fun assignment_from_list [] i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   225
      NONE  (* the SAT solver didn't provide a value for this variable *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   226
      | assignment_from_list (x::xs) i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   227
      if x=i then (SOME true)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   228
      else if x=(~i) then (SOME false)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   229
      else assignment_from_list xs i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   230
    (* int list -> string list -> assignment *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   231
    fun parse_assignment xs [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   232
      assignment_from_list xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   233
      | parse_assignment xs (line::lines) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   234
      if String.isPrefix assignment_prefix line then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   235
        parse_assignment (xs @ int_list_from_string line) lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   236
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   237
        assignment_from_list xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   238
    (* string -> string -> bool *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   239
    fun is_substring needle haystack =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   240
    let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   241
      val length1 = String.size needle
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   242
      val length2 = String.size haystack
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   243
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   244
      if length2 < length1 then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   245
        false
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   246
      else if needle = String.substring (haystack, 0, length1) then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   247
        true
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   248
      else is_substring needle (String.substring (haystack, 1, length2-1))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   249
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   250
    (* string list -> result *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   251
    fun parse_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   252
      UNKNOWN
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   253
      | parse_lines (line::lines) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   254
      if is_substring unsatisfiable line then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   255
        UNSATISFIABLE NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   256
      else if is_substring satisfiable line then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   257
        SATISFIABLE (parse_assignment [] lines)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   258
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   259
        parse_lines lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   260
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   261
    (parse_lines o (List.filter (fn l => l <> "")) o split_lines o File.read) path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   262
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   263
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   264
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   265
(* make_external_solver: call 'writefn', execute 'cmd', call 'readfn'        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   266
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   267
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   268
  (* string -> (PropLogic.prop_formula -> unit) -> (unit -> result) -> solver *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   269
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   270
  fun make_external_solver cmd writefn readfn fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   271
    (writefn fm; system cmd; readfn ());
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   272
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   273
(* ------------------------------------------------------------------------- *)
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   274
(* read_dimacs_cnf_file: returns a propositional formula that corresponds to *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   275
(*      a SAT problem given in DIMACS CNF format                             *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   276
(* ------------------------------------------------------------------------- *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   277
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   278
  (* Path.T -> PropLogic.prop_formula *)
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   279
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   280
  fun read_dimacs_cnf_file path =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   281
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   282
    (* string list -> string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   283
    fun filter_preamble [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   284
      error "problem line not found in DIMACS CNF file"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   285
      | filter_preamble (line::lines) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   286
      if String.isPrefix "c " line orelse line = "c" then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   287
        (* ignore comments *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   288
        filter_preamble lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   289
      else if String.isPrefix "p " line then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   290
        (* ignore the problem line (which must be the last line of the preamble) *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   291
        (* Ignoring the problem line implies that if the file contains more clauses *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   292
        (* or variables than specified in its preamble, we will accept it anyway.   *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   293
        lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   294
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   295
        error "preamble in DIMACS CNF file contains a line that does not begin with \"c \" or \"p \""
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   296
    (* string -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   297
    fun int_from_string s =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   298
      case Int.fromString s of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   299
        SOME i => i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   300
      | NONE   => error ("token " ^ quote s ^ "in DIMACS CNF file is not a number")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   301
    (* int list -> int list list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   302
    fun clauses xs =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   303
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   304
        val (xs1, xs2) = take_prefix (fn i => i <> 0) xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   305
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   306
        case xs2 of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   307
          []      => [xs1]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   308
        | (0::[]) => [xs1]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   309
        | (0::tl) => xs1 :: clauses tl
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   310
        | _       => sys_error "this cannot happen"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   311
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   312
    (* int -> PropLogic.prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   313
    fun literal_from_int i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   314
      (i<>0 orelse error "variable index in DIMACS CNF file is 0";
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   315
      if i>0 then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   316
        PropLogic.BoolVar i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   317
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   318
        PropLogic.Not (PropLogic.BoolVar (~i)))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   319
    (* PropLogic.prop_formula list -> PropLogic.prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   320
    fun disjunction [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   321
      error "empty clause in DIMACS CNF file"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   322
      | disjunction (x::xs) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   323
      (case xs of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   324
        [] => x
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   325
      | _  => PropLogic.Or (x, disjunction xs))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   326
    (* PropLogic.prop_formula list -> PropLogic.prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   327
    fun conjunction [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   328
      error "no clause in DIMACS CNF file"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   329
      | conjunction (x::xs) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   330
      (case xs of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   331
        [] => x
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   332
      | _  => PropLogic.And (x, conjunction xs))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   333
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   334
    (conjunction
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   335
    o (map disjunction)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   336
    o (map (map literal_from_int))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   337
    o clauses
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   338
    o (map int_from_string)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   339
    o List.concat
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   340
    o (map (String.fields (fn c => c mem [#" ", #"\t", #"\n"])))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   341
    o filter_preamble
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   342
    o (List.filter (fn l => l <> ""))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   343
    o split_lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   344
    o File.read)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   345
      path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   346
  end;
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   347
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   348
(* ------------------------------------------------------------------------- *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   349
(* solvers: a (reference to a) table of all registered SAT solvers           *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   350
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   351
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   352
  val solvers = ref ([] : (string * solver) list);
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   353
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   354
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   355
(* add_solver: updates 'solvers' by adding a new solver                      *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   356
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   357
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   358
  (* string * solver -> unit *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   359
22220
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   360
    fun add_solver (name, new_solver) =
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   361
      let
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   362
        val the_solvers = !solvers;
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   363
        val _ = if AList.defined (op =) the_solvers name
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   364
          then warning ("SAT solver " ^ quote name ^ " was defined before")
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   365
          else ();
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   366
      in solvers := AList.update (op =) (name, new_solver) the_solvers end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   367
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   368
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   369
(* invoke_solver: returns the solver associated with the given 'name'        *)
15605
0c544d8b521f minor Library.option related modifications
webertj
parents: 15570
diff changeset
   370
(* Note: If no solver is associated with 'name', exception 'Option' will be  *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   371
(*       raised.                                                             *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   372
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   373
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   374
  (* string -> solver *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   375
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   376
  fun invoke_solver name =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   377
    (the o AList.lookup (op =) (!solvers)) name;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   378
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   379
end;  (* SatSolver *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   380
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   381
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   382
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   383
(* Predefined SAT solvers                                                    *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   384
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   385
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   386
(* ------------------------------------------------------------------------- *)
14753
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   387
(* Internal SAT solver, available as 'SatSolver.invoke_solver "enumerate"'   *)
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   388
(* -- simply enumerates assignments until a satisfying assignment is found   *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   389
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   390
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   391
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   392
  fun enum_solver fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   393
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   394
    (* int list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   395
    val indices = PropLogic.indices fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   396
    (* int list -> int list -> int list option *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   397
    (* binary increment: list 'xs' of current bits, list 'ys' of all bits (lower bits first) *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   398
    fun next_list _ ([]:int list) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   399
      NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   400
      | next_list [] (y::ys) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   401
      SOME [y]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   402
      | next_list (x::xs) (y::ys) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   403
      if x=y then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   404
        (* reset the bit, continue *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   405
        next_list xs ys
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   406
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   407
        (* set the lowest bit that wasn't set before, keep the higher bits *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   408
        SOME (y::x::xs)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   409
    (* int list -> int -> bool *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   410
    fun assignment_from_list xs i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   411
      i mem xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   412
    (* int list -> SatSolver.result *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   413
    fun solver_loop xs =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   414
      if PropLogic.eval (assignment_from_list xs) fm then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   415
        SatSolver.SATISFIABLE (SOME o (assignment_from_list xs))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   416
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   417
        (case next_list xs indices of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   418
          SOME xs' => solver_loop xs'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   419
        | NONE     => SatSolver.UNSATISFIABLE NONE)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   420
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   421
    (* start with the "first" assignment (all variables are interpreted as 'false') *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   422
    solver_loop []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   423
  end
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   424
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   425
  SatSolver.add_solver ("enumerate", enum_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   426
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   427
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   428
(* ------------------------------------------------------------------------- *)
14753
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   429
(* Internal SAT solver, available as 'SatSolver.invoke_solver "dpll"' -- a   *)
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   430
(* simple implementation of the DPLL algorithm (cf. L. Zhang, S. Malik: "The *)
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   431
(* Quest for Efficient Boolean Satisfiability Solvers", July 2002, Fig. 1).  *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   432
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   433
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   434
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   435
  local
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   436
    open PropLogic
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   437
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   438
    fun dpll_solver fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   439
    let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   440
      (* We could use 'PropLogic.defcnf fm' instead of 'PropLogic.nnf fm' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   441
      (* but that sometimes leads to worse performance due to the         *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   442
      (* introduction of additional variables.                            *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   443
      val fm' = PropLogic.nnf fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   444
      (* int list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   445
      val indices = PropLogic.indices fm'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   446
      (* int list -> int -> prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   447
      fun partial_var_eval []      i = BoolVar i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   448
        | partial_var_eval (x::xs) i = if x=i then True else if x=(~i) then False else partial_var_eval xs i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   449
      (* int list -> prop_formula -> prop_formula *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   450
      fun partial_eval xs True             = True
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   451
        | partial_eval xs False            = False
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   452
        | partial_eval xs (BoolVar i)      = partial_var_eval xs i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   453
        | partial_eval xs (Not fm)         = SNot (partial_eval xs fm)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   454
        | partial_eval xs (Or (fm1, fm2))  = SOr (partial_eval xs fm1, partial_eval xs fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   455
        | partial_eval xs (And (fm1, fm2)) = SAnd (partial_eval xs fm1, partial_eval xs fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   456
      (* prop_formula -> int list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   457
      fun forced_vars True              = []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   458
        | forced_vars False             = []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   459
        | forced_vars (BoolVar i)       = [i]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   460
        | forced_vars (Not (BoolVar i)) = [~i]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   461
        | forced_vars (Or (fm1, fm2))   = (forced_vars fm1) inter_int (forced_vars fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   462
        | forced_vars (And (fm1, fm2))  = (forced_vars fm1) union_int (forced_vars fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   463
        (* Above, i *and* ~i may be forced.  In this case the first occurrence takes   *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   464
        (* precedence, and the next partial evaluation of the formula returns 'False'. *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   465
        | forced_vars _                 = error "formula is not in negation normal form"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   466
      (* int list -> prop_formula -> (int list * prop_formula) *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   467
      fun eval_and_force xs fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   468
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   469
        val fm' = partial_eval xs fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   470
        val xs' = forced_vars fm'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   471
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   472
        if null xs' then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   473
          (xs, fm')
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   474
        else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   475
          eval_and_force (xs@xs') fm'  (* xs and xs' should be distinct, so '@' here should have *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   476
                                       (* the same effect as 'union_int'                         *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   477
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   478
      (* int list -> int option *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   479
      fun fresh_var xs =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   480
        Library.find_first (fn i => not (i mem_int xs) andalso not ((~i) mem_int xs)) indices
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   481
      (* int list -> prop_formula -> int list option *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   482
      (* partial assignment 'xs' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   483
      fun dpll xs fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   484
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   485
        val (xs', fm') = eval_and_force xs fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   486
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   487
        case fm' of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   488
          True  => SOME xs'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   489
        | False => NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   490
        | _     =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   491
          let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   492
            val x = valOf (fresh_var xs')  (* a fresh variable must exist since 'fm' did not evaluate to 'True'/'False' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   493
          in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   494
            case dpll (x::xs') fm' of  (* passing fm' rather than fm should save some simplification work *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   495
              SOME xs'' => SOME xs''
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   496
            | NONE      => dpll ((~x)::xs') fm'  (* now try interpreting 'x' as 'False' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   497
          end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   498
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   499
      (* int list -> assignment *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   500
      fun assignment_from_list [] i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   501
        NONE  (* the DPLL procedure didn't provide a value for this variable *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   502
        | assignment_from_list (x::xs) i =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   503
        if x=i then (SOME true)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   504
        else if x=(~i) then (SOME false)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   505
        else assignment_from_list xs i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   506
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   507
      (* initially, no variable is interpreted yet *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   508
      case dpll [] fm' of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   509
        SOME assignment => SatSolver.SATISFIABLE (assignment_from_list assignment)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   510
      | NONE            => SatSolver.UNSATISFIABLE NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   511
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   512
  end  (* local *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   513
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   514
  SatSolver.add_solver ("dpll", dpll_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   515
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   516
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   517
(* ------------------------------------------------------------------------- *)
14753
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   518
(* Internal SAT solver, available as 'SatSolver.invoke_solver "auto"': uses  *)
17577
e87bf1d8f17a zchaff_with_proofs does not delete zChaff\s resolve_trace file anymore
webertj
parents: 17541
diff changeset
   519
(* the last installed solver (other than "auto" itself) that does not raise  *)
15299
576fd0b65ed8 solver auto now returns the result of the first solver that does not raise NOT_CONFIGURED (which may be UNKNOWN)
webertj
parents: 15128
diff changeset
   520
(* 'NOT_CONFIGURED'.  (However, the solver may return 'UNKNOWN'.)            *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   521
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   522
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   523
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   524
  fun auto_solver fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   525
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   526
    fun loop [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   527
      SatSolver.UNKNOWN
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   528
      | loop ((name, solver)::solvers) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   529
      if name="auto" then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   530
        (* do not call solver "auto" from within "auto" *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   531
        loop solvers
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   532
      else (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   533
        (if name="dpll" orelse name="enumerate" then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   534
          warning ("Using SAT solver " ^ quote name ^ "; for better performance, consider using an external solver.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   535
        else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   536
          tracing ("Using SAT solver " ^ quote name ^ "."));
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   537
        (* apply 'solver' to 'fm' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   538
        solver fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   539
          handle SatSolver.NOT_CONFIGURED => loop solvers
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   540
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   541
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   542
    loop (!SatSolver.solvers)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   543
  end
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   544
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   545
  SatSolver.add_solver ("auto", auto_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   546
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   547
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   548
(* ------------------------------------------------------------------------- *)
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   549
(* MiniSat 1.14                                                              *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   550
(* (http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/)            *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   551
(* ------------------------------------------------------------------------- *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   552
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   553
(* ------------------------------------------------------------------------- *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   554
(* "minisat_with_proofs" requires a modified version of MiniSat 1.14 by John *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   555
(* Matthews, which can output ASCII proof traces.  Replaying binary proof    *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   556
(* traces generated by MiniSat-p_v1.14 has _not_ been implemented.           *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   557
(* ------------------------------------------------------------------------- *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   558
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   559
(* add "minisat_with_proofs" _before_ "minisat" to the available solvers, so *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   560
(* that the latter is preferred by the "auto" solver                         *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   561
20152
b6373fe199e1 MiniSat proof trace format changed; MiniSat is now expected to produce a proof also for "trivial" problems
webertj
parents: 20137
diff changeset
   562
(* There is a complication that is dealt with in the code below: MiniSat     *)
b6373fe199e1 MiniSat proof trace format changed; MiniSat is now expected to produce a proof also for "trivial" problems
webertj
parents: 20137
diff changeset
   563
(* introduces IDs for original clauses in the proof trace.  It does not (in  *)
b6373fe199e1 MiniSat proof trace format changed; MiniSat is now expected to produce a proof also for "trivial" problems
webertj
parents: 20137
diff changeset
   564
(* general) follow the convention that the original clauses are numbered     *)
b6373fe199e1 MiniSat proof trace format changed; MiniSat is now expected to produce a proof also for "trivial" problems
webertj
parents: 20137
diff changeset
   565
(* from 0 to n-1 (where n is the number of clauses in the formula).          *)
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   566
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   567
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   568
  exception INVALID_PROOF of string
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   569
  fun minisat_with_proofs fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   570
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   571
    val _          = if (getenv "MINISAT_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
29872
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   572
    val serial_str = serial_string ()
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   573
    val inpath     = File.tmp_path (Path.explode ("isabelle" ^ serial_str ^ ".cnf"))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   574
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   575
    val proofpath  = File.tmp_path (Path.explode ("result" ^ serial_str ^ ".prf"))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   576
    val cmd        = (getenv "MINISAT_HOME") ^ "/minisat " ^ (Path.implode inpath) ^ " -r " ^ (Path.implode outpath) ^ " -t " ^ (Path.implode proofpath) ^ "> /dev/null"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   577
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   578
    fun readfn ()  = SatSolver.read_std_result_file outpath ("SAT", "", "UNSAT")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   579
    val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.implode inpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   580
    val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.implode outpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   581
    val cnf        = PropLogic.defcnf fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   582
    val result     = SatSolver.make_external_solver cmd writefn readfn cnf
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   583
    val _          = try File.rm inpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   584
    val _          = try File.rm outpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   585
  in  case result of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   586
    SatSolver.UNSATISFIABLE NONE =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   587
    (let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   588
      (* string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   589
      val proof_lines = (split_lines o File.read) proofpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   590
        handle IO.Io _ => raise INVALID_PROOF "Could not read file \"result.prf\""
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   591
      (* representation of clauses as ordered lists of literals (with duplicates removed) *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   592
      (* prop_formula -> int list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   593
      fun clause_to_lit_list (PropLogic.Or (fm1, fm2)) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   594
        OrdList.union int_ord (clause_to_lit_list fm1) (clause_to_lit_list fm2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   595
        | clause_to_lit_list (PropLogic.BoolVar i) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   596
        [i]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   597
        | clause_to_lit_list (PropLogic.Not (PropLogic.BoolVar i)) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   598
        [~i]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   599
        | clause_to_lit_list _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   600
        raise INVALID_PROOF "Error: invalid clause in CNF formula."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   601
      (* prop_formula -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   602
      fun cnf_number_of_clauses (PropLogic.And (fm1, fm2)) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   603
        cnf_number_of_clauses fm1 + cnf_number_of_clauses fm2
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   604
        | cnf_number_of_clauses _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   605
        1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   606
      val number_of_clauses = cnf_number_of_clauses cnf
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   607
      (* int list array *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   608
      val clauses = Array.array (number_of_clauses, [])
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   609
      (* initialize the 'clauses' array *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   610
      (* prop_formula * int -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   611
      fun init_array (PropLogic.And (fm1, fm2), n) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   612
        init_array (fm2, init_array (fm1, n))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   613
        | init_array (fm, n) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   614
        (Array.update (clauses, n, clause_to_lit_list fm); n+1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   615
      val _ = init_array (cnf, 0)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   616
      (* optimization for the common case where MiniSat "R"s clauses in their *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   617
      (* original order:                                                      *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   618
      val last_ref_clause = ref (number_of_clauses - 1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   619
      (* search the 'clauses' array for the given list of literals 'lits', *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   620
      (* starting at index '!last_ref_clause + 1'                          *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   621
      (* int list -> int option *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   622
      fun original_clause_id lits =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   623
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   624
        fun original_clause_id_from index =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   625
          if index = number_of_clauses then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   626
            (* search from beginning again *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   627
            original_clause_id_from 0
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   628
          (* both 'lits' and the list of literals used in 'clauses' are sorted, so *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   629
          (* testing for equality should suffice -- barring duplicate literals     *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   630
          else if Array.sub (clauses, index) = lits then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   631
            (* success *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   632
            last_ref_clause := index;
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   633
            SOME index
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   634
          ) else if index = !last_ref_clause then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   635
            (* failure *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   636
            NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   637
          else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   638
            (* continue search *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   639
            original_clause_id_from (index + 1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   640
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   641
        original_clause_id_from (!last_ref_clause + 1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   642
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   643
      (* string -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   644
      fun int_from_string s = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   645
        case Int.fromString s of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   646
          SOME i => i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   647
        | NONE   => raise INVALID_PROOF ("File format error: number expected (" ^ quote s ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   648
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   649
      (* parse the proof file *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   650
      val clause_table  = ref (Inttab.empty : int list Inttab.table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   651
      val empty_id      = ref ~1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   652
      (* contains a mapping from clause IDs as used by MiniSat to clause IDs in *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   653
      (* our proof format, where original clauses are numbered starting from 0  *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   654
      val clause_id_map = ref (Inttab.empty : int Inttab.table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   655
      fun sat_to_proof id = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   656
        case Inttab.lookup (!clause_id_map) id of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   657
          SOME id' => id'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   658
        | NONE     => raise INVALID_PROOF ("Clause ID " ^ Int.toString id ^ " used, but not defined.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   659
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   660
      val next_id = ref (number_of_clauses - 1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   661
      (* string list -> unit *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   662
      fun process_tokens [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   663
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   664
        | process_tokens (tok::toks) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   665
        if tok="R" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   666
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   667
            id::sep::lits =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   668
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   669
              val _        = if !empty_id = ~1 then () else raise INVALID_PROOF "File format error: \"R\" disallowed after \"X\"."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   670
              val cid      = int_from_string id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   671
              val _        = if sep = "<=" then () else raise INVALID_PROOF ("File format error: \"<=\" expected (" ^ quote sep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   672
              val ls       = sort int_ord (map int_from_string lits)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   673
              val proof_id = case original_clause_id ls of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   674
                               SOME orig_id => orig_id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   675
                             | NONE         => raise INVALID_PROOF ("Original clause (new ID is " ^ id ^ ") not found.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   676
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   677
              (* extend the mapping of clause IDs with this newly defined ID *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   678
              clause_id_map := Inttab.update_new (cid, proof_id) (!clause_id_map)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   679
                handle Inttab.DUP _ => raise INVALID_PROOF ("File format error: clause " ^ id ^ " defined more than once (in \"R\").")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   680
              (* the proof itself doesn't change *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   681
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   682
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   683
            raise INVALID_PROOF "File format error: \"R\" followed by an insufficient number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   684
        ) else if tok="C" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   685
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   686
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   687
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   688
              val _        = if !empty_id = ~1 then () else raise INVALID_PROOF "File format error: \"C\" disallowed after \"X\"."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   689
              val cid      = int_from_string id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   690
              val _        = if sep = "<=" then () else raise INVALID_PROOF ("File format error: \"<=\" expected (" ^ quote sep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   691
              (* ignore the pivot literals in MiniSat's trace *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   692
              fun unevens []             = raise INVALID_PROOF "File format error: \"C\" followed by an even number of IDs."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   693
                | unevens (x :: [])      = x :: []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   694
                | unevens (x :: _ :: xs) = x :: unevens xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   695
              val rs       = (map sat_to_proof o unevens o map int_from_string) ids
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   696
              (* extend the mapping of clause IDs with this newly defined ID *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   697
              val proof_id = inc next_id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   698
              val _        = clause_id_map := Inttab.update_new (cid, proof_id) (!clause_id_map)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   699
                               handle Inttab.DUP _ => raise INVALID_PROOF ("File format error: clause " ^ id ^ " defined more than once (in \"C\").")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   700
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   701
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   702
              clause_table := Inttab.update_new (proof_id, rs) (!clause_table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   703
                handle Inttab.DUP _ => raise INVALID_PROOF ("Error: internal ID for clause " ^ id ^ " already used.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   704
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   705
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   706
            raise INVALID_PROOF "File format error: \"C\" followed by an insufficient number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   707
        ) else if tok="D" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   708
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   709
            [id] =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   710
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   711
              val _ = if !empty_id = ~1 then () else raise INVALID_PROOF "File format error: \"D\" disallowed after \"X\"."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   712
              val _ = sat_to_proof (int_from_string id)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   713
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   714
              (* simply ignore "D" *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   715
              ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   716
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   717
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   718
            raise INVALID_PROOF "File format error: \"D\" followed by an illegal number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   719
        ) else if tok="X" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   720
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   721
            [id1, id2] =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   722
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   723
              val _            = if !empty_id = ~1 then () else raise INVALID_PROOF "File format error: more than one end-of-proof statement."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   724
              val _            = sat_to_proof (int_from_string id1)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   725
              val new_empty_id = sat_to_proof (int_from_string id2)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   726
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   727
              (* update conflict id *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   728
              empty_id := new_empty_id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   729
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   730
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   731
            raise INVALID_PROOF "File format error: \"X\" followed by an illegal number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   732
        ) else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   733
          raise INVALID_PROOF ("File format error: unknown token " ^ quote tok ^ " encountered.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   734
      (* string list -> unit *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   735
      fun process_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   736
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   737
        | process_lines (l::ls) = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   738
          process_tokens (String.tokens (fn c => c = #" " orelse c = #"\t") l);
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   739
          process_lines ls
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   740
        )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   741
      (* proof *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   742
      val _ = process_lines proof_lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   743
      val _ = if !empty_id <> ~1 then () else raise INVALID_PROOF "File format error: no conflicting clause specified."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   744
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   745
      SatSolver.UNSATISFIABLE (SOME (!clause_table, !empty_id))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   746
    end handle INVALID_PROOF reason => (warning reason; SatSolver.UNSATISFIABLE NONE))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   747
  | result =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   748
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   749
  end
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   750
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   751
  SatSolver.add_solver ("minisat_with_proofs", minisat_with_proofs)
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   752
end;
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   753
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   754
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   755
  fun minisat fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   756
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   757
    val _          = if (getenv "MINISAT_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
29872
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   758
    val serial_str = serial_string ()
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   759
    val inpath     = File.tmp_path (Path.explode ("isabelle" ^ serial_str ^ ".cnf"))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   760
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   761
    val cmd        = (getenv "MINISAT_HOME") ^ "/minisat " ^ (Path.implode inpath) ^ " -r " ^ (Path.implode outpath) ^ " > /dev/null"
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   762
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   763
    fun readfn ()  = SatSolver.read_std_result_file outpath ("SAT", "", "UNSAT")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   764
    val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.implode inpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   765
    val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.implode outpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   766
    val result     = SatSolver.make_external_solver cmd writefn readfn fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   767
    val _          = try File.rm inpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   768
    val _          = try File.rm outpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   769
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   770
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   771
  end
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   772
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   773
  SatSolver.add_solver ("minisat", minisat)
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   774
end;
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   775
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   776
(* ------------------------------------------------------------------------- *)
15332
0dc05858a862 added ZCHAFF_VERSION
webertj
parents: 15329
diff changeset
   777
(* zChaff (http://www.princeton.edu/~chaff/zchaff.html)                      *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   778
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   779
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   780
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   781
(* 'zchaff_with_proofs' applies the "zchaff" prover to a formula, and if     *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   782
(* zChaff finds that the formula is unsatisfiable, a proof of this is read   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   783
(* from a file "resolve_trace" that was generated by zChaff.  See the code   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   784
(* below for the expected format of the "resolve_trace" file.  Aside from    *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   785
(* some basic syntactic checks, no verification of the proof is performed.   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   786
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   787
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   788
(* add "zchaff_with_proofs" _before_ "zchaff" to the available solvers, so   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   789
(* that the latter is preferred by the "auto" solver                         *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   790
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   791
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   792
  exception INVALID_PROOF of string
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   793
  fun zchaff_with_proofs fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   794
  case SatSolver.invoke_solver "zchaff" fm of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   795
    SatSolver.UNSATISFIABLE NONE =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   796
    (let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   797
      (* string list *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   798
      val proof_lines = ((split_lines o File.read) (Path.explode "resolve_trace"))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   799
        handle IO.Io _ => raise INVALID_PROOF "Could not read file \"resolve_trace\""
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   800
      (* PropLogic.prop_formula -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   801
      fun cnf_number_of_clauses (PropLogic.And (fm1, fm2)) = cnf_number_of_clauses fm1 + cnf_number_of_clauses fm2
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   802
        | cnf_number_of_clauses _                          = 1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   803
      (* string -> int *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   804
      fun int_from_string s = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   805
        case Int.fromString s of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   806
          SOME i => i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   807
        | NONE   => raise INVALID_PROOF ("File format error: number expected (" ^ quote s ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   808
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   809
      (* parse the "resolve_trace" file *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   810
      val clause_offset = ref ~1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   811
      val clause_table  = ref (Inttab.empty : int list Inttab.table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   812
      val empty_id      = ref ~1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   813
      (* string list -> unit *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   814
      fun process_tokens [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   815
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   816
        | process_tokens (tok::toks) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   817
        if tok="CL:" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   818
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   819
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   820
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   821
              val _   = if !clause_offset = ~1 then () else raise INVALID_PROOF ("File format error: \"CL:\" disallowed after \"VAR:\".")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   822
              val _   = if !empty_id = ~1 then () else raise INVALID_PROOF ("File format error: \"CL:\" disallowed after \"CONF:\".")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   823
              val cid = int_from_string id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   824
              val _   = if sep = "<=" then () else raise INVALID_PROOF ("File format error: \"<=\" expected (" ^ quote sep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   825
              val rs  = map int_from_string ids
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   826
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   827
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   828
              clause_table := Inttab.update_new (cid, rs) (!clause_table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   829
                handle Inttab.DUP _ => raise INVALID_PROOF ("File format error: clause " ^ id ^ " defined more than once.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   830
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   831
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   832
            raise INVALID_PROOF "File format error: \"CL:\" followed by an insufficient number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   833
        ) else if tok="VAR:" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   834
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   835
            id::levsep::levid::valsep::valid::antesep::anteid::litsep::lits =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   836
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   837
              val _   = if !empty_id = ~1 then () else raise INVALID_PROOF ("File format error: \"VAR:\" disallowed after \"CONF:\".")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   838
              (* set 'clause_offset' to the largest used clause ID *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   839
              val _   = if !clause_offset = ~1 then clause_offset :=
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   840
                (case Inttab.max_key (!clause_table) of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   841
                  SOME id => id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   842
                | NONE    => cnf_number_of_clauses (PropLogic.defcnf fm) - 1  (* the first clause ID is 0, not 1 *))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   843
                else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   844
                  ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   845
              val vid = int_from_string id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   846
              val _   = if levsep = "L:" then () else raise INVALID_PROOF ("File format error: \"L:\" expected (" ^ quote levsep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   847
              val _   = int_from_string levid
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   848
              val _   = if valsep = "V:" then () else raise INVALID_PROOF ("File format error: \"V:\" expected (" ^ quote valsep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   849
              val _   = int_from_string valid
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   850
              val _   = if antesep = "A:" then () else raise INVALID_PROOF ("File format error: \"A:\" expected (" ^ quote antesep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   851
              val aid = int_from_string anteid
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   852
              val _   = if litsep = "Lits:" then () else raise INVALID_PROOF ("File format error: \"Lits:\" expected (" ^ quote litsep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   853
              val ls  = map int_from_string lits
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   854
              (* convert the data provided by zChaff to our resolution-style proof format *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   855
              (* each "VAR:" line defines a unit clause, the resolvents are implicitly    *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   856
              (* given by the literals in the antecedent clause                           *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   857
              (* we use the sum of '!clause_offset' and the variable ID as clause ID for the unit clause *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   858
              val cid = !clause_offset + vid
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   859
              (* the low bit of each literal gives its sign (positive/negative), therefore  *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   860
              (* we have to divide each literal by 2 to obtain the proper variable ID; then *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   861
              (* we add '!clause_offset' to obtain the ID of the corresponding unit clause  *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   862
              val vids = filter (not_equal vid) (map (fn l => l div 2) ls)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   863
              val rs   = aid :: map (fn v => !clause_offset + v) vids
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   864
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   865
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   866
              clause_table := Inttab.update_new (cid, rs) (!clause_table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   867
                handle Inttab.DUP _ => raise INVALID_PROOF ("File format error: clause " ^ string_of_int cid ^ " (derived from antecedent for variable " ^ id ^ ") already defined.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   868
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   869
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   870
            raise INVALID_PROOF "File format error: \"VAR:\" followed by an insufficient number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   871
        ) else if tok="CONF:" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   872
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   873
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   874
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   875
              val _   = if !empty_id = ~1 then () else raise INVALID_PROOF "File format error: more than one conflicting clause specified."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   876
              val cid = int_from_string id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   877
              val _   = if sep = "==" then () else raise INVALID_PROOF ("File format error: \"==\" expected (" ^ quote sep ^ " encountered).")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   878
              val ls  = map int_from_string ids
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   879
              (* the conflict clause must be resolved with the unit clauses *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   880
              (* for its literals to obtain the empty clause                *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   881
              val vids         = map (fn l => l div 2) ls
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   882
              val rs           = cid :: map (fn v => !clause_offset + v) vids
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   883
              val new_empty_id = getOpt (Inttab.max_key (!clause_table), !clause_offset) + 1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   884
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   885
              (* update clause table and conflict id *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   886
              clause_table := Inttab.update_new (new_empty_id, rs) (!clause_table)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   887
                handle Inttab.DUP _ => raise INVALID_PROOF ("File format error: clause " ^ string_of_int new_empty_id ^ " (empty clause derived from clause " ^ id ^ ") already defined.");
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   888
              empty_id     := new_empty_id
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   889
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   890
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   891
            raise INVALID_PROOF "File format error: \"CONF:\" followed by an insufficient number of tokens."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   892
        ) else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   893
          raise INVALID_PROOF ("File format error: unknown token " ^ quote tok ^ " encountered.")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   894
      (* string list -> unit *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   895
      fun process_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   896
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   897
        | process_lines (l::ls) = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   898
          process_tokens (String.tokens (fn c => c = #" " orelse c = #"\t") l);
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   899
          process_lines ls
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   900
        )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   901
      (* proof *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   902
      val _ = process_lines proof_lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   903
      val _ = if !empty_id <> ~1 then () else raise INVALID_PROOF "File format error: no conflicting clause specified."
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   904
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   905
      SatSolver.UNSATISFIABLE (SOME (!clause_table, !empty_id))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   906
    end handle INVALID_PROOF reason => (warning reason; SatSolver.UNSATISFIABLE NONE))
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   907
  | result =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   908
    result
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   909
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   910
  SatSolver.add_solver ("zchaff_with_proofs", zchaff_with_proofs)
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   911
end;
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   912
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   913
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   914
  fun zchaff fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   915
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   916
    val _          = if (getenv "ZCHAFF_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
29872
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   917
    val serial_str = serial_string ()
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   918
    val inpath     = File.tmp_path (Path.explode ("isabelle" ^ serial_str ^ ".cnf"))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   919
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   920
    val cmd        = (getenv "ZCHAFF_HOME") ^ "/zchaff " ^ (Path.implode inpath) ^ " > " ^ (Path.implode outpath)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   921
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   922
    fun readfn ()  = SatSolver.read_std_result_file outpath ("Instance Satisfiable", "", "Instance Unsatisfiable")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   923
    val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.implode inpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   924
    val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.implode outpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   925
    val result     = SatSolver.make_external_solver cmd writefn readfn fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   926
    val _          = try File.rm inpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   927
    val _          = try File.rm outpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   928
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   929
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   930
  end
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   931
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   932
  SatSolver.add_solver ("zchaff", zchaff)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   933
end;
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   934
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   935
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   936
(* BerkMin 561 (http://eigold.tripod.com/BerkMin.html)                       *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   937
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   938
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   939
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   940
  fun berkmin fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   941
  let
30237
e6f76bf0e067 Eliminated ZCHAFF_VERSION configuration variable, since zChaff's output format is identical in all versions since March 2003 (at least), and also because it forces users who want to use the latest versions to lie about the version number.
blanchet
parents: 29872
diff changeset
   942
    val _          = if (getenv "BERKMIN_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
29872
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   943
    val serial_str = serial_string ()
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   944
    val inpath     = File.tmp_path (Path.explode ("isabelle" ^ serial_str ^ ".cnf"))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   945
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
30237
e6f76bf0e067 Eliminated ZCHAFF_VERSION configuration variable, since zChaff's output format is identical in all versions since March 2003 (at least), and also because it forces users who want to use the latest versions to lie about the version number.
blanchet
parents: 29872
diff changeset
   946
    val exec       = getenv "BERKMIN_EXE"
e6f76bf0e067 Eliminated ZCHAFF_VERSION configuration variable, since zChaff's output format is identical in all versions since March 2003 (at least), and also because it forces users who want to use the latest versions to lie about the version number.
blanchet
parents: 29872
diff changeset
   947
    val cmd        = (getenv "BERKMIN_HOME") ^ "/" ^ (if exec = "" then "BerkMin561" else exec) ^ " " ^ (Path.implode inpath) ^ " > " ^ (Path.implode outpath)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   948
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   949
    fun readfn ()  = SatSolver.read_std_result_file outpath ("Satisfiable          !!", "solution =", "UNSATISFIABLE          !!")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   950
    val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.implode inpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   951
    val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.implode outpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   952
    val result     = SatSolver.make_external_solver cmd writefn readfn fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   953
    val _          = try File.rm inpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   954
    val _          = try File.rm outpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   955
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   956
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   957
  end
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   958
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   959
  SatSolver.add_solver ("berkmin", berkmin)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   960
end;
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   961
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   962
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   963
(* Jerusat 1.3 (http://www.cs.tau.ac.il/~ale1/)                              *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   964
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   966
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   967
  fun jerusat fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   968
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   969
    val _          = if (getenv "JERUSAT_HOME") = "" then raise SatSolver.NOT_CONFIGURED else ()
29872
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   970
    val serial_str = serial_string ()
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   971
    val inpath     = File.tmp_path (Path.explode ("isabelle" ^ serial_str ^ ".cnf"))
14e208d607af Added serial_string to SAT solver input and output files, to prevent multithreading chaos.
blanchet
parents: 22567
diff changeset
   972
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   973
    val cmd        = (getenv "JERUSAT_HOME") ^ "/Jerusat1.3 " ^ (Path.implode inpath) ^ " > " ^ (Path.implode outpath)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   974
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (PropLogic.defcnf fm)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   975
    fun readfn ()  = SatSolver.read_std_result_file outpath ("s SATISFIABLE", "v ", "s UNSATISFIABLE")
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   976
    val _          = if File.exists inpath then warning ("overwriting existing file " ^ quote (Path.implode inpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   977
    val _          = if File.exists outpath then warning ("overwriting existing file " ^ quote (Path.implode outpath)) else ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   978
    val result     = SatSolver.make_external_solver cmd writefn readfn fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   979
    val _          = try File.rm inpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   980
    val _          = try File.rm outpath
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   981
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   982
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   983
  end
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   984
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   985
  SatSolver.add_solver ("jerusat", jerusat)
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   986
end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   987
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   988
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   989
(* Add code for other SAT solvers below.                                     *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   990
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   991
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   992
(*
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   993
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   994
  fun mysolver fm = ...
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   995
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   996
  SatSolver.add_solver ("myname", (fn fm => if mysolver_is_configured then mysolver fm else raise SatSolver.NOT_CONFIGURED));  -- register the solver
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
   997
end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   998
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   999
-- the solver is now available as SatSolver.invoke_solver "myname"
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
  1000
*)