src/HOL/Tools/sat_solver.ML
author boehmes
Thu, 01 May 2014 22:56:59 +0200
changeset 56815 848d507584db
parent 56147 9589605bcf41
child 56845 691da43fbdd4
permissions -rw-r--r--
added internal proof-producing SAT solver
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
    Author:     Tjark Weber
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
     3
    Copyright   2004-2009
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     4
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
     5
Interface to external SAT solvers, and (simple) built-in SAT solvers.
51940
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
     6
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
     7
Relevant Isabelle environment settings:
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
     8
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
     9
  # MiniSat 1.14
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    10
  #MINISAT_HOME=/usr/local/bin
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    11
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    12
  # zChaff
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    13
  #ZCHAFF_HOME=/usr/local/bin
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    14
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    15
  # BerkMin561
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    16
  #BERKMIN_HOME=/usr/local/bin
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    17
  #BERKMIN_EXE=BerkMin561-linux
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    18
  #BERKMIN_EXE=BerkMin561-solaris
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    19
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    20
  # Jerusat 1.3
958d439b3013 decentralized historic settings;
wenzelm
parents: 43850
diff changeset
    21
  #JERUSAT_HOME=/usr/local/bin
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    22
*)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    23
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    24
signature SAT_SOLVER =
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    25
sig
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    26
  exception NOT_CONFIGURED
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
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
  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
    29
  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
    30
  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
    31
                  | UNSATISFIABLE of proof option
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    32
                  | UNKNOWN
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    33
  type solver     = Prop_Logic.prop_formula -> result
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    34
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    35
  (* auxiliary functions to create external SAT solvers *)
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    36
  val write_dimacs_cnf_file : Path.T -> Prop_Logic.prop_formula -> unit
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    37
  val write_dimacs_sat_file : Path.T -> Prop_Logic.prop_formula -> unit
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    38
  val read_std_result_file : Path.T -> string * string * string -> result
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    39
  val make_external_solver : string -> (Prop_Logic.prop_formula -> unit) ->
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    40
    (unit -> result) -> solver
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    41
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    42
  val read_dimacs_cnf_file : Path.T -> Prop_Logic.prop_formula
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
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
  (* generic solver interface *)
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
    45
  val get_solvers   : unit -> (string * solver) list
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    46
  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
    47
  val invoke_solver : string -> solver  (* exception Option *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    48
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    49
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    50
structure SatSolver : SAT_SOLVER =
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    51
struct
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    52
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
    53
  open Prop_Logic;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    54
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    55
(* ------------------------------------------------------------------------- *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    56
(* should be raised by an external SAT solver to indicate that the solver is *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    57
(* not configured properly                                                   *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    58
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    59
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    60
  exception NOT_CONFIGURED;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    61
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    62
(* ------------------------------------------------------------------------- *)
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15332
diff changeset
    63
(* 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
    64
(*      a satisfying assignment regardless of the value of variable 'i'      *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    65
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
    66
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    67
  type assignment = int -> bool option;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    68
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    69
(* ------------------------------------------------------------------------- *)
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    70
(* 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
    71
(*      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
    72
(*      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
    73
(*      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
    74
(*      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
    75
(*      (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
    76
(*      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
    77
(*      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
    78
(*      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
    79
(*      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
    80
(*      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
    81
(*      but do not need to be consecutive.                                   *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    82
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    83
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    84
  type proof = int list Inttab.table * int;
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    85
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
    86
(* ------------------------------------------------------------------------- *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    87
(* 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
    88
(*      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
    89
(*      'UNSATISFIABLE', a proof of unsatisfiability may be returned         *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    90
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    91
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    92
  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
    93
                  | UNSATISFIABLE of proof option
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
    94
                  | UNKNOWN;
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    95
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    96
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    97
(* type of SAT solvers: given a propositional formula, a satisfying          *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    98
(*      assignment may be returned                                           *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
    99
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   100
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   101
  type solver = prop_formula -> result;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   102
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   103
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   104
(* write_dimacs_cnf_file: serializes a formula 'fm' of propositional logic   *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   105
(*      to a file in DIMACS CNF format (see "Satisfiability Suggested        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   106
(*      Format", May 8 1993, Section 2.1)                                    *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   107
(* Note: 'fm' must not contain a variable index less than 1.                 *)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   108
(* Note: 'fm' must be given in CNF.                                          *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   109
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   110
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   111
  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
   112
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   113
    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
   114
      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
   115
      | 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
   116
      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
   117
      | cnf_True_False_elim fm =
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   118
      fm  (* since 'fm' is in CNF, either 'fm'='True'/'False',
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   119
             or 'fm' does not contain 'True'/'False' at all *)
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   120
    fun cnf_number_of_clauses (And (fm1, fm2)) =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   121
      (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
   122
      | cnf_number_of_clauses _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   123
      1
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   124
    fun write_cnf_file out =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   125
    let
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   126
      fun write_formula True =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   127
          error "formula is not in CNF"
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   128
        | write_formula False =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   129
          error "formula is not in CNF"
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   130
        | write_formula (BoolVar i) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   131
          (i>=1 orelse error "formula contains a variable index less than 1";
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   132
           TextIO.output (out, string_of_int i))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   133
        | write_formula (Not (BoolVar i)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   134
          (TextIO.output (out, "-");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   135
           write_formula (BoolVar i))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   136
        | write_formula (Not _) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   137
          error "formula is not in CNF"
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   138
        | write_formula (Or (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   139
          (write_formula fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   140
           TextIO.output (out, " ");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   141
           write_formula fm2)
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   142
        | write_formula (And (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   143
          (write_formula fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   144
           TextIO.output (out, " 0\n");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   145
           write_formula fm2)
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   146
      val fm'               = cnf_True_False_elim fm
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   147
      val number_of_vars    = maxidx fm'
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   148
      val number_of_clauses = cnf_number_of_clauses fm'
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   149
    in
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   150
      TextIO.output (out, "c This file was generated by SatSolver.write_dimacs_cnf_file\n");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   151
      TextIO.output (out, "p cnf " ^ string_of_int number_of_vars ^ " " ^
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   152
                            string_of_int number_of_clauses ^ "\n");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   153
      write_formula fm';
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   154
      TextIO.output (out, " 0\n")
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   155
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   156
  in
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   157
    File.open_output write_cnf_file path
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   158
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   159
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   160
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   161
(* write_dimacs_sat_file: serializes a formula 'fm' of propositional logic   *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   162
(*      to a file in DIMACS SAT format (see "Satisfiability Suggested        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   163
(*      Format", May 8 1993, Section 2.2)                                    *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   164
(* Note: 'fm' must not contain a variable index less than 1.                 *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   165
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   166
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   167
  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
   168
  let
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   169
    fun write_sat_file out =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   170
    let
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   171
      fun write_formula True =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   172
          TextIO.output (out, "*()")
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   173
        | write_formula False =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   174
          TextIO.output (out, "+()")
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   175
        | write_formula (BoolVar i) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   176
          (i>=1 orelse error "formula contains a variable index less than 1";
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   177
           TextIO.output (out, string_of_int i))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   178
        | write_formula (Not (BoolVar i)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   179
          (TextIO.output (out, "-");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   180
           write_formula (BoolVar i))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   181
        | write_formula (Not fm) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   182
          (TextIO.output (out, "-(");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   183
           write_formula fm;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   184
           TextIO.output (out, ")"))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   185
        | write_formula (Or (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   186
          (TextIO.output (out, "+(");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   187
           write_formula_or fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   188
           TextIO.output (out, " ");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   189
           write_formula_or fm2;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   190
           TextIO.output (out, ")"))
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   191
        | write_formula (And (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   192
          (TextIO.output (out, "*(");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   193
           write_formula_and fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   194
           TextIO.output (out, " ");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   195
           write_formula_and fm2;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   196
           TextIO.output (out, ")"))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   197
      (* optimization to make use of n-ary disjunction/conjunction *)
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   198
      and write_formula_or (Or (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   199
          (write_formula_or fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   200
           TextIO.output (out, " ");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   201
           write_formula_or fm2)
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   202
        | write_formula_or fm =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   203
          write_formula fm
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   204
      and write_formula_and (And (fm1, fm2)) =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   205
          (write_formula_and fm1;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   206
           TextIO.output (out, " ");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   207
           write_formula_and fm2)
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   208
        | write_formula_and fm =
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   209
          write_formula fm
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   210
      val number_of_vars = Int.max (maxidx fm, 1)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   211
    in
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   212
      TextIO.output (out, "c This file was generated by SatSolver.write_dimacs_sat_file\n");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   213
      TextIO.output (out, "p sat " ^ string_of_int number_of_vars ^ "\n");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   214
      TextIO.output (out, "(");
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   215
      write_formula fm;
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   216
      TextIO.output (out, ")\n")
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   217
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   218
  in
31219
034f23104635 write_dimacs_{sat,cnf}_file now write the DIMACS file on the fly, without building it in memory first
webertj
parents: 30275
diff changeset
   219
    File.open_output write_sat_file path
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   220
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   221
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   222
(* ------------------------------------------------------------------------- *)
17620
49568e5e0450 parse_std_result_file renamed to read_std_result_file
webertj
parents: 17581
diff changeset
   223
(* 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
   224
(*      variable assignment.  Returns the assignment, or 'UNSATISFIABLE' if  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   225
(*      the file contains 'unsatisfiable', or 'UNKNOWN' if the file contains *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   226
(*      neither 'satisfiable' nor 'unsatisfiable'.  Empty lines are ignored. *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   227
(*      The assignment must be given in one or more lines immediately after  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   228
(*      the line that contains 'satisfiable'.  These lines must begin with   *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   229
(*      'assignment_prefix'.  Variables must be separated by " ".  Non-      *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   230
(*      integer strings are ignored.  If variable i is contained in the      *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   231
(*      assignment, then i is interpreted as 'true'.  If ~i is contained in  *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   232
(*      the assignment, then i is interpreted as 'false'.  Otherwise the     *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
   233
(*      value of i is taken to be unspecified.                               *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   234
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   235
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   236
  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
   237
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   238
    fun int_list_from_string s =
32952
aeb1e44fbc19 replaced String.concat by implode;
wenzelm
parents: 32740
diff changeset
   239
      map_filter Int.fromString (space_explode " " s)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   240
    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
   241
      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
   242
      | 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
   243
      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
   244
      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
   245
      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
   246
    fun parse_assignment xs [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   247
      assignment_from_list xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   248
      | 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
   249
      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
   250
        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
   251
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   252
        assignment_from_list xs
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   253
    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
   254
    let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   255
      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
   256
      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
   257
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   258
      if length2 < length1 then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   259
        false
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   260
      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
   261
        true
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   262
      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
   263
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   264
    fun parse_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   265
      UNKNOWN
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   266
      | parse_lines (line::lines) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   267
      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
   268
        UNSATISFIABLE NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   269
      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
   270
        SATISFIABLE (parse_assignment [] lines)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   271
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   272
        parse_lines lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   273
  in
33317
b4534348b8fd standardized filter/filter_out;
wenzelm
parents: 33228
diff changeset
   274
    (parse_lines o filter (fn l => l <> "") o split_lines o File.read) path
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   275
  end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   276
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   277
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   278
(* make_external_solver: call 'writefn', execute 'cmd', call 'readfn'        *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   279
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   280
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   281
  fun make_external_solver cmd writefn readfn fm =
43850
7f2cbc713344 moved bash operations to Isabelle_System (cf. Scala version);
wenzelm
parents: 43701
diff changeset
   282
    (writefn fm; Isabelle_System.bash cmd; readfn ());
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   283
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   284
(* ------------------------------------------------------------------------- *)
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   285
(* read_dimacs_cnf_file: returns a propositional formula that corresponds to *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   286
(*      a SAT problem given in DIMACS CNF format                             *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   287
(* ------------------------------------------------------------------------- *)
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   288
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   289
  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
   290
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   291
    fun filter_preamble [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   292
      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
   293
      | filter_preamble (line::lines) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   294
      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
   295
        (* ignore comments *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   296
        filter_preamble lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   297
      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
   298
        (* 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
   299
        (* 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
   300
        (* 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
   301
        lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   302
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   303
        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
   304
    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
   305
      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
   306
        SOME i => i
33937
b5ca587d0885 read_dimacs_cnf_file can now read DIMACS files that contain successive
webertj
parents: 33576
diff changeset
   307
      | NONE   => error ("token " ^ quote s ^ " in DIMACS CNF file is not a number")
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   308
    fun clauses xs =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   309
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   310
        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
   311
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   312
        case xs2 of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   313
          []      => [xs1]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   314
        | (0::[]) => [xs1]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   315
        | (0::tl) => xs1 :: clauses tl
40314
b5ec88d9ac03 replaced ancient sys_error by raise Fail, assuming that the latter is not handled specifically by the environment;
wenzelm
parents: 39687
diff changeset
   316
        | _       => raise Fail "SatSolver.clauses"
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   317
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   318
    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
   319
      (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
   320
      if i>0 then
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   321
        Prop_Logic.BoolVar i
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   322
      else
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   323
        Prop_Logic.Not (Prop_Logic.BoolVar (~i)))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   324
    fun disjunction [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   325
      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
   326
      | disjunction (x::xs) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   327
      (case xs of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   328
        [] => x
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   329
      | _  => Prop_Logic.Or (x, disjunction xs))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   330
    fun conjunction [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   331
      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
   332
      | conjunction (x::xs) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   333
      (case xs of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   334
        [] => x
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   335
      | _  => Prop_Logic.And (x, conjunction xs))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   336
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   337
    (conjunction
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   338
    o (map disjunction)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   339
    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
   340
    o clauses
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   341
    o (map int_from_string)
36692
54b64d4ad524 farewell to old-style mem infixes -- type inference in situations with mem_int and mem_string should provide enough information to resolve the type of (op =)
haftmann
parents: 35011
diff changeset
   342
    o (maps (String.tokens (member (op =) [#" ", #"\t", #"\n"])))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   343
    o filter_preamble
33317
b4534348b8fd standardized filter/filter_out;
wenzelm
parents: 33228
diff changeset
   344
    o filter (fn l => l <> "")
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   345
    o split_lines
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   346
    o File.read)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   347
      path
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   348
  end;
15040
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   349
ed574b4f7e70 read_dimacs_cnf_file added
webertj
parents: 14999
diff changeset
   350
(* ------------------------------------------------------------------------- *)
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   351
(* solvers: a table of all registered SAT solvers                            *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   352
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   353
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   354
  val solvers = Synchronized.var "solvers" ([] : (string * solver) list);
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   355
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   356
  fun get_solvers () = Synchronized.value solvers;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   357
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   358
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   359
(* add_solver: updates 'solvers' by adding a new solver                      *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   360
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   361
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   362
  fun add_solver (name, new_solver) =
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   363
    Synchronized.change solvers (fn the_solvers =>
22220
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   364
      let
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   365
        val _ = if AList.defined (op =) the_solvers name
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   366
          then warning ("SAT solver " ^ quote name ^ " was defined before")
6dc8d0dca678 dropped Output.update_warn
haftmann
parents: 21858
diff changeset
   367
          else ();
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   368
      in AList.update (op =) (name, new_solver) the_solvers end);
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   369
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   370
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   371
(* invoke_solver: returns the solver associated with the given 'name'        *)
15605
0c544d8b521f minor Library.option related modifications
webertj
parents: 15570
diff changeset
   372
(* Note: If no solver is associated with 'name', exception 'Option' will be  *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   373
(*       raised.                                                             *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   374
(* ------------------------------------------------------------------------- *)
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 =
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   377
    the (AList.lookup (op =) (get_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
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   394
    val indices = Prop_Logic.indices fm
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   395
    (* 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
   396
    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
   397
      NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   398
      | next_list [] (y::ys) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   399
      SOME [y]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   400
      | 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
   401
      if x=y then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   402
        (* reset the bit, continue *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   403
        next_list xs ys
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   404
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   405
        (* 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
   406
        SOME (y::x::xs)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   407
    fun assignment_from_list xs i =
36692
54b64d4ad524 farewell to old-style mem infixes -- type inference in situations with mem_int and mem_string should provide enough information to resolve the type of (op =)
haftmann
parents: 35011
diff changeset
   408
      member (op =) xs i
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   409
    fun solver_loop xs =
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   410
      if Prop_Logic.eval (assignment_from_list xs) fm then
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   411
        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
   412
      else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   413
        (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
   414
          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
   415
        | NONE     => SatSolver.UNSATISFIABLE NONE)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   416
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   417
    (* 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
   418
    solver_loop []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   419
  end
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   420
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   421
  SatSolver.add_solver ("enumerate", enum_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   422
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   423
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   424
(* ------------------------------------------------------------------------- *)
14753
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   425
(* Internal SAT solver, available as 'SatSolver.invoke_solver "dpll"' -- a   *)
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   426
(* simple implementation of the DPLL algorithm (cf. L. Zhang, S. Malik: "The *)
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   427
(* Quest for Efficient Boolean Satisfiability Solvers", July 2002, Fig. 1).  *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   428
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   429
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   430
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   431
  local
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   432
    open Prop_Logic
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   433
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   434
    fun dpll_solver fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   435
    let
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   436
      (* We could use 'Prop_Logic.defcnf fm' instead of 'Prop_Logic.nnf fm' *)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   437
      (* 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
   438
      (* introduction of additional variables.                            *)
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   439
      val fm' = Prop_Logic.nnf fm
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   440
      val indices = Prop_Logic.indices fm'
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   441
      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
   442
        | 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
   443
      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
   444
        | 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
   445
        | 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
   446
        | 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
   447
        | 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
   448
        | 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
   449
      fun forced_vars True              = []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   450
        | forced_vars False             = []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   451
        | 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
   452
        | forced_vars (Not (BoolVar i)) = [~i]
33049
c38f02fdf35d curried inter as canonical list operation (beware of argument order)
haftmann
parents: 33039
diff changeset
   453
        | forced_vars (Or (fm1, fm2))   = inter (op =) (forced_vars fm1) (forced_vars fm2)
33042
ddf1f03a9ad9 curried union as canonical list operation
haftmann
parents: 33039
diff changeset
   454
        | forced_vars (And (fm1, fm2))  = union (op =) (forced_vars fm1) (forced_vars fm2)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   455
        (* 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
   456
        (* 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
   457
        | 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
   458
      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
   459
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   460
        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
   461
        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
   462
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   463
        if null xs' then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   464
          (xs, fm')
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   465
        else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   466
          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
   467
                                       (* 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
   468
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   469
      fun fresh_var xs =
36692
54b64d4ad524 farewell to old-style mem infixes -- type inference in situations with mem_int and mem_string should provide enough information to resolve the type of (op =)
haftmann
parents: 35011
diff changeset
   470
        find_first (fn i => not (member (op =) xs i) andalso not (member (op =) xs (~i))) indices
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   471
      (* partial assignment 'xs' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   472
      fun dpll xs fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   473
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   474
        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
   475
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   476
        case fm' of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   477
          True  => SOME xs'
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   478
        | False => NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   479
        | _     =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   480
          let
33035
15eab423e573 standardized basic operations on type option;
wenzelm
parents: 32952
diff changeset
   481
            val x = the (fresh_var xs')  (* a fresh variable must exist since 'fm' did not evaluate to 'True'/'False' *)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   482
          in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   483
            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
   484
              SOME xs'' => SOME xs''
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   485
            | 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
   486
          end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   487
      end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   488
      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
   489
        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
   490
        | 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
   491
        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
   492
        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
   493
        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
   494
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   495
      (* 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
   496
      case dpll [] fm' of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   497
        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
   498
      | NONE            => SatSolver.UNSATISFIABLE NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   499
    end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   500
  end  (* local *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   501
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   502
  SatSolver.add_solver ("dpll", dpll_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   503
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   504
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   505
(* ------------------------------------------------------------------------- *)
56815
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   506
(* Internal SAT solver, available as 'SatSolver.invoke_solver "dpll_p"' --   *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   507
(* a simple, slightly more efficient implementation of the DPLL algorithm    *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   508
(* (cf. L. Zhang, S. Malik: "The Quest for Efficient Boolean Satisfiability  *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   509
(* Solvers", July 2002, Fig. 2). In contrast to the other two ML solvers     *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   510
(* above, this solver produces proof traces. *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   511
(* ------------------------------------------------------------------------- *)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   512
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   513
let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   514
  type clause = int list * int
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   515
  type value = bool option
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   516
  datatype reason = Decided | Implied of clause | Level0 of int
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   517
  type variable = bool option * reason * int * int
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   518
  type proofs = int * int list Inttab.table
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   519
  type state =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   520
    int * int list * variable Inttab.table * clause list Inttab.table * proofs
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   521
  exception CONFLICT of clause * state
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   522
  exception UNSAT of clause * state
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   523
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   524
  fun neg i = ~i
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   525
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   526
  fun lit_value lit value = if lit > 0 then value else Option.map not value
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   527
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   528
  fun var_of vars lit: variable = the (Inttab.lookup vars (abs lit))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   529
  fun value_of vars lit = lit_value lit (#1 (var_of vars lit))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   530
  fun reason_of vars lit = #2 (var_of vars lit)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   531
  fun level_of vars lit = #3 (var_of vars lit)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   532
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   533
  fun is_true vars lit = (value_of vars lit = SOME true)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   534
  fun is_false vars lit = (value_of vars lit = SOME false)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   535
  fun is_unassigned vars lit = (value_of vars lit = NONE)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   536
  fun assignment_of vars lit = the_default NONE (try (value_of vars) lit)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   537
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   538
  fun put_var value reason level (_, _, _, rank) = (value, reason, level, rank)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   539
  fun incr_rank (value, reason, level, rank) = (value, reason, level, rank + 1)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   540
  fun update_var lit f = Inttab.map_entry (abs lit) f
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   541
  fun add_var lit = Inttab.update (abs lit, (NONE, Decided, ~1, 0))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   542
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   543
  fun assign lit r l = update_var lit (put_var (SOME (lit > 0)) r l)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   544
  fun unassign lit = update_var lit (put_var NONE Decided ~1)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   545
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   546
  fun add_proof [] (idx, ptab) = (idx, (idx + 1, ptab))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   547
    | add_proof ps (idx, ptab) = (idx, (idx + 1, Inttab.update (idx, ps) ptab))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   548
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   549
  fun level0_proof_of (Level0 idx) = SOME idx
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   550
    | level0_proof_of _ = NONE
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   551
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   552
  fun level0_proofs_of vars = map_filter (level0_proof_of o reason_of vars)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   553
  fun prems_of vars (lits, p) = p :: level0_proofs_of vars lits
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   554
  fun mk_proof vars cls proofs = add_proof (prems_of vars cls) proofs
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   555
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   556
  fun push lit cls (level, trail, vars, clss, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   557
    let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   558
      val (reason, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   559
        if level = 0 then apfst Level0 (mk_proof vars cls proofs)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   560
        else (Implied cls, proofs)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   561
    in (level, lit :: trail, assign lit reason level vars, clss, proofs) end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   562
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   563
  fun push_decided lit (level, trail, vars, clss, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   564
    let val vars' = assign lit Decided (level + 1) vars
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   565
    in (level + 1, lit :: 0 :: trail, vars', clss, proofs) end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   566
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   567
  fun prop (cls as (lits, _)) (cx as (units, state as (level, _, vars, _, _))) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   568
    if exists (is_true vars) lits then cx
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   569
    else if forall (is_false vars) lits then
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   570
      if level = 0 then raise UNSAT (cls, state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   571
      else raise CONFLICT (cls, state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   572
    else
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   573
      (case filter (is_unassigned vars) lits of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   574
        [lit] => (lit :: units, push lit cls state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   575
      | _ => cx)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   576
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   577
  fun propagate units (state as (_, _, _, clss, _)) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   578
    (case fold (fold prop o Inttab.lookup_list clss) units ([], state) of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   579
      ([], state') => (NONE, state')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   580
    | (units', state') => propagate units' state')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   581
    handle CONFLICT (cls, state') => (SOME cls, state')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   582
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   583
  fun max_unassigned (v, (NONE, _, _, rank)) (x as (_, r)) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   584
        if rank > r then (SOME v, rank) else x
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   585
    | max_unassigned _  x = x
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   586
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   587
  fun decide (state as (_, _, vars, _, _)) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   588
    (case Inttab.fold max_unassigned vars (NONE, 0) of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   589
      (SOME lit, _) => SOME (lit, push_decided lit state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   590
    | (NONE, _) => NONE)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   591
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   592
  fun mark lit = Inttab.update (abs lit, true)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   593
  fun marked ms lit = the_default false (Inttab.lookup ms (abs lit))
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   594
  fun ignore l ms lit = ((lit = l) orelse marked ms lit)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   595
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   596
  fun first_lit _ [] = raise Empty
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   597
    | first_lit _ (0 :: _) = raise Empty
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   598
    | first_lit pred (lit :: lits) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   599
        if pred lit then (lit, lits) else first_lit pred lits
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   600
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   601
  fun reason_cls_of vars lit =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   602
    (case reason_of vars lit of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   603
      Implied cls => cls
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   604
    | _ => raise Option)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   605
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   606
  fun analyze conflicting_cls (level, trail, vars, _, _) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   607
    let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   608
      fun back i lit (lits, p) trail ms ls ps =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   609
        let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   610
          val (lits0, lits') = List.partition (equal 0 o level_of vars) lits
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   611
          val lits1 = filter_out (ignore lit ms) lits'
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   612
          val lits2 = filter_out (equal level o level_of vars) lits1
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   613
          val i' = length lits1 - length lits2 + i
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   614
          val ms' = fold mark lits1 ms
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   615
          val ls' = lits2 @ ls
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   616
          val ps' = level0_proofs_of vars lits0 @ (p :: ps)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   617
          val (lit', trail') = first_lit (marked ms') trail
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   618
        in 
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   619
          if i' = 1 then (neg lit', ls', rev ps')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   620
          else back (i' - 1) lit' (reason_cls_of vars lit') trail' ms' ls' ps'
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   621
        end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   622
    in back 0 0 conflicting_cls trail Inttab.empty [] [] end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   623
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   624
  fun keep_clause (cls as (lits, _)) (level, trail, vars, clss, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   625
    let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   626
      val vars' = fold (fn lit => update_var lit incr_rank) lits vars
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   627
      val clss' = fold (fn lit => Inttab.cons_list (neg lit, cls)) lits clss
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   628
    in (level, trail, vars', clss', proofs) end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   629
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   630
  fun learn (cls as (lits, _)) = (length lits <= 2) ? keep_clause cls
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   631
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   632
  fun backjump _ (state as (_, [], _, _, _)) = state 
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   633
    | backjump i (level, 0 :: trail, vars, clss, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   634
        (level - 1, trail, vars, clss, proofs) |> (i > 1) ? backjump (i - 1)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   635
    | backjump i (level, lit :: trail, vars, clss, proofs) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   636
        backjump i (level, trail, unassign lit vars, clss, proofs)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   637
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   638
  fun search units state =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   639
    (case propagate units state of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   640
      (NONE, state' as (_, _, vars, _, _)) =>
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   641
        (case decide state' of
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   642
          NONE => SatSolver.SATISFIABLE (assignment_of vars)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   643
        | SOME (lit, state'') => search [lit] state'')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   644
    | (SOME conflicting_cls, state' as (level, trail, vars, clss, proofs)) =>
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   645
        let 
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   646
          val (lit, lits, ps) = analyze conflicting_cls state'
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   647
          val (idx, proofs') = add_proof ps proofs
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   648
          val cls = (lit :: lits, idx)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   649
        in
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   650
          (level, trail, vars, clss, proofs')
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   651
          |> backjump (level - fold (Integer.max o level_of vars) lits 0)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   652
          |> learn cls
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   653
          |> push lit cls
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   654
          |> search [lit]
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   655
        end)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   656
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   657
  fun has_opposing_lits [] = false
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   658
    | has_opposing_lits (lit :: lits) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   659
        member (op =) lits (neg lit) orelse has_opposing_lits lits
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   660
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   661
  fun add_clause (cls as ([_], _)) (units, state) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   662
        let val (units', state') = prop cls (units, state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   663
        in (units', state') end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   664
    | add_clause (cls as (lits, _)) (cx as (units, state)) =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   665
        if has_opposing_lits lits then cx
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   666
        else (units, keep_clause cls state)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   667
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   668
  fun mk_clause lits proofs =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   669
    apfst (pair (distinct (op =) lits)) (add_proof [] proofs)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   670
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   671
  fun solve litss =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   672
    let
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   673
      val (clss, proofs) = fold_map mk_clause litss (0, Inttab.empty)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   674
      val vars = fold (fold add_var) litss Inttab.empty
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   675
      val state = (0, [], vars, Inttab.empty, proofs)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   676
    in uncurry search (fold add_clause clss ([], state)) end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   677
    handle UNSAT (conflicting_cls, (_, _, vars, _, proofs)) =>
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   678
      let val (idx, (_, ptab)) = mk_proof vars conflicting_cls proofs
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   679
      in SatSolver.UNSATISFIABLE (SOME (ptab, idx)) end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   680
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   681
  fun variable_of (Prop_Logic.BoolVar 0) = error "bad propositional variable"
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   682
    | variable_of (Prop_Logic.BoolVar i) = i
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   683
    | variable_of _ = error "expected formula in CNF"
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   684
  fun literal_of (Prop_Logic.Not fm) = neg (variable_of fm)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   685
    | literal_of fm = variable_of fm
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   686
  fun clause_of (Prop_Logic.Or (fm1, fm2)) = clause_of fm1 @ clause_of fm2
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   687
    | clause_of fm = [literal_of fm]
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   688
  fun clauses_of (Prop_Logic.And (fm1, fm2)) = clauses_of fm1 @ clauses_of fm2
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   689
    | clauses_of Prop_Logic.True = [[1, ~1]]
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   690
    | clauses_of Prop_Logic.False = [[1], [~1]]
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   691
    | clauses_of fm = [clause_of fm]
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   692
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   693
  fun dpll_solver fm =
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   694
    let val fm' = if Prop_Logic.is_cnf fm then fm else Prop_Logic.defcnf fm
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   695
    in solve (clauses_of fm') end
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   696
in
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   697
  SatSolver.add_solver ("dpll_p", dpll_solver)
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   698
end;
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   699
848d507584db added internal proof-producing SAT solver
boehmes
parents: 56147
diff changeset
   700
(* ------------------------------------------------------------------------- *)
14753
f40b45db8cf0 Comments fixed
webertj
parents: 14703
diff changeset
   701
(* 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
   702
(* 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
   703
(* 'NOT_CONFIGURED'.  (However, the solver may return 'UNKNOWN'.)            *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   704
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   705
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   706
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   707
  fun auto_solver fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   708
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   709
    fun loop [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   710
      SatSolver.UNKNOWN
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   711
      | loop ((name, solver)::solvers) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   712
      if name="auto" then
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   713
        (* 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
   714
        loop solvers
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   715
      else (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   716
        (* apply 'solver' to 'fm' *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   717
        solver fm
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   718
          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
   719
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   720
  in
56147
9589605bcf41 prefer more robust Synchronized.var;
wenzelm
parents: 55436
diff changeset
   721
    loop (SatSolver.get_solvers ())
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   722
  end
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   723
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   724
  SatSolver.add_solver ("auto", auto_solver)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   725
end;
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   726
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   727
(* ------------------------------------------------------------------------- *)
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   728
(* MiniSat 1.14                                                              *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   729
(* (http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/)            *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   730
(* ------------------------------------------------------------------------- *)
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   731
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   732
(* ------------------------------------------------------------------------- *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   733
(* "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
   734
(* Matthews, which can output ASCII proof traces.  Replaying binary proof    *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   735
(* traces generated by MiniSat-p_v1.14 has _not_ been implemented.           *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   736
(* ------------------------------------------------------------------------- *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   737
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   738
(* add "minisat_with_proofs" _before_ "minisat" to the available solvers, so *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   739
(* that the latter is preferred by the "auto" solver                         *)
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   740
20152
b6373fe199e1 MiniSat proof trace format changed; MiniSat is now expected to produce a proof also for "trivial" problems
webertj
parents: 20137
diff changeset
   741
(* 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
   742
(* 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
   743
(* 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
   744
(* 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
   745
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   746
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   747
  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
   748
  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
   749
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   750
    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
   751
    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
   752
    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
   753
    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
   754
    val proofpath  = File.tmp_path (Path.explode ("result" ^ serial_str ^ ".prf"))
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
   755
    val cmd        = getenv "MINISAT_HOME" ^ "/minisat " ^ File.shell_path inpath ^ " -r " ^ File.shell_path outpath ^ " -t " ^ File.shell_path proofpath ^ "> /dev/null"
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   756
    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
   757
    fun readfn ()  = SatSolver.read_std_result_file outpath ("SAT", "", "UNSAT")
41944
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
   758
    val _ = if File.exists inpath then warning ("overwriting existing file " ^ Path.print inpath) else ()
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
   759
    val _ = if File.exists outpath then warning ("overwriting existing file " ^ Path.print outpath) else ()
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   760
    val cnf        = Prop_Logic.defcnf fm
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   761
    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
   762
    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
   763
    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
   764
  in  case result of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   765
    SatSolver.UNSATISFIABLE NONE =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   766
    (let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   767
      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
   768
        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
   769
      (* representation of clauses as ordered lists of literals (with duplicates removed) *)
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   770
      fun clause_to_lit_list (Prop_Logic.Or (fm1, fm2)) =
39687
4e9b6ada3a21 modernized structure Ord_List;
wenzelm
parents: 37254
diff changeset
   771
        Ord_List.union int_ord (clause_to_lit_list fm1) (clause_to_lit_list fm2)
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   772
        | clause_to_lit_list (Prop_Logic.BoolVar i) =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   773
        [i]
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   774
        | clause_to_lit_list (Prop_Logic.Not (Prop_Logic.BoolVar i)) =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   775
        [~i]
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   776
        | clause_to_lit_list _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   777
        raise INVALID_PROOF "Error: invalid clause in CNF formula."
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   778
      fun cnf_number_of_clauses (Prop_Logic.And (fm1, fm2)) =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   779
        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
   780
        | cnf_number_of_clauses _ =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   781
        1
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   782
      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
   783
      (* int list array *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   784
      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
   785
      (* initialize the 'clauses' array *)
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   786
      fun init_array (Prop_Logic.And (fm1, fm2), n) =
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   787
        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
   788
        | init_array (fm, n) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   789
        (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
   790
      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
   791
      (* 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
   792
      (* original order:                                                      *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   793
      val last_ref_clause = Unsynchronized.ref (number_of_clauses - 1)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   794
      (* 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
   795
      (* 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
   796
      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
   797
      let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   798
        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
   799
          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
   800
            (* search from beginning again *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   801
            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
   802
          (* 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
   803
          (* 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
   804
          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
   805
            (* success *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   806
            last_ref_clause := index;
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   807
            SOME index
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   808
          ) 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
   809
            (* failure *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   810
            NONE
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   811
          else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   812
            (* continue search *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   813
            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
   814
      in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   815
        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
   816
      end
55436
9781e17dcc23 removed odd comments -- inferred types are shown by Prover IDE;
wenzelm
parents: 52049
diff changeset
   817
      fun int_from_string s =
9781e17dcc23 removed odd comments -- inferred types are shown by Prover IDE;
wenzelm
parents: 52049
diff changeset
   818
        (case Int.fromString s of
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   819
          SOME i => i
55436
9781e17dcc23 removed odd comments -- inferred types are shown by Prover IDE;
wenzelm
parents: 52049
diff changeset
   820
        | NONE   => raise INVALID_PROOF ("File format error: number expected (" ^ quote s ^ " encountered)."))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   821
      (* parse the proof file *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   822
      val clause_table  = Unsynchronized.ref (Inttab.empty : int list Inttab.table)
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   823
      val empty_id      = Unsynchronized.ref ~1
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   824
      (* 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
   825
      (* our proof format, where original clauses are numbered starting from 0  *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   826
      val clause_id_map = Unsynchronized.ref (Inttab.empty : int Inttab.table)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   827
      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
   828
        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
   829
          SOME id' => id'
41491
a2ad5b824051 eliminated Int.toString;
wenzelm
parents: 41471
diff changeset
   830
        | NONE     => raise INVALID_PROOF ("Clause ID " ^ string_of_int id ^ " used, but not defined.")
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   831
      )
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   832
      val next_id = Unsynchronized.ref (number_of_clauses - 1)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   833
      fun process_tokens [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   834
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   835
        | process_tokens (tok::toks) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   836
        if tok="R" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   837
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   838
            id::sep::lits =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   839
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   840
              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
   841
              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
   842
              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
   843
              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
   844
              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
   845
                               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
   846
                             | 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
   847
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   848
              (* 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
   849
              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
   850
                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
   851
              (* 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
   852
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   853
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   854
            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
   855
        ) 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
   856
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   857
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   858
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   859
              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
   860
              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
   861
              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
   862
              (* 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
   863
              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
   864
                | unevens (x :: [])      = x :: []
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   865
                | 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
   866
              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
   867
              (* extend the mapping of clause IDs with this newly defined ID *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   868
              val proof_id = Unsynchronized.inc next_id
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   869
              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
   870
                               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
   871
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   872
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   873
              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
   874
                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
   875
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   876
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   877
            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
   878
        ) 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
   879
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   880
            [id] =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   881
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   882
              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
   883
              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
   884
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   885
              (* simply ignore "D" *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   886
              ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   887
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   888
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   889
            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
   890
        ) 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
   891
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   892
            [id1, id2] =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   893
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   894
              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
   895
              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
   896
              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
   897
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   898
              (* update conflict id *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   899
              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
   900
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   901
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   902
            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
   903
        ) else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   904
          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
   905
      fun process_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   906
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   907
        | process_lines (l::ls) = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   908
          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
   909
          process_lines ls
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   910
        )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   911
      (* proof *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   912
      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
   913
      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
   914
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   915
      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
   916
    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
   917
  | result =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   918
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   919
  end
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   920
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   921
  SatSolver.add_solver ("minisat_with_proofs", minisat_with_proofs)
20135
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   922
end;
5a6b33268bb6 support for MiniSat proof traces added
webertj
parents: 20033
diff changeset
   923
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   924
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   925
  fun minisat fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   926
  let
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
   927
    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
   928
    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
   929
    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
   930
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
   931
    val cmd        = getenv "MINISAT_HOME" ^ "/minisat " ^ File.shell_path inpath ^ " -r " ^ File.shell_path outpath ^ " > /dev/null"
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   932
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (Prop_Logic.defcnf fm)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   933
    fun readfn ()  = SatSolver.read_std_result_file outpath ("SAT", "", "UNSAT")
41944
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
   934
    val _ = if File.exists inpath then warning ("overwriting existing file " ^ Path.print inpath) else ()
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
   935
    val _ = if File.exists outpath then warning ("overwriting existing file " ^ Path.print outpath) else ()
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   936
    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
   937
    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
   938
    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
   939
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   940
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   941
  end
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   942
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   943
  SatSolver.add_solver ("minisat", minisat)
20033
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   944
end;
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   945
2b8dbb637792 added support for MiniSat 1.14
webertj
parents: 19190
diff changeset
   946
(* ------------------------------------------------------------------------- *)
15332
0dc05858a862 added ZCHAFF_VERSION
webertj
parents: 15329
diff changeset
   947
(* zChaff (http://www.princeton.edu/~chaff/zchaff.html)                      *)
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   948
(* ------------------------------------------------------------------------- *)
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
   949
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   950
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   951
(* '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
   952
(* 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
   953
(* 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
   954
(* 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
   955
(* 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
   956
(* ------------------------------------------------------------------------- *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   957
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   958
(* 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
   959
(* that the latter is preferred by the "auto" solver                         *)
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   960
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
   961
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   962
  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
   963
  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
   964
  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
   965
    SatSolver.UNSATISFIABLE NONE =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   966
    (let
43701
f91c3c899911 comment;
wenzelm
parents: 41944
diff changeset
   967
      (* FIXME File.tmp_path (!?) *)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   968
      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
   969
        handle IO.Io _ => raise INVALID_PROOF "Could not read file \"resolve_trace\""
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   970
      fun cnf_number_of_clauses (Prop_Logic.And (fm1, fm2)) =
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   971
            cnf_number_of_clauses fm1 + cnf_number_of_clauses fm2
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
   972
        | cnf_number_of_clauses _ = 1
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   973
      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
   974
        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
   975
          SOME i => i
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   976
        | 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
   977
      )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   978
      (* parse the "resolve_trace" file *)
32740
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   979
      val clause_offset = Unsynchronized.ref ~1
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   980
      val clause_table  = Unsynchronized.ref (Inttab.empty : int list Inttab.table)
9dd0a2f83429 explicit indication of Unsynchronized.ref;
wenzelm
parents: 31219
diff changeset
   981
      val empty_id      = Unsynchronized.ref ~1
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   982
      fun process_tokens [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   983
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   984
        | process_tokens (tok::toks) =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   985
        if tok="CL:" then (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   986
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   987
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   988
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   989
              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
   990
              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
   991
              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
   992
              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
   993
              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
   994
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   995
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   996
              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
   997
                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
   998
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
   999
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1000
            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
  1001
        ) 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
  1002
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1003
            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
  1004
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1005
              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
  1006
              (* 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
  1007
              val _   = if !clause_offset = ~1 then clause_offset :=
52049
156e12d5cb92 tuned signature;
wenzelm
parents: 51940
diff changeset
  1008
                (case Inttab.max (!clause_table) of
156e12d5cb92 tuned signature;
wenzelm
parents: 51940
diff changeset
  1009
                  SOME (id, _) => id
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
  1010
                | NONE => cnf_number_of_clauses (Prop_Logic.defcnf fm) - 1  (* the first clause ID is 0, not 1 *))
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1011
                else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1012
                  ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1013
              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
  1014
              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
  1015
              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
  1016
              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
  1017
              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
  1018
              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
  1019
              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
  1020
              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
  1021
              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
  1022
              (* 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
  1023
              (* 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
  1024
              (* 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
  1025
              (* 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
  1026
              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
  1027
              (* 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
  1028
              (* 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
  1029
              (* 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
  1030
              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
  1031
              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
  1032
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1033
              (* update clause table *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1034
              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
  1035
                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
  1036
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1037
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1038
            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
  1039
        ) 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
  1040
          case toks of
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1041
            id::sep::ids =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1042
            let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1043
              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
  1044
              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
  1045
              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
  1046
              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
  1047
              (* 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
  1048
              (* 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
  1049
              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
  1050
              val rs           = cid :: map (fn v => !clause_offset + v) vids
52049
156e12d5cb92 tuned signature;
wenzelm
parents: 51940
diff changeset
  1051
              val new_empty_id = the_default (!clause_offset) (Option.map fst (Inttab.max (!clause_table))) + 1
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1052
            in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1053
              (* 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
  1054
              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
  1055
                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
  1056
              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
  1057
            end
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1058
          | _ =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1059
            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
  1060
        ) else
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1061
          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
  1062
      fun process_lines [] =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1063
        ()
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1064
        | process_lines (l::ls) = (
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1065
          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
  1066
          process_lines ls
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1067
        )
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1068
      (* proof *)
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1069
      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
  1070
      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
  1071
    in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1072
      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
  1073
    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
  1074
  | result =>
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1075
    result
17493
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
  1076
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1077
  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
  1078
end;
cf8713d880b1 SAT solver interface modified to support proofs of unsatisfiability
webertj
parents: 16915
diff changeset
  1079
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
  1080
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1081
  fun zchaff fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1082
  let
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
  1083
    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
  1084
    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
  1085
    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
  1086
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
  1087
    val cmd        = getenv "ZCHAFF_HOME" ^ "/zchaff " ^ File.shell_path inpath ^ " > " ^ File.shell_path outpath
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
  1088
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (Prop_Logic.defcnf fm)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1089
    fun readfn ()  = SatSolver.read_std_result_file outpath ("Instance Satisfiable", "", "Instance Unsatisfiable")
41944
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1090
    val _ = if File.exists inpath then warning ("overwriting existing file " ^ Path.print inpath) else ()
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1091
    val _ = if File.exists outpath then warning ("overwriting existing file " ^ Path.print outpath) else ()
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1092
    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
  1093
    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
  1094
    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
  1095
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1096
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1097
  end
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
  1098
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1099
  SatSolver.add_solver ("zchaff", zchaff)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1100
end;
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1101
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1102
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1103
(* BerkMin 561 (http://eigold.tripod.com/BerkMin.html)                       *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1104
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1105
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1106
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1107
  fun berkmin fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1108
  let
30275
381ce8d88cb8 Reintroduced previous changes: Made "Refute.norm_rhs" public and simplified the configuration of the BerkMin and zChaff SAT solvers.
blanchet
parents: 30240
diff changeset
  1109
    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
  1110
    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
  1111
    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
  1112
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
30275
381ce8d88cb8 Reintroduced previous changes: Made "Refute.norm_rhs" public and simplified the configuration of the BerkMin and zChaff SAT solvers.
blanchet
parents: 30240
diff changeset
  1113
    val exec       = getenv "BERKMIN_EXE"
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
  1114
    val cmd        = getenv "BERKMIN_HOME" ^ "/" ^ (if exec = "" then "BerkMin561" else exec) ^ " " ^ File.shell_path inpath ^ " > " ^ File.shell_path outpath
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
  1115
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (Prop_Logic.defcnf fm)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1116
    fun readfn ()  = SatSolver.read_std_result_file outpath ("Satisfiable          !!", "solution =", "UNSATISFIABLE          !!")
41944
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1117
    val _ = if File.exists inpath then warning ("overwriting existing file " ^ Path.print inpath) else ()
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1118
    val _ = if File.exists outpath then warning ("overwriting existing file " ^ Path.print outpath) else ()
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1119
    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
  1120
    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
  1121
    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
  1122
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1123
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1124
  end
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1125
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1126
  SatSolver.add_solver ("berkmin", berkmin)
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1127
end;
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1128
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1129
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1130
(* Jerusat 1.3 (http://www.cs.tau.ac.il/~ale1/)                              *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1131
(* ------------------------------------------------------------------------- *)
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1132
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1133
let
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1134
  fun jerusat fm =
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1135
  let
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1136
    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
  1137
    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
  1138
    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
  1139
    val outpath    = File.tmp_path (Path.explode ("result" ^ serial_str))
35011
9e55e87434ff proper treatment of paths passed to the shell -- to allow spaces in file names as usual;
wenzelm
parents: 35010
diff changeset
  1140
    val cmd        = getenv "JERUSAT_HOME" ^ "/Jerusat1.3 " ^ File.shell_path inpath ^ " > " ^ File.shell_path outpath
41471
54a58904a598 modernized structure Prop_Logic;
wenzelm
parents: 40314
diff changeset
  1141
    fun writefn fm = SatSolver.write_dimacs_cnf_file inpath (Prop_Logic.defcnf fm)
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1142
    fun readfn ()  = SatSolver.read_std_result_file outpath ("s SATISFIABLE", "v ", "s UNSATISFIABLE")
41944
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1143
    val _ = if File.exists inpath then warning ("overwriting existing file " ^ Path.print inpath) else ()
b97091ae583a Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
wenzelm
parents: 41491
diff changeset
  1144
    val _ = if File.exists outpath then warning ("overwriting existing file " ^ Path.print outpath) else ()
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1145
    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
  1146
    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
  1147
    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
  1148
  in
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1149
    result
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1150
  end
14965
7155b319eafa new SAT solver interface
webertj
parents: 14805
diff changeset
  1151
in
22567
1565d476a9e2 removed assert/deny (avoid clash with Alice keywords and confusion due to strict evaluation);
wenzelm
parents: 22220
diff changeset
  1152
  SatSolver.add_solver ("jerusat", jerusat)
14487
157d0ea7b2da Installed solvers now determined at call time (as opposed to compile time)
webertj
parents: 14460
diff changeset
  1153
end;
14453
3397a69dfa4e Internal and external SAT solvers
webertj
parents:
diff changeset
  1154