mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 11:15:43 -05:00
refactor: introduce check_invariants in CC
costly, but helps find bugs
This commit is contained in:
parent
ce9bcb234d
commit
b8445d0ca3
8 changed files with 80 additions and 3 deletions
|
|
@ -1426,7 +1426,7 @@ module Make (Th : Theory_intf.S) = struct
|
||||||
(* remove some learnt clauses
|
(* remove some learnt clauses
|
||||||
NOTE: so far we do not forget learnt clauses. We could, as long as
|
NOTE: so far we do not forget learnt clauses. We could, as long as
|
||||||
lemmas from the theory itself are kept. *)
|
lemmas from the theory itself are kept. *)
|
||||||
let reduce_db () = ()
|
let reduce_db (_:t) = ()
|
||||||
|
|
||||||
(* Decide on a new literal, and enqueue it into the trail *)
|
(* Decide on a new literal, and enqueue it into the trail *)
|
||||||
let rec pick_branch_aux st atom : unit =
|
let rec pick_branch_aux st atom : unit =
|
||||||
|
|
@ -1450,11 +1450,18 @@ module Make (Th : Theory_intf.S) = struct
|
||||||
| exception Not_found -> raise Sat
|
| exception Not_found -> raise Sat
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let[@inline] check_invariants (st:t) =
|
||||||
|
if Util._CHECK_INVARIANTS then (
|
||||||
|
Th.check_invariants @@ theory st;
|
||||||
|
(* TODO: also check internal invariants? *)
|
||||||
|
)
|
||||||
|
|
||||||
(* do some amount of search, until the number of conflicts or clause learnt
|
(* do some amount of search, until the number of conflicts or clause learnt
|
||||||
reaches the given parameters *)
|
reaches the given parameters *)
|
||||||
let search (st:t) n_of_conflicts n_of_learnts : unit =
|
let search (st:t) n_of_conflicts n_of_learnts : unit =
|
||||||
let conflictC = ref 0 in
|
let conflictC = ref 0 in
|
||||||
while true do
|
while true do
|
||||||
|
check_invariants st;
|
||||||
match propagate st with
|
match propagate st with
|
||||||
| Some confl -> (* Conflict *)
|
| Some confl -> (* Conflict *)
|
||||||
incr conflictC;
|
incr conflictC;
|
||||||
|
|
@ -1472,8 +1479,9 @@ module Make (Th : Theory_intf.S) = struct
|
||||||
(* if decision_level() = 0 then simplify (); *)
|
(* if decision_level() = 0 then simplify (); *)
|
||||||
|
|
||||||
if n_of_learnts >= 0 &&
|
if n_of_learnts >= 0 &&
|
||||||
Vec.size st.clauses - Vec.size st.trail >= n_of_learnts
|
Vec.size st.clauses - Vec.size st.trail >= n_of_learnts then (
|
||||||
then reduce_db();
|
reduce_db st;
|
||||||
|
);
|
||||||
|
|
||||||
pick_branch_lit st
|
pick_branch_lit st
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -130,5 +130,9 @@ module type S = sig
|
||||||
val if_sat : t -> formula slice_actions -> (formula, proof) res
|
val if_sat : t -> formula slice_actions -> (formula, proof) res
|
||||||
(** Called at the end of the search in case a model has been found. If no new clause is
|
(** Called at the end of the search in case a model has been found. If no new clause is
|
||||||
pushed, then 'sat' is returned, else search is resumed. *)
|
pushed, then 'sat' is returned, else search is resumed. *)
|
||||||
|
|
||||||
|
(**/**)
|
||||||
|
val check_invariants : t -> unit
|
||||||
|
(**/**)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ and task_merge_ cc a b e_ab : unit =
|
||||||
(fun parent -> push_pending cc parent)
|
(fun parent -> push_pending cc parent)
|
||||||
end;
|
end;
|
||||||
(* perform [union ra rb] *)
|
(* perform [union ra rb] *)
|
||||||
|
Log.debugf 15 (fun k->k "(@[cc.merge@ :from %a@ :into %a@])" Equiv_class.pp r_from Equiv_class.pp r_into);
|
||||||
begin
|
begin
|
||||||
let r_into_old_parents = r_into.n_parents in
|
let r_into_old_parents = r_into.n_parents in
|
||||||
let r_into_old_tags = r_into.n_tags in
|
let r_into_old_tags = r_into.n_tags in
|
||||||
|
|
@ -606,3 +607,49 @@ let mk_model (cc:t) (m:Model.t) : Model.t =
|
||||||
funs
|
funs
|
||||||
in
|
in
|
||||||
Model.add_funs funs m
|
Model.add_funs funs m
|
||||||
|
|
||||||
|
let pp_full out (cc:t) : unit =
|
||||||
|
let pp_n out n =
|
||||||
|
let pp_next out n =
|
||||||
|
if n==n.n_root then () else Fmt.fprintf out "@ :next %a" Equiv_class.pp n.n_root in
|
||||||
|
let pp_root out n =
|
||||||
|
let u = find cc n in if n==u||n.n_root==u then () else Fmt.fprintf out "@ :root %a" Equiv_class.pp u in
|
||||||
|
Fmt.fprintf out "(@[%a%a%a@])" Term.pp n.n_term pp_next n pp_root n
|
||||||
|
and pp_sig_e out (s,n) =
|
||||||
|
Fmt.fprintf out "(@[<1>%a@ -> %a@])" Signature.pp s Equiv_class.pp n
|
||||||
|
in
|
||||||
|
Fmt.fprintf out
|
||||||
|
"(@[cc.state@ (@[<hv>:nodes@ %a@])@ (@[<hv>:sig@ %a@])@])"
|
||||||
|
(Util.pp_seq ~sep:" " pp_n) (Term.Tbl.values cc.tbl)
|
||||||
|
(Util.pp_seq ~sep:" " pp_sig_e) (Sig_tbl.to_seq cc.signatures_tbl)
|
||||||
|
|
||||||
|
let check_invariants_ (cc:t) =
|
||||||
|
Log.debug 5 "(cc.check-invariants)";
|
||||||
|
Log.debugf 15 (fun k-> k "%a" pp_full cc);
|
||||||
|
assert (Term.equal (Term.true_ cc.tst) cc.true_.n_term);
|
||||||
|
assert (Term.equal (Term.false_ cc.tst) cc.false_.n_term);
|
||||||
|
assert (Vec.is_empty cc.tasks);
|
||||||
|
(* check that subterms are internalized *)
|
||||||
|
Term.Tbl.iter
|
||||||
|
(fun t n ->
|
||||||
|
assert (Term.equal t n.n_term);
|
||||||
|
assert (not @@ Equiv_class.get_field Equiv_class.field_is_pending n);
|
||||||
|
relevant_subterms t
|
||||||
|
(fun u -> assert (Term.Tbl.mem cc.tbl u));
|
||||||
|
(* check proper signature *)
|
||||||
|
begin match signature cc t with
|
||||||
|
| None -> ()
|
||||||
|
| Some s ->
|
||||||
|
Log.debugf 15 (fun k->k "(@[cc.check-sig@ %a@ :sig %a@])" Term.pp t Signature.pp s);
|
||||||
|
(* add, but only if not present already *)
|
||||||
|
begin match Sig_tbl.find cc.signatures_tbl s with
|
||||||
|
| exception Not_found -> assert false
|
||||||
|
| repr_s -> assert (same_class cc n repr_s)
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
)
|
||||||
|
cc.tbl;
|
||||||
|
()
|
||||||
|
|
||||||
|
let[@inline] check_invariants (cc:t) : unit =
|
||||||
|
if Util._CHECK_INVARIANTS then check_invariants_ cc
|
||||||
|
|
|
||||||
|
|
@ -68,3 +68,6 @@ val mk_model : t -> Model.t -> Model.t
|
||||||
(** Enrich a model by mapping terms to their representative's value,
|
(** Enrich a model by mapping terms to their representative's value,
|
||||||
if any. Otherwise map the representative to a fresh value *)
|
if any. Otherwise map the representative to a fresh value *)
|
||||||
|
|
||||||
|
(**/**)
|
||||||
|
val check_invariants : t -> unit
|
||||||
|
(**/**)
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ let make ~name ~make () : t = {name;make}
|
||||||
|
|
||||||
let make_st
|
let make_st
|
||||||
(type st)
|
(type st)
|
||||||
|
?(check_invariants=fun _ -> ())
|
||||||
?(on_merge=fun _ _ _ _ -> ())
|
?(on_merge=fun _ _ _ _ -> ())
|
||||||
?(on_assert=fun _ _ -> ())
|
?(on_assert=fun _ _ -> ())
|
||||||
?(mk_model=fun _ _ -> Model.empty)
|
?(mk_model=fun _ _ -> Model.empty)
|
||||||
|
|
@ -99,5 +100,6 @@ let make_st
|
||||||
let on_assert = on_assert
|
let on_assert = on_assert
|
||||||
let final_check = final_check
|
let final_check = final_check
|
||||||
let mk_model = mk_model
|
let mk_model = mk_model
|
||||||
|
let check_invariants = check_invariants
|
||||||
end in
|
end in
|
||||||
(module A : STATE)
|
(module A : STATE)
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,11 @@ let act_add_persistent_axiom self c : unit =
|
||||||
let (module A) = self.cdcl_acts in
|
let (module A) = self.cdcl_acts in
|
||||||
A.push_persistent c Proof.default
|
A.push_persistent c Proof.default
|
||||||
|
|
||||||
|
let check_invariants (self:t) =
|
||||||
|
if Util._CHECK_INVARIANTS then (
|
||||||
|
Congruence_closure.check_invariants (cc self);
|
||||||
|
)
|
||||||
|
|
||||||
let mk_theory_actions (self:t) : Theory.actions =
|
let mk_theory_actions (self:t) : Theory.actions =
|
||||||
let (module A) = self.cdcl_acts in
|
let (module A) = self.cdcl_acts in
|
||||||
let module R = struct
|
let module R = struct
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,6 @@ let setup_gc () =
|
||||||
module Int_set = CCSet.Make(CCInt)
|
module Int_set = CCSet.Make(CCInt)
|
||||||
module Int_map = CCMap.Make(CCInt)
|
module Int_map = CCMap.Make(CCInt)
|
||||||
module Int_tbl = CCHashtbl.Make(CCInt)
|
module Int_tbl = CCHashtbl.Make(CCInt)
|
||||||
|
|
||||||
|
(* NOTE: if true, can have a big impact on performance *)
|
||||||
|
let _CHECK_INVARIANTS = true
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,8 @@ val setup_gc : unit -> unit
|
||||||
module Int_set : CCSet.S with type elt = int
|
module Int_set : CCSet.S with type elt = int
|
||||||
module Int_map : CCMap.S with type key = int
|
module Int_map : CCMap.S with type key = int
|
||||||
module Int_tbl : CCHashtbl.S with type key = int
|
module Int_tbl : CCHashtbl.S with type key = int
|
||||||
|
|
||||||
|
(* compile time config for internal checking of invariants *)
|
||||||
|
val _CHECK_INVARIANTS : bool
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue