mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 11:15:43 -05:00
Added unsat-core option in sat_solve
Cleaned up a bit soler_types and added some doc
This commit is contained in:
parent
ccfbe72bdf
commit
6338f682df
9 changed files with 100 additions and 29 deletions
3
TODO.md
3
TODO.md
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
## Main goals
|
## Main goals
|
||||||
|
|
||||||
- Include cnf conversion in 'sat' library
|
|
||||||
- Modify theories to allow passing bulk of assumed literals
|
- Modify theories to allow passing bulk of assumed literals
|
||||||
* Create shared "vector" (formulas/atoms ?)
|
* Create shared "vector" (formulas/atoms ?)
|
||||||
* Allow theory propagation
|
* Allow theory propagation
|
||||||
|
|
@ -11,7 +10,6 @@
|
||||||
* Clean Solver_types interface
|
* Clean Solver_types interface
|
||||||
- Add proof output for smt/theories
|
- Add proof output for smt/theories
|
||||||
* Each theory brings its own proof output (tautologies), somehow
|
* Each theory brings its own proof output (tautologies), somehow
|
||||||
- Add model extraction (at least for SAT)
|
|
||||||
- Allow to plug one's code into boolean propagation
|
- Allow to plug one's code into boolean propagation
|
||||||
* react upon propagation (possibly by propagating more, or side-effect)
|
* react upon propagation (possibly by propagating more, or side-effect)
|
||||||
* more advanced/specific propagation (2-clauses)?
|
* more advanced/specific propagation (2-clauses)?
|
||||||
|
|
@ -20,5 +18,4 @@
|
||||||
|
|
||||||
## Long term goals
|
## Long term goals
|
||||||
|
|
||||||
- unsat-core (easy from resolution proofs)
|
|
||||||
- max-sat/max-smt
|
- max-sat/max-smt
|
||||||
|
|
|
||||||
25
sat/res.ml
25
sat/res.ml
|
|
@ -257,6 +257,29 @@ module Make(St : Solver_types.S)(Proof : sig type proof end) = struct
|
||||||
assert_can_prove_unsat c;
|
assert_can_prove_unsat c;
|
||||||
return_proof (St.empty_clause, [])
|
return_proof (St.empty_clause, [])
|
||||||
|
|
||||||
|
(* Compute unsat-core *)
|
||||||
|
let compare_cl c d =
|
||||||
|
let rec aux = function
|
||||||
|
| [], [] -> 0
|
||||||
|
| a :: r, a' :: r' -> begin match compare_atoms a a' with
|
||||||
|
| 0 -> aux (r, r')
|
||||||
|
| x -> x
|
||||||
|
end
|
||||||
|
| _ :: _ , [] -> -1
|
||||||
|
| [], _ :: _ -> 1
|
||||||
|
in
|
||||||
|
aux (to_list c, to_list d)
|
||||||
|
|
||||||
|
let unsat_core proof =
|
||||||
|
let rec aux proof =
|
||||||
|
let p = proof () in
|
||||||
|
match p.step with
|
||||||
|
| Hypothesis | Lemma _ -> [p.conclusion]
|
||||||
|
| Resolution (proof1, proof2, _) ->
|
||||||
|
List.rev_append (aux proof1) (aux proof2)
|
||||||
|
in
|
||||||
|
List.sort_uniq compare_cl (aux proof)
|
||||||
|
|
||||||
(* Print proof graph *)
|
(* Print proof graph *)
|
||||||
let _i = ref 0
|
let _i = ref 0
|
||||||
let new_id () = incr _i; "id_" ^ (string_of_int !_i)
|
let new_id () = incr _i; "id_" ^ (string_of_int !_i)
|
||||||
|
|
@ -284,6 +307,8 @@ module Make(St : Solver_types.S)(Proof : sig type proof end) = struct
|
||||||
else
|
else
|
||||||
()
|
()
|
||||||
|
|
||||||
|
(* We use a custom function instead of the functions in Solver_type,
|
||||||
|
so that atoms are sorted before printing. *)
|
||||||
let print_clause fmt c = print_cl fmt (to_list c)
|
let print_clause fmt c = print_cl fmt (to_list c)
|
||||||
|
|
||||||
let print_dot_rule opt f arg fmt cl =
|
let print_dot_rule opt f arg fmt cl =
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ module type S = sig
|
||||||
val prove_unsat : clause -> proof
|
val prove_unsat : clause -> proof
|
||||||
(** Given a conflict clause [c], returns a proof of the empty clause. *)
|
(** Given a conflict clause [c], returns a proof of the empty clause. *)
|
||||||
|
|
||||||
|
val unsat_core : proof -> clause list
|
||||||
|
(** Returns the unsat_core of the given proof, i.e the lists of conclusions of all leafs of the proof. *)
|
||||||
|
|
||||||
val print_dot : Format.formatter -> proof -> unit
|
val print_dot : Format.formatter -> proof -> unit
|
||||||
(** Print the given proof in dot format on the given formatter. *)
|
(** Print the given proof in dot format on the given formatter. *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ module Make(Dummy : sig end) = struct
|
||||||
exception Bad_atom
|
exception Bad_atom
|
||||||
|
|
||||||
type atom = Fsat.t
|
type atom = Fsat.t
|
||||||
|
type clause = Stypes.clause
|
||||||
type proof = SatSolver.Proof.proof
|
type proof = SatSolver.Proof.proof
|
||||||
|
|
||||||
type res =
|
type res =
|
||||||
|
|
@ -107,7 +108,6 @@ module Make(Dummy : sig end) = struct
|
||||||
let equal = Fsat.equal
|
let equal = Fsat.equal
|
||||||
let compare = Fsat.compare
|
let compare = Fsat.compare
|
||||||
|
|
||||||
let print_atom = Fsat.print
|
|
||||||
let iter_atoms = Fsat.iter
|
let iter_atoms = Fsat.iter
|
||||||
|
|
||||||
let solve () =
|
let solve () =
|
||||||
|
|
@ -130,6 +130,10 @@ module Make(Dummy : sig end) = struct
|
||||||
| None -> assert false
|
| None -> assert false
|
||||||
| Some c -> SatSolver.Proof.prove_unsat c
|
| Some c -> SatSolver.Proof.prove_unsat c
|
||||||
|
|
||||||
|
let unsat_core = SatSolver.Proof.unsat_core
|
||||||
|
|
||||||
|
let print_atom = Fsat.print
|
||||||
|
let print_clause = Stypes.print_clause
|
||||||
let print_proof = SatSolver.Proof.print_dot
|
let print_proof = SatSolver.Proof.print_dot
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
15
sat/sat.mli
15
sat/sat.mli
|
|
@ -13,6 +13,9 @@ module Make(Dummy: sig end) : sig
|
||||||
type atom = Fsat.t
|
type atom = Fsat.t
|
||||||
(** Type for atoms, i.e boolean literals. *)
|
(** Type for atoms, i.e boolean literals. *)
|
||||||
|
|
||||||
|
type clause
|
||||||
|
(** Abstract type for clauses *)
|
||||||
|
|
||||||
type proof
|
type proof
|
||||||
(** Abstract type for resolution proofs *)
|
(** Abstract type for resolution proofs *)
|
||||||
|
|
||||||
|
|
@ -36,9 +39,6 @@ module Make(Dummy: sig end) : sig
|
||||||
(** Usual hash and comparison functions. For now, directly uses
|
(** Usual hash and comparison functions. For now, directly uses
|
||||||
[Pervasives] and [Hashtbl] builtins. *)
|
[Pervasives] and [Hashtbl] builtins. *)
|
||||||
|
|
||||||
val print_atom : Format.formatter -> atom -> unit
|
|
||||||
(** Print the atom on the given formatter. *)
|
|
||||||
|
|
||||||
val iter_atoms : (atom -> unit) -> unit
|
val iter_atoms : (atom -> unit) -> unit
|
||||||
(** Allows iteration over all atoms created (even if unused). *)
|
(** Allows iteration over all atoms created (even if unused). *)
|
||||||
|
|
||||||
|
|
@ -54,6 +54,15 @@ module Make(Dummy: sig end) : sig
|
||||||
val get_proof : unit -> proof
|
val get_proof : unit -> proof
|
||||||
(** Returns the resolution proof found, if [solve] returned [Unsat]. *)
|
(** Returns the resolution proof found, if [solve] returned [Unsat]. *)
|
||||||
|
|
||||||
|
val unsat_core : proof -> clause list
|
||||||
|
(** Returns the unsat-core of the proof. *)
|
||||||
|
|
||||||
|
val print_atom : Format.formatter -> atom -> unit
|
||||||
|
(** Print the atom on the given formatter. *)
|
||||||
|
|
||||||
|
val print_clause : Format.formatter -> clause -> unit
|
||||||
|
(** Print the clause on the given formatter. *)
|
||||||
|
|
||||||
val print_proof : Format.formatter -> proof -> unit
|
val print_proof : Format.formatter -> proof -> unit
|
||||||
(** Print the given proof in dot format. *)
|
(** Print the given proof in dot format. *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,9 @@ module Make (F : Formula_intf.S)
|
||||||
tatoms_queue = Queue.create ();
|
tatoms_queue = Queue.create ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let to_float i = float_of_int i
|
||||||
|
let to_int f = int_of_float f
|
||||||
|
|
||||||
let f_weight i j =
|
let f_weight i j =
|
||||||
(Vec.get env.vars j).weight < (Vec.get env.vars i).weight
|
(Vec.get env.vars j).weight < (Vec.get env.vars i).weight
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ module Make (F : Formula_intf.S) = struct
|
||||||
|
|
||||||
and clause =
|
and clause =
|
||||||
{ name : string;
|
{ name : string;
|
||||||
mutable atoms : atom Vec.t ;
|
atoms : atom Vec.t ;
|
||||||
mutable activity : float;
|
mutable activity : float;
|
||||||
mutable removed : bool;
|
mutable removed : bool;
|
||||||
learnt : bool;
|
learnt : bool;
|
||||||
|
|
@ -154,14 +154,25 @@ module Make (F : Formula_intf.S) = struct
|
||||||
let cpt = ref 0 in
|
let cpt = ref 0 in
|
||||||
fun () -> incr cpt; "C" ^ (string_of_int !cpt)
|
fun () -> incr cpt; "C" ^ (string_of_int !cpt)
|
||||||
|
|
||||||
let to_float i = float_of_int i
|
|
||||||
|
|
||||||
let to_int f = int_of_float f
|
|
||||||
|
|
||||||
let clear () =
|
let clear () =
|
||||||
cpt_mk_var := 0;
|
cpt_mk_var := 0;
|
||||||
ma := MA.empty
|
ma := MA.empty
|
||||||
|
|
||||||
|
(* Pretty printing for atoms and clauses *)
|
||||||
|
let print_atom fmt a = F.print fmt a.lit
|
||||||
|
|
||||||
|
let print_atoms fmt v =
|
||||||
|
print_atom fmt (Vec.get v 0);
|
||||||
|
if (Vec.size v) > 1 then begin
|
||||||
|
for i = 1 to (Vec.size v) - 1 do
|
||||||
|
Format.fprintf fmt " ∨ %a" print_atom (Vec.get v i)
|
||||||
|
done
|
||||||
|
end
|
||||||
|
|
||||||
|
let print_clause fmt c =
|
||||||
|
Format.fprintf fmt "%s : %a" c.name print_atoms c.atoms
|
||||||
|
|
||||||
|
(* Complete debug printing *)
|
||||||
let sign a = if a==a.var.pa then "" else "-"
|
let sign a = if a==a.var.pa then "" else "-"
|
||||||
|
|
||||||
let level a =
|
let level a =
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ module type S = sig
|
||||||
(** The signatures of clauses used in the Solver. *)
|
(** The signatures of clauses used in the Solver. *)
|
||||||
|
|
||||||
type formula
|
type formula
|
||||||
|
type varmap
|
||||||
|
val ma : varmap ref
|
||||||
|
|
||||||
type var = {
|
type var = {
|
||||||
vid : int;
|
vid : int;
|
||||||
|
|
@ -38,7 +40,7 @@ module type S = sig
|
||||||
|
|
||||||
and clause = {
|
and clause = {
|
||||||
name : string;
|
name : string;
|
||||||
mutable atoms : atom Vec.t;
|
atoms : atom Vec.t;
|
||||||
mutable activity : float;
|
mutable activity : float;
|
||||||
mutable removed : bool;
|
mutable removed : bool;
|
||||||
learnt : bool;
|
learnt : bool;
|
||||||
|
|
@ -46,37 +48,46 @@ module type S = sig
|
||||||
}
|
}
|
||||||
|
|
||||||
and reason = clause option
|
and reason = clause option
|
||||||
|
|
||||||
and premise = clause list
|
and premise = clause list
|
||||||
|
(** Recursive types for literals (atoms) and clauses *)
|
||||||
val cpt_mk_var : int ref
|
|
||||||
type varmap
|
|
||||||
val ma : varmap ref
|
|
||||||
|
|
||||||
val dummy_var : var
|
val dummy_var : var
|
||||||
val dummy_atom : atom
|
val dummy_atom : atom
|
||||||
val dummy_clause : clause
|
val dummy_clause : clause
|
||||||
val empty_clause : clause
|
(** Dummy values for use in vector dummys *)
|
||||||
|
|
||||||
val make_var : formula -> var * bool
|
val empty_clause : clause
|
||||||
|
(** The empty clause *)
|
||||||
|
|
||||||
val add_atom : formula -> atom
|
val add_atom : formula -> atom
|
||||||
|
(** Returns the atom associated with the given formula *)
|
||||||
|
|
||||||
|
val make_var : formula -> var * bool
|
||||||
|
(** Returns the variable linked with the given formula, and wether the atom associated with the formula
|
||||||
|
is [var.pa] or [var.na] *)
|
||||||
|
|
||||||
val make_clause : string -> atom list -> int -> bool -> premise -> clause
|
val make_clause : string -> atom list -> int -> bool -> premise -> clause
|
||||||
|
(** [make_clause name atoms size learnt premise] creates a clause with the given attributes. *)
|
||||||
|
|
||||||
val fresh_name : unit -> string
|
val fresh_name : unit -> string
|
||||||
|
|
||||||
val fresh_lname : unit -> string
|
val fresh_lname : unit -> string
|
||||||
|
|
||||||
val fresh_dname : unit -> string
|
val fresh_dname : unit -> string
|
||||||
|
(** Fresh names for clauses *)
|
||||||
|
|
||||||
val to_float : int -> float
|
|
||||||
|
|
||||||
val to_int : float -> int
|
|
||||||
val made_vars_info : var Vec.t -> int
|
val made_vars_info : var Vec.t -> int
|
||||||
|
(** Returns the number of variables created, and fill the given vector with the variables created.
|
||||||
|
Each variable is set in the vecotr with its [vid] as index. *)
|
||||||
|
|
||||||
val clear : unit -> unit
|
val clear : unit -> unit
|
||||||
|
(** Forget all variables cretaed *)
|
||||||
|
|
||||||
|
val print_atom : Format.formatter -> atom -> unit
|
||||||
|
val print_clause : Format.formatter -> clause -> unit
|
||||||
|
(** Pretty printing functions for atoms and clauses *)
|
||||||
|
|
||||||
val pp_atom : Buffer.t -> atom -> unit
|
val pp_atom : Buffer.t -> atom -> unit
|
||||||
val pp_clause : Buffer.t -> clause -> unit
|
val pp_clause : Buffer.t -> clause -> unit
|
||||||
|
(** Debug function for atoms and clauses (very verbose) *)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,11 @@ let rec print_cl fmt = function
|
||||||
| [a] -> Sat.Fsat.print fmt a
|
| [a] -> Sat.Fsat.print fmt a
|
||||||
| a :: ((_ :: _) as r) -> Format.fprintf fmt "%a ∨ %a" Sat.Fsat.print a print_cl r
|
| a :: ((_ :: _) as r) -> Format.fprintf fmt "%a ∨ %a" Sat.Fsat.print a print_cl r
|
||||||
|
|
||||||
let print_cnf cnf =
|
let print_lcl l =
|
||||||
List.iter (fun c -> Format.fprintf std "%a@\n" print_cl c) cnf
|
List.iter (fun c -> Format.fprintf std "%a@\n" print_cl c) l
|
||||||
|
|
||||||
|
let print_lclause l =
|
||||||
|
List.iter (fun c -> Format.fprintf std "%a@\n" S.print_clause c) l
|
||||||
|
|
||||||
(* Arguments parsing *)
|
(* Arguments parsing *)
|
||||||
let file = ref ""
|
let file = ref ""
|
||||||
|
|
@ -98,6 +101,7 @@ let p_cnf = ref false
|
||||||
let p_assign = ref false
|
let p_assign = ref false
|
||||||
let p_proof_check = ref false
|
let p_proof_check = ref false
|
||||||
let p_proof_print = ref false
|
let p_proof_print = ref false
|
||||||
|
let p_unsat_core = ref false
|
||||||
let time_limit = ref 300.
|
let time_limit = ref 300.
|
||||||
let size_limit = ref 1000_000_000.
|
let size_limit = ref 1000_000_000.
|
||||||
|
|
||||||
|
|
@ -150,6 +154,8 @@ let argspec = Arg.align [
|
||||||
"<s>[kMGT] Sets the size limit for the sat solver";
|
"<s>[kMGT] Sets the size limit for the sat solver";
|
||||||
"-time", Arg.String (int_arg time_limit),
|
"-time", Arg.String (int_arg time_limit),
|
||||||
"<t>[smhd] Sets the time limit for the sat solver";
|
"<t>[smhd] Sets the time limit for the sat solver";
|
||||||
|
"-u", Arg.Set p_unsat_core,
|
||||||
|
" Prints the unsat-core explanation of the unsat proof";
|
||||||
"-v", Arg.Int (fun i -> Log.set_debug i),
|
"-v", Arg.Int (fun i -> Log.set_debug i),
|
||||||
"<lvl> Sets the debug verbose level";
|
"<lvl> Sets the debug verbose level";
|
||||||
]
|
]
|
||||||
|
|
@ -179,7 +185,7 @@ let main () =
|
||||||
(* Interesting stuff happening *)
|
(* Interesting stuff happening *)
|
||||||
let cnf = get_cnf () in
|
let cnf = get_cnf () in
|
||||||
if !p_cnf then
|
if !p_cnf then
|
||||||
print_cnf cnf;
|
print_lcl cnf;
|
||||||
S.assume cnf;
|
S.assume cnf;
|
||||||
match S.solve () with
|
match S.solve () with
|
||||||
| S.Sat ->
|
| S.Sat ->
|
||||||
|
|
@ -190,7 +196,9 @@ let main () =
|
||||||
print "Unsat";
|
print "Unsat";
|
||||||
if !p_proof_check then begin
|
if !p_proof_check then begin
|
||||||
let p = S.get_proof () in
|
let p = S.get_proof () in
|
||||||
print_proof p
|
print_proof p;
|
||||||
|
if !p_unsat_core then
|
||||||
|
print_lclause (S.unsat_core p)
|
||||||
end
|
end
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue