sidekick/src/sat/solver.mli
2022-07-30 20:27:47 -04:00

176 lines
5 KiB
OCaml

(** The external interface implemented by SAT solvers. *)
(*
MSAT is free software, using the Apache license, see file LICENSE
Copyright 2016 Guillaume Bury
Copyright 2016 Simon Cruanes
*)
open Sidekick_core
open Sigs
type clause
type plugin = Sigs.plugin
type solver
(** The main solver type. *)
type store
(** Stores atoms, clauses, etc. *)
module Clause : sig
type t = clause
val equal : t -> t -> bool
module Tbl : Hashtbl.S with type key = t
val pp : store -> t Fmt.printer
(** Print the clause *)
val short_name : store -> t -> string
(** Short name for a clause. Unspecified *)
val n_atoms : store -> t -> int
val lits_iter : store -> t -> Lit.t Iter.t
(** Literals of a clause *)
val lits_a : store -> t -> Lit.t array
(** Atoms of a clause *)
val lits_l : store -> t -> Lit.t list
(** List of atoms of a clause *)
end
(** {2 Main Solver Type} *)
type t = solver
(** Main solver type, containing all state for solving. *)
val store : t -> store
(** Store for the solver *)
val stat : t -> Stat.t
(** Statistics *)
val proof : t -> Proof_trace.t
(** Access the inner proof *)
val on_conflict : t -> (Clause.t, unit) Event.t
val on_decision : t -> (Lit.t, unit) Event.t
val on_learnt : t -> (Clause.t, unit) Event.t
val on_gc : t -> (Lit.t array, unit) Event.t
(** {2 Types} *)
(** Result type for the solver *)
type res =
| Sat of sat_state (** Returned when the solver reaches SAT, with a model *)
| Unsat of clause unsat_state
(** Returned when the solver reaches UNSAT, with a proof *)
exception UndecidedLit
(** Exception raised by the evaluating functions when a literal
has not yet been assigned a value. *)
(** {2 Base operations} *)
val assume : t -> Lit.t list list -> unit
(** Add the list of clauses to the current set of assumptions.
Modifies the sat solver state in place. *)
val add_clause : t -> Lit.t list -> Proof_step.id -> unit
(** Lower level addition of clauses *)
val add_clause_a : t -> Lit.t array -> Proof_step.id -> unit
(** Lower level addition of clauses *)
val add_input_clause : t -> Lit.t list -> unit
(** Like {!add_clause} but with the justification of being an input clause *)
val add_input_clause_a : t -> Lit.t array -> unit
(** Like {!add_clause_a} but with justification of being an input clause *)
(** {2 Solving} *)
val solve : ?on_progress:(unit -> unit) -> ?assumptions:Lit.t list -> t -> res
(** Try and solves the current set of clauses.
@param assumptions additional atomic assumptions to be temporarily added.
The assumptions are just used for this call to [solve], they are
not saved in the solver's state.
@param on_progress regularly called during solving.
Can raise {!Resource_exhausted}
to stop solving.
@raise Resource_exhausted if the on_progress handler raised it to stop
*)
(** {2 Evaluating and adding literals} *)
val add_lit : t -> ?default_pol:bool -> Lit.t -> unit
(** Ensure the SAT solver handles this particular literal, ie add
a boolean variable for it if it's not already there. *)
val set_default_pol : t -> Lit.t -> bool -> unit
(** Set default polarity for the given boolean variable.
Sign of the literal is ignored. *)
val true_at_level0 : t -> Lit.t -> bool
(** [true_at_level0 a] returns [true] if [a] was proved at level0, i.e.
it must hold in all models *)
val eval_lit : t -> Lit.t -> lbool
(** Evaluate atom in current state *)
(** {2 Assumption stack} *)
val push_assumption : t -> Lit.t -> unit
(** Pushes an assumption onto the assumption stack. It will remain
there until it's pop'd by {!pop_assumptions}. *)
val pop_assumptions : t -> int -> unit
(** [pop_assumptions solver n] removes [n] assumptions from the stack.
It removes the assumptions that were the most
recently added via {!push_assumptions}. *)
(** Result returned by {!check_sat_propagations_only} *)
type propagation_result =
| PR_sat
| PR_conflict of { backtracked: int }
| PR_unsat of clause unsat_state
val check_sat_propagations_only :
?assumptions:Lit.t list -> t -> propagation_result
(** [check_sat_propagations_only solver] uses the added clauses
and local assumptions (using {!push_assumptions} and [assumptions])
to quickly assess whether the context is satisfiable.
It is not complete; calling {!solve} is required to get an accurate
result.
@returns either [Ok()] if propagation yielded no conflict, or [Error c]
if a conflict clause [c] was found. *)
(** {2 Initialization} *)
val plugin_cdcl_t : (module THEORY_CDCL_T) -> (module PLUGIN)
val create :
?stat:Stat.t ->
?size:[ `Tiny | `Small | `Big ] ->
proof:Proof_trace.t ->
plugin ->
t
(** Create new solver
@param theory the theory
@param the proof
@param size the initial size of internal data structures. The bigger,
the faster, but also the more RAM it uses. *)
val plugin_pure_sat : plugin
val create_pure_sat :
?stat:Stat.t ->
?size:[ `Tiny | `Small | `Big ] ->
proof:Proof_trace.t ->
unit ->
t