mirror of
https://github.com/c-cube/sidekick.git
synced 2026-01-23 01:46:43 -05:00
Merge branch 'wip-fix-lra' into wip-lra-simplex-unsat-core
This commit is contained in:
commit
14bb5898f0
12 changed files with 229 additions and 42 deletions
3
Makefile
3
Makefile
|
|
@ -44,6 +44,9 @@ $(TESTTOOL)-smt-QF_DT: snapshots
|
|||
$(TESTTOOL)-smt-QF_LRA: snapshots
|
||||
$(TESTTOOL) run $(TESTOPTS) \
|
||||
--csv snapshots/smt-QF_LRA-$(DATE).csv --task sidekick-smt-nodir tests/QF_LRA
|
||||
$(TESTTOOL)-smt-QF_UFLRA: snapshots
|
||||
$(TESTTOOL) run $(TESTOPTS) \
|
||||
--csv snapshots/smt-QF_UFLRA-$(DATE).csv --task sidekick-smt-nodir tests/QF_UFLRA
|
||||
|
||||
install: build-install
|
||||
@dune install
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ depends: [
|
|||
"containers" { >= "3.0" & < "4.0" }
|
||||
"iter"
|
||||
"zarith"
|
||||
"smtlib-utils" { >= "0.1" & < "0.2" }
|
||||
"smtlib-utils" { >= "0.1" & < "0.3" }
|
||||
"sidekick" { = version }
|
||||
"menhir"
|
||||
"msat" { >= "0.8" < "0.9" }
|
||||
|
|
|
|||
|
|
@ -914,6 +914,8 @@ end = struct
|
|||
| Eq (a,b) -> C.Eq (a, b)
|
||||
| Not u -> C.Not u
|
||||
| Ite (a,b,c) -> C.If (a,b,c)
|
||||
| LRA (LRA_pred (Eq, a, b)) ->
|
||||
C.Eq (a,b) (* need congruence closure on this one, for theory combination *)
|
||||
| LRA _ -> C.Opaque t (* no congruence here *)
|
||||
|
||||
module As_key = struct
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ module type ARG = sig
|
|||
|
||||
val ty_lra : S.T.Term.state -> ty
|
||||
|
||||
val has_ty_real : term -> bool
|
||||
(** Does this term have the type [Real] *)
|
||||
|
||||
module Gensym : sig
|
||||
type t
|
||||
|
||||
|
|
@ -73,18 +76,37 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
module T = A.S.T.Term
|
||||
module Lit = A.S.Solver_internal.Lit
|
||||
module SI = A.S.Solver_internal
|
||||
module N = A.S.Solver_internal.CC.N
|
||||
|
||||
module Tag = struct
|
||||
type t =
|
||||
| By_def
|
||||
| Lit of Lit.t
|
||||
| CC_eq of N.t * N.t
|
||||
|
||||
let pp out = function
|
||||
| By_def -> Fmt.string out "<bydef>"
|
||||
| Lit l -> Fmt.fprintf out "(@[lit %a@])" Lit.pp l
|
||||
| CC_eq (n1,n2) -> Fmt.fprintf out "(@[cc-eq@ %a@ %a@])" N.pp n1 N.pp n2
|
||||
|
||||
let to_lits si = function
|
||||
| By_def -> []
|
||||
| Lit l -> [l]
|
||||
| CC_eq (n1,n2) ->
|
||||
SI.CC.explain_eq (SI.cc si) n1 n2
|
||||
end
|
||||
|
||||
module SimpVar
|
||||
: Linear_expr.VAR_GEN
|
||||
with type t = A.term
|
||||
and type Fresh.t = A.Gensym.t
|
||||
and type lit = Lit.t
|
||||
and type lit = Tag.t
|
||||
= struct
|
||||
type t = A.term
|
||||
let pp = A.S.T.Term.pp
|
||||
let compare = A.S.T.Term.compare
|
||||
type lit = Lit.t
|
||||
let pp_lit = Lit.pp
|
||||
type lit = Tag.t
|
||||
let pp_lit = Tag.pp
|
||||
module Fresh = struct
|
||||
type t = A.Gensym.t
|
||||
let copy = A.Gensym.copy
|
||||
|
|
@ -101,14 +123,17 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
module LE = SimpSolver.L.Expr
|
||||
module LConstr = SimpSolver.L.Constr
|
||||
|
||||
type proxy = T.t
|
||||
type state = {
|
||||
tst: T.state;
|
||||
simps: T.t T.Tbl.t; (* cache *)
|
||||
gensym: A.Gensym.t;
|
||||
neq_encoded: unit T.Tbl.t;
|
||||
(* if [a != b] asserted and not in this table, add clause [a = b \/ a<b \/ a>b] *)
|
||||
mutable t_defs: (T.t * LE.t) list; (* term definitions *)
|
||||
pred_defs: (pred * LE.t * LE.t) T.Tbl.t; (* predicate definitions *)
|
||||
needs_th_combination: LE.t T.Tbl.t; (* terms that require theory combination *)
|
||||
t_defs: LE.t T.Tbl.t; (* term definitions *)
|
||||
pred_defs: (pred * LE.t * LE.t * T.t * T.t) T.Tbl.t; (* predicate definitions *)
|
||||
local_eqs: (N.t * N.t) Backtrack_stack.t; (* inferred by the congruence closure *)
|
||||
}
|
||||
|
||||
let create tst : state =
|
||||
|
|
@ -116,10 +141,20 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
simps=T.Tbl.create 128;
|
||||
gensym=A.Gensym.create tst;
|
||||
neq_encoded=T.Tbl.create 16;
|
||||
t_defs=[];
|
||||
needs_th_combination=T.Tbl.create 8;
|
||||
t_defs=T.Tbl.create 8;
|
||||
pred_defs=T.Tbl.create 16;
|
||||
local_eqs = Backtrack_stack.create();
|
||||
}
|
||||
|
||||
let push_level self =
|
||||
Backtrack_stack.push_level self.local_eqs;
|
||||
()
|
||||
|
||||
let pop_levels self n =
|
||||
Backtrack_stack.pop_levels self.local_eqs n ~f:(fun _ -> ());
|
||||
()
|
||||
|
||||
(* FIXME
|
||||
let simplify (self:state) (simp:SI.Simplify.t) (t:T.t) : T.t option =
|
||||
let tst = self.tst in
|
||||
|
|
@ -191,73 +226,118 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
LE.( n * t )
|
||||
| LRA_const q -> LE.of_const q
|
||||
|
||||
let as_linexp_id = as_linexp ~f:CCFun.id
|
||||
|
||||
(* TODO: keep the linexps until they're asserted;
|
||||
TODO: but use simplification in preprocess
|
||||
*)
|
||||
|
||||
(* preprocess linear expressions away *)
|
||||
let preproc_lra self si ~recurse ~mk_lit:_ ~add_clause:_ (t:T.t) : T.t option =
|
||||
let preproc_lra (self:state) si ~recurse ~mk_lit:_ ~add_clause:_ (t:T.t) : T.t option =
|
||||
Log.debugf 50 (fun k->k "lra.preprocess %a" T.pp t);
|
||||
let _tst = SI.tst si in
|
||||
let tst = SI.tst si in
|
||||
match A.view_as_lra t with
|
||||
| LRA_pred ((Eq|Neq) as pred, t1, t2) ->
|
||||
(* keep equality as is, needed for congruence closure *)
|
||||
let t1 = recurse t1 in
|
||||
let t2 = recurse t2 in
|
||||
let u = A.mk_lra tst (LRA_pred (pred, t1, t2)) in
|
||||
if T.equal t u then None else Some u
|
||||
| LRA_pred (pred, t1, t2) ->
|
||||
let l1 = as_linexp ~f:recurse t1 in
|
||||
let l2 = as_linexp ~f:recurse t2 in
|
||||
let proxy = fresh_term self ~pre:"_pred_lra_" Ty.bool in
|
||||
T.Tbl.add self.pred_defs proxy (pred, l1, l2);
|
||||
T.Tbl.add self.pred_defs proxy (pred, l1, l2, t1, t2);
|
||||
Log.debugf 5 (fun k->k"@[<hv2>lra.preprocess.step %a@ :into %a@ :def %a@]"
|
||||
T.pp t T.pp proxy pp_pred_def (pred,l1,l2));
|
||||
Some proxy
|
||||
| LRA_op _ | LRA_mult _ ->
|
||||
let le = as_linexp ~f:recurse t in
|
||||
let proxy = fresh_term self ~pre:"_e_lra_" (T.ty t) in
|
||||
self.t_defs <- (proxy, le) :: self.t_defs;
|
||||
T.Tbl.add self.t_defs proxy le;
|
||||
T.Tbl.add self.needs_th_combination proxy le;
|
||||
Log.debugf 5 (fun k->k"@[<hv2>lra.preprocess.step %a@ :into %a@ :def %a@]"
|
||||
T.pp t T.pp proxy LE.pp le);
|
||||
Some proxy
|
||||
| LRA_other t when A.has_ty_real t ->
|
||||
let le = LE.monomial1 t in
|
||||
T.Tbl.replace self.needs_th_combination t le;
|
||||
None
|
||||
| LRA_const _ | LRA_other _ -> None
|
||||
|
||||
(* partial check: just ensure [a != b] triggers the clause
|
||||
(* ensure that [a != b] triggers the clause
|
||||
[a=b \/ a<b \/ a>b] *)
|
||||
let partial_check_ (self:state) si (acts:SI.actions) (trail:_ Iter.t) : unit =
|
||||
let encode_neq self si acts trail : unit =
|
||||
let tst = self.tst in
|
||||
begin
|
||||
trail
|
||||
|> Iter.filter (fun lit -> not (Lit.sign lit))
|
||||
|> Iter.filter_map
|
||||
(fun lit ->
|
||||
let t = Lit.term lit in
|
||||
match A.view_as_lra t with
|
||||
| LRA_pred (Eq, a, b) when not (T.Tbl.mem self.neq_encoded t) ->
|
||||
Some (lit, a,b)
|
||||
| _ -> None)
|
||||
Log.debugf 50 (fun k->k "@[lra: check lit %a@ :t %a@ :sign %B@]"
|
||||
Lit.pp lit T.pp t (Lit.sign lit));
|
||||
|
||||
let check_pred pred a b =
|
||||
let pred = if Lit.sign lit then pred else Predicate.neg pred in
|
||||
Log.debugf 50 (fun k->k "pred = `%s`" (Predicate.to_string pred));
|
||||
if pred = Neq && not (T.Tbl.mem self.neq_encoded t) then (
|
||||
Some (lit, a, b)
|
||||
) else None
|
||||
in
|
||||
|
||||
begin match T.Tbl.find self.pred_defs t with
|
||||
| (pred, _, _, ta, tb) -> check_pred pred ta tb
|
||||
| exception Not_found ->
|
||||
begin match A.view_as_lra t with
|
||||
| LRA_pred (pred, a, b) -> check_pred pred a b
|
||||
| _ -> None
|
||||
end
|
||||
end)
|
||||
|> Iter.iter
|
||||
(fun (lit,a,b) ->
|
||||
Log.debugf 50 (fun k->k "encode neq in %a" Lit.pp lit);
|
||||
let c = [
|
||||
Lit.abs lit;
|
||||
Lit.neg lit;
|
||||
SI.mk_lit si acts (A.mk_lra tst (LRA_pred (Lt, a, b)));
|
||||
SI.mk_lit si acts (A.mk_lra tst (LRA_pred (Lt, b, a)));
|
||||
] in
|
||||
SI.add_clause_permanent si acts c;
|
||||
T.Tbl.add self.neq_encoded (Lit.term lit) ();
|
||||
T.Tbl.add self.neq_encoded (Lit.term (Lit.abs lit)) ();
|
||||
)
|
||||
end
|
||||
|
||||
let dedup_lits lits : _ list =
|
||||
let module LTbl = CCHashtbl.Make(Lit) in
|
||||
let tbl = LTbl.create 16 in
|
||||
List.iter (fun l -> LTbl.replace tbl l ()) lits;
|
||||
LTbl.keys_list tbl
|
||||
|
||||
module Q_map = CCMap.Make(Q)
|
||||
|
||||
let final_check_ (self:state) si (acts:SI.actions) (trail:_ Iter.t) : unit =
|
||||
Log.debug 5 "(th-lra.final-check)";
|
||||
let simplex = SimpSolver.create self.gensym in
|
||||
encode_neq self si acts trail;
|
||||
(* first, add definitions *)
|
||||
begin
|
||||
List.iter
|
||||
(fun (t,le) ->
|
||||
T.Tbl.iter
|
||||
(fun t le ->
|
||||
let open LE.Infix in
|
||||
let le = le - LE.monomial1 t in
|
||||
let c = LConstr.eq0 le in
|
||||
let lit = assert false (* TODO: find the lit *) in
|
||||
let lit = Tag.By_def in
|
||||
SimpSolver.add_constr simplex c lit
|
||||
)
|
||||
)
|
||||
self.t_defs
|
||||
end;
|
||||
(* add congruence closure equalities *)
|
||||
Backtrack_stack.iter self.local_eqs
|
||||
~f:(fun (n1,n2) ->
|
||||
let t1 = N.term n1 |> as_linexp_id in
|
||||
let t2 = N.term n2 |> as_linexp_id in
|
||||
let c = LConstr.eq0 LE.(t1 - t2) in
|
||||
let lit = Tag.CC_eq (n1,n2) in
|
||||
SimpSolver.add_constr simplex c lit);
|
||||
(* add trail *)
|
||||
begin
|
||||
trail
|
||||
|
|
@ -265,26 +345,78 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
(fun lit ->
|
||||
let sign = Lit.sign lit in
|
||||
let t = Lit.term lit in
|
||||
let assert_pred pred a b =
|
||||
let pred = if sign then pred else Predicate.neg pred in
|
||||
if pred = Neq then (
|
||||
Log.debugf 50 (fun k->k "(@[LRA.skip-neq@ :in %a@])" T.pp t);
|
||||
) else (
|
||||
let c = LConstr.of_expr LE.(a-b) pred in
|
||||
SimpSolver.add_constr simplex c (Tag.Lit lit);
|
||||
)
|
||||
in
|
||||
begin match T.Tbl.find self.pred_defs t with
|
||||
| exception Not_found -> ()
|
||||
| (pred, a, b) ->
|
||||
(* FIXME: generic negation+printer in Linear_expr_intf;
|
||||
actually move predicates to their own module *)
|
||||
let pred = if sign then pred else Predicate.neg pred in
|
||||
if pred = Neq then (
|
||||
Log.debugf 50 (fun k->k "skip neq in %a" T.pp t);
|
||||
) else (
|
||||
(* TODO: tag *)
|
||||
let c = LConstr.of_expr LE.(a-b) pred in
|
||||
SimpSolver.add_constr simplex c lit;
|
||||
)
|
||||
| (pred, a, b, _, _) -> assert_pred pred a b
|
||||
| exception Not_found ->
|
||||
begin match A.view_as_lra t with
|
||||
| LRA_pred (pred, a, b) ->
|
||||
let a = try T.Tbl.find self.t_defs a with _ -> as_linexp_id a in
|
||||
let b = try T.Tbl.find self.t_defs b with _ -> as_linexp_id b in
|
||||
assert_pred pred a b
|
||||
| _ -> ()
|
||||
end
|
||||
end)
|
||||
end;
|
||||
Log.debug 5 "lra: call arith solver";
|
||||
begin match SimpSolver.solve simplex with
|
||||
| SimpSolver.Solution _m ->
|
||||
Log.debug 5 "lra: solver returns SAT";
|
||||
() (* TODO: get a model + model combination *)
|
||||
Log.debugf 50
|
||||
(fun k->k "(@[LRA.needs-th-combination:@ %a@])"
|
||||
(Util.pp_iter @@ Fmt.within "`" "`" T.pp) (T.Tbl.keys self.needs_th_combination));
|
||||
(* FIXME: theory combination
|
||||
let lazy model = model in
|
||||
Log.debugf 30 (fun k->k "(@[LRA.model@ %a@])" FM_A.pp_model model);
|
||||
|
||||
(* theory combination: for [t1,t2] terms in [self.needs_th_combination]
|
||||
that have same value, but are not provably equal, push
|
||||
decision [t1=t2] into the SAT solver. *)
|
||||
begin
|
||||
let by_val: T.t list Q_map.t =
|
||||
T.Tbl.to_iter self.needs_th_combination
|
||||
|> Iter.map (fun (t,le) -> FM_A.eval_model model le, t)
|
||||
|> Iter.fold
|
||||
(fun m (q,t) ->
|
||||
let l = Q_map.get_or ~default:[] q m in
|
||||
Q_map.add q (t::l) m)
|
||||
Q_map.empty
|
||||
in
|
||||
Q_map.iter
|
||||
(fun _q ts ->
|
||||
begin match ts with
|
||||
| [] | [_] -> ()
|
||||
| ts ->
|
||||
(* several terms! see if they are already equal *)
|
||||
CCList.diagonal ts
|
||||
|> List.iter
|
||||
(fun (t1,t2) ->
|
||||
Log.debugf 50
|
||||
(fun k->k "(@[LRA.th-comb.check-pair[val=%a]@ %a@ %a@])"
|
||||
Q.pp_print _q T.pp t1 T.pp t2);
|
||||
(* FIXME: we need these equalities to be considered
|
||||
by the congruence closure *)
|
||||
if not (SI.cc_are_equal si t1 t2) then (
|
||||
Log.debug 50 "LRA.th-comb.must-decide-equal";
|
||||
let t = A.mk_lra (SI.tst si) (LRA_pred (Eq, t1, t2)) in
|
||||
let lit = SI.mk_lit si acts t in
|
||||
SI.push_decision si acts lit
|
||||
)
|
||||
)
|
||||
end)
|
||||
by_val;
|
||||
()
|
||||
end;
|
||||
*)
|
||||
()
|
||||
| SimpSolver.Unsatisfiable cert ->
|
||||
let unsat_core =
|
||||
match SimpSolver.check_cert simplex cert with
|
||||
|
|
@ -292,9 +424,15 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
| _ -> assert false (* some kind of fatal error ? *)
|
||||
in
|
||||
Log.debugf 5 (fun k->k"lra: solver returns UNSAT@ with cert %a"
|
||||
(Fmt.Dump.list Lit.pp) unsat_core);
|
||||
(Fmt.Dump.list Tag.pp) unsat_core);
|
||||
(* TODO: produce and store a proper LRA resolution proof *)
|
||||
let confl = List.rev_map Lit.neg unsat_core in
|
||||
let confl =
|
||||
unsat_core
|
||||
|> Iter.of_list
|
||||
|> Iter.flat_map_l (fun tag -> Tag.to_lits si tag)
|
||||
|> Iter.map Lit.neg
|
||||
|> Iter.to_rev_list
|
||||
in
|
||||
SI.raise_conflict si acts confl SI.P.default
|
||||
end;
|
||||
()
|
||||
|
|
@ -304,8 +442,12 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
let st = create (SI.tst si) in
|
||||
(* TODO SI.add_simplifier si (simplify st); *)
|
||||
SI.add_preprocess si (preproc_lra st);
|
||||
SI.on_partial_check si (partial_check_ st);
|
||||
SI.on_final_check si (final_check_ st);
|
||||
SI.on_cc_post_merge si
|
||||
(fun _ _ n1 n2 ->
|
||||
if A.has_ty_real (N.term n1) then (
|
||||
Backtrack_stack.push st.local_eqs (n1, n2)
|
||||
));
|
||||
(* SI.add_preprocess si (cnf st); *)
|
||||
(* TODO: theory combination *)
|
||||
st
|
||||
|
|
@ -313,6 +455,6 @@ module Make(A : ARG) : S with module A = A = struct
|
|||
let theory =
|
||||
A.S.mk_theory
|
||||
~name:"th-lra"
|
||||
~create_and_setup
|
||||
~create_and_setup ~push_level ~pop_levels
|
||||
()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -835,6 +835,10 @@ module Make (A: CC_ARG)
|
|||
let[@inline] merge_t cc t1 t2 expl =
|
||||
merge cc (add_term cc t1) (add_term cc t2) expl
|
||||
|
||||
let explain_eq cc n1 n2 : lit list =
|
||||
let th = ref true in
|
||||
explain_pair cc ~th [] n1 n2
|
||||
|
||||
let on_pre_merge cc f = cc.on_pre_merge <- f :: cc.on_pre_merge
|
||||
let on_post_merge cc f = cc.on_post_merge <- f :: cc.on_post_merge
|
||||
let on_new_term cc f = cc.on_new_term <- f :: cc.on_new_term
|
||||
|
|
|
|||
|
|
@ -280,6 +280,10 @@ module type CC_S = sig
|
|||
val assert_lits : t -> lit Iter.t -> unit
|
||||
(** Addition of many literals *)
|
||||
|
||||
val explain_eq : t -> N.t -> N.t -> lit list
|
||||
(** Explain why the two nodes are equal.
|
||||
Fails if they are not, in an unspecified way *)
|
||||
|
||||
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'a
|
||||
(** Raise a conflict with the given explanation
|
||||
it must be a theory tautology that [expl ==> absurd].
|
||||
|
|
@ -390,10 +394,19 @@ module type SOLVER_INTERNAL = sig
|
|||
(** {3 hooks for the theory} *)
|
||||
|
||||
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unit
|
||||
(** Propagate a literal for a reason. This is similar to asserting
|
||||
the clause [reason => lit], but more lightweight, and in a way
|
||||
that is backtrackable. *)
|
||||
|
||||
val raise_conflict : t -> actions -> lit list -> proof -> 'a
|
||||
(** Give a conflict clause to the solver *)
|
||||
|
||||
val push_decision : t -> actions -> lit -> unit
|
||||
(** Ask the SAT solver to decide the given literal in an extension of the
|
||||
current trail. This is useful for theory combination.
|
||||
If the SAT solver backtracks, this (potential) decision is removed
|
||||
and forgotten. *)
|
||||
|
||||
val propagate: t -> actions -> lit -> (unit -> lit list) -> unit
|
||||
(** Propagate a boolean using a unit clause.
|
||||
[expl => lit] must be a theory lemma, that is, a T-tautology *)
|
||||
|
|
@ -429,6 +442,9 @@ module type SOLVER_INTERNAL = sig
|
|||
val cc_find : t -> CC.N.t -> CC.N.t
|
||||
(** Find representative of the node *)
|
||||
|
||||
val cc_are_equal : t -> term -> term -> bool
|
||||
(** Are these two terms equal in the congruence closure? *)
|
||||
|
||||
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit
|
||||
(** Merge these two nodes in the congruence closure, given this explanation.
|
||||
It must be a theory tautology that [expl ==> n1 = n2].
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ let argspec = Arg.align [
|
|||
"--no-p", Arg.Clear p_progress, " no progress bar";
|
||||
"--size", Arg.String (int_arg size_limit), " <s>[kMGT] sets the size limit for the sat solver";
|
||||
"--time", Arg.String (int_arg time_limit), " <t>[smhd] sets the time limit for the sat solver";
|
||||
"-t", Arg.String (int_arg time_limit), " short for --time";
|
||||
"--version", Arg.Unit (fun () -> Printf.printf "version: %s\n%!" Sidekick_version.version; exit 0), " show version and exit";
|
||||
"-d", Arg.Int Msat.Log.set_debug, "<lvl> sets the debug verbose level";
|
||||
"--debug", Arg.Int Msat.Log.set_debug, "<lvl> sets the debug verbose level";
|
||||
|
|
|
|||
|
|
@ -202,6 +202,10 @@ module Make(A : ARG)
|
|||
|
||||
let add_preprocess self f = self.preprocess <- f :: self.preprocess
|
||||
|
||||
let push_decision (_self:t) (acts:actions) (lit:lit) : unit =
|
||||
let sign = Lit.sign lit in
|
||||
acts.Msat.acts_add_decision_lit (Lit.abs lit) sign
|
||||
|
||||
let[@inline] raise_conflict self acts c : 'a =
|
||||
Stat.incr self.count_conflict;
|
||||
acts.Msat.acts_raise_conflict c P.default
|
||||
|
|
@ -279,6 +283,10 @@ module Make(A : ARG)
|
|||
|
||||
let cc_add_term self t = CC.add_term (cc self) t
|
||||
let cc_find self n = CC.find (cc self) n
|
||||
let cc_are_equal self t1 t2 =
|
||||
let n1 = cc_add_term self t1 in
|
||||
let n2 = cc_add_term self t2 in
|
||||
N.equal (cc_find self n1) (cc_find self n2)
|
||||
let cc_merge self _acts n1 n2 e = CC.merge (cc self) n1 n2 e
|
||||
let cc_merge_t self acts t1 t2 e =
|
||||
cc_merge self acts (cc_add_term self t1) (cc_add_term self t2) e
|
||||
|
|
@ -578,7 +586,7 @@ module Make(A : ARG)
|
|||
|
||||
let add_clause (self:t) (c:Atom.t IArray.t) : unit =
|
||||
Stat.incr self.count_clause;
|
||||
Log.debugf 50 (fun k->k "add clause %a@." (Util.pp_iarray Atom.pp) c);
|
||||
Log.debugf 50 (fun k->k "(@[solver.add-clause@ %a@])" (Util.pp_iarray Atom.pp) c);
|
||||
Sat_solver.add_clause_a self.solver (c:> Atom.t array) P.default
|
||||
|
||||
let add_clause_l self c = add_clause self (IArray.of_list c)
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ module Th_lra = Sidekick_arith_lra.Make(struct
|
|||
| _ -> LRA_other t
|
||||
|
||||
let ty_lra _st = Ty.real
|
||||
let has_ty_real t = Ty.equal (T.ty t) Ty.real
|
||||
|
||||
module Gensym = struct
|
||||
type t = {
|
||||
|
|
|
|||
|
|
@ -280,6 +280,12 @@ let rec conv_term (ctx:Ctx.t) (t:PA.term) : T.t =
|
|||
| PA.Add, [a;b] -> T.lra ctx.tst (LRA_op (Plus, a, b))
|
||||
| PA.Add, (a::l) ->
|
||||
List.fold_left (fun a b -> T.lra ctx.tst (LRA_op (Plus,a,b))) a l
|
||||
| PA.Minus, [a] ->
|
||||
begin match t_as_q a with
|
||||
| Some a -> T.lra ctx.tst (LRA_const (Q.neg a))
|
||||
| None ->
|
||||
T.lra ctx.tst (LRA_op (Minus, T.lra ctx.tst (LRA_const Q.zero), a))
|
||||
end
|
||||
| PA.Minus, [a;b] -> T.lra ctx.tst (LRA_op (Minus, a, b))
|
||||
| PA.Minus, (a::l) ->
|
||||
List.fold_left (fun a b -> T.lra ctx.tst (LRA_op (Minus,a,b))) a l
|
||||
|
|
|
|||
|
|
@ -34,3 +34,5 @@ let pop_levels (self:_ t) (n:int) ~f : unit =
|
|||
done;
|
||||
Vec.shrink self.lvls new_lvl
|
||||
)
|
||||
|
||||
let iter ~f self = Vec.iter f self.vec
|
||||
|
|
|
|||
|
|
@ -19,3 +19,5 @@ val push_level : _ t -> unit
|
|||
|
||||
val pop_levels : 'a t -> int -> f:('a -> unit) -> unit
|
||||
(** [pop_levels st n ~f] removes [n] levels, calling [f] on every removed item *)
|
||||
|
||||
val iter : f:('a -> unit) -> 'a t -> unit
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue