mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 11:15:43 -05:00
wip: feat: start cdsat solver
This commit is contained in:
parent
4a5ccffc7a
commit
cd9aa883b2
9 changed files with 209 additions and 0 deletions
106
src/cdsat/TVar.ml
Normal file
106
src/cdsat/TVar.ml
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
type t = int
|
||||||
|
type var = t
|
||||||
|
|
||||||
|
let pp = Fmt.int
|
||||||
|
|
||||||
|
module Vec_of = Veci
|
||||||
|
|
||||||
|
(* TODO: GC API, + reuse existing slots that have been GC'd at the
|
||||||
|
next [new_var_] allocation *)
|
||||||
|
|
||||||
|
type store = {
|
||||||
|
tst: Term.store;
|
||||||
|
of_term: t Term.Weak_map.t;
|
||||||
|
term: Term.t Vec.t;
|
||||||
|
level: Veci.t;
|
||||||
|
value: Value.t option Vec.t;
|
||||||
|
reason: reason Vec.t;
|
||||||
|
has_value: Bitvec.t;
|
||||||
|
new_vars: Vec_of.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
and reason =
|
||||||
|
| Decide
|
||||||
|
| Propagate of { level: int; hyps: Vec_of.t; proof: Sidekick_proof.step_id }
|
||||||
|
|
||||||
|
(* create a new variable *)
|
||||||
|
let new_var_ (self : store) ~term:(term_for_v : Term.t) () : t =
|
||||||
|
let v : t = Vec.size self.term in
|
||||||
|
let { tst = _; of_term = _; term; level; value; reason; has_value; new_vars }
|
||||||
|
=
|
||||||
|
self
|
||||||
|
in
|
||||||
|
Vec.push term term_for_v;
|
||||||
|
Veci.push level (-1);
|
||||||
|
Vec.push value None;
|
||||||
|
Vec.push reason Decide;
|
||||||
|
(* fake *)
|
||||||
|
Bitvec.ensure_size has_value (v + 1);
|
||||||
|
Bitvec.set has_value v false;
|
||||||
|
Vec_of.push new_vars v;
|
||||||
|
v
|
||||||
|
|
||||||
|
let of_term (self : store) (t : Term.t) : t =
|
||||||
|
match Term.Weak_map.find_opt self.of_term t with
|
||||||
|
| Some v -> v
|
||||||
|
| None ->
|
||||||
|
let v = new_var_ self ~term:t () in
|
||||||
|
Term.Weak_map.add self.of_term t v;
|
||||||
|
(* TODO: map sub-terms to variables. Perhaps preprocess-like hooks that
|
||||||
|
will allow the variable to be properly defined in one theory? *)
|
||||||
|
v
|
||||||
|
|
||||||
|
let has_value (self : store) (v : t) : bool = Bitvec.get self.has_value v
|
||||||
|
let level (self : store) (v : t) : int = Veci.get self.level v
|
||||||
|
let value (self : store) (v : t) : _ option = Vec.get self.value v
|
||||||
|
let term (self : store) (v : t) : Term.t = Vec.get self.term v
|
||||||
|
let reason (self : store) (v : t) : reason = Vec.get self.reason v
|
||||||
|
|
||||||
|
let pop_new_var self : _ option =
|
||||||
|
if Vec_of.is_empty self.new_vars then
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some (Vec_of.pop self.new_vars)
|
||||||
|
|
||||||
|
module Reason = struct
|
||||||
|
type t = reason =
|
||||||
|
| Decide
|
||||||
|
| Propagate of { level: int; hyps: Vec_of.t; proof: Sidekick_proof.step_id }
|
||||||
|
|
||||||
|
let pp out (self : t) : unit =
|
||||||
|
match self with
|
||||||
|
| Decide -> Fmt.string out "decide"
|
||||||
|
| Propagate { level; hyps; proof = _ } ->
|
||||||
|
Fmt.fprintf out "(@[propagate[lvl=%d]@ :n-hyps %d@])" level
|
||||||
|
(Vec_of.size hyps)
|
||||||
|
|
||||||
|
let decide : t = Decide
|
||||||
|
|
||||||
|
let[@inline] propagate_ level v proof : t =
|
||||||
|
Propagate { level; hyps = v; proof }
|
||||||
|
|
||||||
|
let propagate_v store v proof : t =
|
||||||
|
let level = Vec_of.fold_left (fun l v -> max l (level store v)) 0 v in
|
||||||
|
propagate_ level v proof
|
||||||
|
|
||||||
|
let propagate_l store l proof : t =
|
||||||
|
let v = Vec_of.create ~cap:(List.length l) () in
|
||||||
|
List.iter (Vec_of.push v) l;
|
||||||
|
propagate_v store v proof
|
||||||
|
end
|
||||||
|
|
||||||
|
module Store = struct
|
||||||
|
type t = store
|
||||||
|
|
||||||
|
let create tst : t =
|
||||||
|
{
|
||||||
|
tst;
|
||||||
|
of_term = Term.Weak_map.create 256;
|
||||||
|
reason = Vec.create ();
|
||||||
|
term = Vec.create ();
|
||||||
|
level = Veci.create ();
|
||||||
|
value = Vec.create ();
|
||||||
|
has_value = Bitvec.create ();
|
||||||
|
new_vars = Vec_of.create ();
|
||||||
|
}
|
||||||
|
end
|
||||||
52
src/cdsat/TVar.mli
Normal file
52
src/cdsat/TVar.mli
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
(** Variables.
|
||||||
|
|
||||||
|
A variable is a term in the finite basis for CDSAT. It must be assigned
|
||||||
|
a value before the solver can answer "sat".
|
||||||
|
*)
|
||||||
|
|
||||||
|
type t = private int
|
||||||
|
type var = t
|
||||||
|
|
||||||
|
(** Store of variables *)
|
||||||
|
module Store : sig
|
||||||
|
type t
|
||||||
|
|
||||||
|
val create : Term.store -> t
|
||||||
|
(** Create a new store *)
|
||||||
|
end
|
||||||
|
|
||||||
|
module Vec_of : Vec_sig.S with type elt := t
|
||||||
|
(** Vector of variables *)
|
||||||
|
|
||||||
|
type store = Store.t
|
||||||
|
|
||||||
|
(** Reason for assignment *)
|
||||||
|
module Reason : sig
|
||||||
|
type t =
|
||||||
|
| Decide
|
||||||
|
| Propagate of { level: int; hyps: Vec_of.t; proof: Sidekick_proof.step_id }
|
||||||
|
|
||||||
|
include Sidekick_sigs.PRINT with type t := t
|
||||||
|
|
||||||
|
val decide : t
|
||||||
|
val propagate_v : store -> Vec_of.t -> Sidekick_proof.step_id -> t
|
||||||
|
val propagate_l : store -> var list -> Sidekick_proof.step_id -> t
|
||||||
|
end
|
||||||
|
|
||||||
|
val of_term : store -> Term.t -> t
|
||||||
|
(** Obtain a variable for this term. *)
|
||||||
|
|
||||||
|
val term : store -> t -> Term.t
|
||||||
|
(** Term for this variable *)
|
||||||
|
|
||||||
|
val has_value : store -> t -> bool
|
||||||
|
(** Does the variable have a value in the current assignment? *)
|
||||||
|
|
||||||
|
val level : store -> t -> int
|
||||||
|
(** Level of the current assignment, or [-1] *)
|
||||||
|
|
||||||
|
val value : store -> t -> Value.t option
|
||||||
|
(** Value in the current assignment *)
|
||||||
|
|
||||||
|
val pop_new_var : store -> t option
|
||||||
|
(** Pop a new variable if any, or return [None] *)
|
||||||
8
src/cdsat/dune
Normal file
8
src/cdsat/dune
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
(library
|
||||||
|
(name sidekick_cdsat)
|
||||||
|
(public_name sidekick.cdsat)
|
||||||
|
(synopsis "CDSAT-based SMT core for sidekick")
|
||||||
|
(flags :standard -open Sidekick_util -open Sidekick_core)
|
||||||
|
(private_modules types_)
|
||||||
|
(libraries containers sidekick.util sidekick.core sidekick.sigs
|
||||||
|
sidekick.proof sidekick.abstract-solver))
|
||||||
6
src/cdsat/sidekick_cdsat.ml
Normal file
6
src/cdsat/sidekick_cdsat.ml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(** CDSAT core *)
|
||||||
|
|
||||||
|
module Trail = Trail
|
||||||
|
module TVar = TVar
|
||||||
|
module Reason = TVar.Reason
|
||||||
|
module Value = Value
|
||||||
22
src/cdsat/trail.ml
Normal file
22
src/cdsat/trail.ml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
module VVec = TVar.Vec_of
|
||||||
|
|
||||||
|
type t = { vars: VVec.t; levels: Veci.t }
|
||||||
|
|
||||||
|
let create () : t = { vars = VVec.create (); levels = Veci.create () }
|
||||||
|
|
||||||
|
let[@inline] push_assignment (self : t) (v : TVar.t) : unit =
|
||||||
|
VVec.push self.vars v
|
||||||
|
|
||||||
|
let[@inline] var_at (self : t) (i : int) : TVar.t = VVec.get self.vars i
|
||||||
|
let[@inline] n_levels self = Veci.size self.levels
|
||||||
|
let push_level (self : t) : unit = Veci.push self.levels (VVec.size self.vars)
|
||||||
|
|
||||||
|
let pop_levels (self : t) (n : int) ~f : unit =
|
||||||
|
if n <= n_levels self then (
|
||||||
|
let idx = Veci.get self.levels n in
|
||||||
|
Veci.shrink self.levels n;
|
||||||
|
while VVec.size self.vars > idx do
|
||||||
|
let elt = VVec.pop self.vars in
|
||||||
|
f elt
|
||||||
|
done
|
||||||
|
)
|
||||||
9
src/cdsat/trail.mli
Normal file
9
src/cdsat/trail.mli
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
(** Trail *)
|
||||||
|
|
||||||
|
type t
|
||||||
|
|
||||||
|
val create : unit -> t
|
||||||
|
val var_at : t -> int -> TVar.t
|
||||||
|
val push_assignment : t -> TVar.t -> unit
|
||||||
|
|
||||||
|
include Sidekick_sigs.BACKTRACKABLE0_CB with type t := t and type elt := TVar.t
|
||||||
0
src/cdsat/types_.ml
Normal file
0
src/cdsat/types_.ml
Normal file
1
src/cdsat/value.ml
Normal file
1
src/cdsat/value.ml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
include Term
|
||||||
5
src/cdsat/value.mli
Normal file
5
src/cdsat/value.mli
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
(** Values *)
|
||||||
|
|
||||||
|
type t = Term.t
|
||||||
|
|
||||||
|
include Sidekick_sigs.EQ_ORD_HASH_PRINT with type t := t
|
||||||
Loading…
Add table
Reference in a new issue