mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-06 19:25:36 -05:00
feat: conflict minimization à la minisat
This commit is contained in:
parent
521340a23f
commit
5080195c5b
1 changed files with 82 additions and 0 deletions
|
|
@ -1108,6 +1108,85 @@ module Make(Plugin : PLUGIN)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(* abtraction of the assignment level of [v] in an integer *)
|
||||||
|
let[@inline] abstract_level_ (self:t) (v:var) : int =
|
||||||
|
1 lsl (Var.level self.store v land 31)
|
||||||
|
|
||||||
|
exception Non_redundant
|
||||||
|
|
||||||
|
(* can we remove [a] by self-subsuming resolutions with other lits
|
||||||
|
of the learnt clause? *)
|
||||||
|
let lit_redundant (self:t) (abstract_levels:int) (v:var) : bool =
|
||||||
|
let store = self.store in
|
||||||
|
let to_unmark = self.to_clear in
|
||||||
|
|
||||||
|
let top = Vec.size to_unmark in
|
||||||
|
let rec aux v =
|
||||||
|
match Var.reason store v with
|
||||||
|
| None -> assert false
|
||||||
|
| Some Decision -> raise_notrace Non_redundant
|
||||||
|
| Some (Bcp c | Bcp_lazy (lazy c)) ->
|
||||||
|
let c_atoms = Clause.atoms_a store c in
|
||||||
|
assert (Var.equal v (Atom.var c_atoms.(0)));
|
||||||
|
(* check that all the other lits of [c] are marked or redundant *)
|
||||||
|
for i = 1 to Array.length c_atoms - 1 do
|
||||||
|
let v2 = Atom.var c_atoms.(i) in
|
||||||
|
if not (Var.marked store v2) && Var.level store v2 > 0 then (
|
||||||
|
match Var.reason store v2 with
|
||||||
|
| None -> assert false
|
||||||
|
| Some (Bcp _ | Bcp_lazy _)
|
||||||
|
when (abstract_level_ self v2 land abstract_levels) <> 0 ->
|
||||||
|
(* possibly removable, its level may comprise an atom in learnt clause *)
|
||||||
|
Vec.push to_unmark v2;
|
||||||
|
Var.mark store v2;
|
||||||
|
aux v2
|
||||||
|
| Some _ ->
|
||||||
|
raise_notrace Non_redundant
|
||||||
|
)
|
||||||
|
done
|
||||||
|
in
|
||||||
|
try aux v; true
|
||||||
|
with Non_redundant ->
|
||||||
|
(* clear new marks, they are not actually redundant *)
|
||||||
|
for i = top to Vec.size to_unmark-1 do
|
||||||
|
Var.unmark store (Vec.get to_unmark i)
|
||||||
|
done;
|
||||||
|
Vec.shrink to_unmark top;
|
||||||
|
false
|
||||||
|
|
||||||
|
(* minimize conflict by removing atoms whose propagation history
|
||||||
|
is ultimately self-subsuming with [lits] *)
|
||||||
|
let minimize_conflict (self:t) (c_level:int) (learnt: atom Vec.t) : unit =
|
||||||
|
let store = self.store in
|
||||||
|
let to_unmark = self.to_clear in
|
||||||
|
assert (Vec.is_empty to_unmark);
|
||||||
|
|
||||||
|
Vec.iter
|
||||||
|
(fun a ->
|
||||||
|
if Atom.level store a < c_level then (
|
||||||
|
Vec.push to_unmark (Atom.var a);
|
||||||
|
Var.mark store (Atom.var a)
|
||||||
|
))
|
||||||
|
learnt;
|
||||||
|
|
||||||
|
(* abstraction of the levels involved in the conflict at all,
|
||||||
|
as logical "or" of each literal's approximate level *)
|
||||||
|
let abstract_levels =
|
||||||
|
Vec.fold (fun lvl a -> lvl lor abstract_level_ self (Atom.var a)) 0 learnt
|
||||||
|
in
|
||||||
|
|
||||||
|
Vec.filter_in_place
|
||||||
|
(fun a ->
|
||||||
|
Atom.level store a = c_level ||
|
||||||
|
begin match Atom.reason store a with
|
||||||
|
| Some Decision -> true (* always keep decisions *)
|
||||||
|
| _ ->
|
||||||
|
not (lit_redundant self abstract_levels (Atom.var a))
|
||||||
|
end)
|
||||||
|
learnt;
|
||||||
|
()
|
||||||
|
|
||||||
(* result of conflict analysis, containing the learnt clause and some
|
(* result of conflict analysis, containing the learnt clause and some
|
||||||
additional info. *)
|
additional info. *)
|
||||||
type conflict_res = {
|
type conflict_res = {
|
||||||
|
|
@ -1210,6 +1289,9 @@ module Make(Plugin : PLUGIN)
|
||||||
Vec.iter (Store.clear_var store) to_unmark;
|
Vec.iter (Store.clear_var store) to_unmark;
|
||||||
Vec.clear to_unmark;
|
Vec.clear to_unmark;
|
||||||
|
|
||||||
|
(* minimize conflict, to get a more general lemma *)
|
||||||
|
minimize_conflict self conflict_level learnt;
|
||||||
|
|
||||||
(* put high-level literals first, so that:
|
(* put high-level literals first, so that:
|
||||||
- they make adequate watch lits
|
- they make adequate watch lits
|
||||||
- the first literal is the UIP, if any *)
|
- the first literal is the UIP, if any *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue