mirror of
https://github.com/c-cube/sidekick.git
synced 2025-12-09 12:45:48 -05:00
refactor(cc): merge the two task queues
This commit is contained in:
parent
b7518a632a
commit
bf70f9688d
1 changed files with 109 additions and 117 deletions
|
|
@ -16,9 +16,6 @@ end
|
||||||
|
|
||||||
module Sig_tbl = CCHashtbl.Make(Signature)
|
module Sig_tbl = CCHashtbl.Make(Signature)
|
||||||
|
|
||||||
type merge_op = node * node * explanation
|
|
||||||
(* a merge operation to perform *)
|
|
||||||
|
|
||||||
module type ACTIONS = sig
|
module type ACTIONS = sig
|
||||||
val on_backtrack: (unit -> unit) -> unit
|
val on_backtrack: (unit -> unit) -> unit
|
||||||
(** Register a callback to be invoked upon backtracking below the current level *)
|
(** Register a callback to be invoked upon backtracking below the current level *)
|
||||||
|
|
@ -35,6 +32,10 @@ end
|
||||||
|
|
||||||
type actions = (module ACTIONS)
|
type actions = (module ACTIONS)
|
||||||
|
|
||||||
|
type task =
|
||||||
|
| T_pending of node
|
||||||
|
| T_merge of node * node * explanation
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
tst: Term.state;
|
tst: Term.state;
|
||||||
acts: actions;
|
acts: actions;
|
||||||
|
|
@ -48,10 +49,8 @@ type t = {
|
||||||
The critical property is that all members of an equivalence class
|
The critical property is that all members of an equivalence class
|
||||||
that have the same "shape" (including head symbol)
|
that have the same "shape" (including head symbol)
|
||||||
have the same signature *)
|
have the same signature *)
|
||||||
pending: node Vec.t;
|
tasks: task Vec.t;
|
||||||
(* nodes to check, maybe their new signature is in {!signatures_tbl} *)
|
(* tasks to perform *)
|
||||||
combine: merge_op Vec.t;
|
|
||||||
(* pairs of terms to merge *)
|
|
||||||
mutable ps_lits: Lit.Set.t;
|
mutable ps_lits: Lit.Set.t;
|
||||||
(* proof state *)
|
(* proof state *)
|
||||||
ps_queue: (node*node) Vec.t;
|
ps_queue: (node*node) Vec.t;
|
||||||
|
|
@ -146,22 +145,18 @@ let add_signature cc (t:term) (r:node): unit =
|
||||||
assert (same_class cc r r');
|
assert (same_class cc r r');
|
||||||
end
|
end
|
||||||
|
|
||||||
let[@inline] is_done (cc:t): bool =
|
|
||||||
Vec.is_empty cc.pending &&
|
|
||||||
Vec.is_empty cc.combine
|
|
||||||
|
|
||||||
let push_pending cc t : unit =
|
let push_pending cc t : unit =
|
||||||
if not @@ Equiv_class.get_field Equiv_class.field_is_pending t then (
|
if not @@ Equiv_class.get_field Equiv_class.field_is_pending t then (
|
||||||
Log.debugf 5 (fun k->k "(@[<hv1>cc.push_pending@ %a@])" Equiv_class.pp t);
|
Log.debugf 5 (fun k->k "(@[<hv1>cc.push_pending@ %a@])" Equiv_class.pp t);
|
||||||
Equiv_class.set_field Equiv_class.field_is_pending true t;
|
Equiv_class.set_field Equiv_class.field_is_pending true t;
|
||||||
Vec.push cc.pending t
|
Vec.push cc.tasks (T_pending t)
|
||||||
)
|
)
|
||||||
|
|
||||||
let push_combine cc t u e : unit =
|
let push_combine cc t u e : unit =
|
||||||
Log.debugf 5
|
Log.debugf 5
|
||||||
(fun k->k "(@[<hv1>cc.push_combine@ :t1 %a@ :t2 %a@ :expl %a@])"
|
(fun k->k "(@[<hv1>cc.push_combine@ :t1 %a@ :t2 %a@ :expl %a@])"
|
||||||
Equiv_class.pp t Equiv_class.pp u Explanation.pp e);
|
Equiv_class.pp t Equiv_class.pp u Explanation.pp e);
|
||||||
Vec.push cc.combine (t,u,e)
|
Vec.push cc.tasks @@ T_merge (t,u,e)
|
||||||
|
|
||||||
(* re-root the explanation tree of the equivalence class of [n]
|
(* re-root the explanation tree of the equivalence class of [n]
|
||||||
so that it points to [n].
|
so that it points to [n].
|
||||||
|
|
@ -296,11 +291,17 @@ let add_tag_n cc (n:node) (tag:int) (expl:explanation) : unit =
|
||||||
|
|
||||||
(* main CC algo: add terms from [pending] to the signature table,
|
(* main CC algo: add terms from [pending] to the signature table,
|
||||||
check for collisions *)
|
check for collisions *)
|
||||||
let rec update_pending (cc:t): unit =
|
let rec update_tasks (cc:t): unit =
|
||||||
(* step 2 deal with pending (parent) terms whose equiv class
|
(* step 2 deal with pending (parent) terms whose equiv class
|
||||||
might have changed *)
|
might have changed *)
|
||||||
while not (Vec.is_empty cc.pending) do
|
while not (Vec.is_empty cc.tasks) do
|
||||||
let n = Vec.pop_last cc.pending in
|
let task = Vec.pop_last cc.tasks in
|
||||||
|
match task with
|
||||||
|
| T_pending n -> task_pending_ cc n
|
||||||
|
| T_merge (t,u,expl) -> task_merge_ cc t u expl
|
||||||
|
done
|
||||||
|
|
||||||
|
and task_pending_ cc n =
|
||||||
Equiv_class.set_field Equiv_class.field_is_pending false n;
|
Equiv_class.set_field Equiv_class.field_is_pending false n;
|
||||||
(* check if some parent collided *)
|
(* check if some parent collided *)
|
||||||
begin match find_by_signature cc n.n_term with
|
begin match find_by_signature cc n.n_term with
|
||||||
|
|
@ -328,16 +329,11 @@ let rec update_pending (cc:t): unit =
|
||||||
(* FIXME: when to actually evaluate?
|
(* FIXME: when to actually evaluate?
|
||||||
eval_pending cc;
|
eval_pending cc;
|
||||||
*)
|
*)
|
||||||
done;
|
()
|
||||||
if not (is_done cc) then (
|
|
||||||
update_combine cc (* repeat *)
|
|
||||||
)
|
|
||||||
|
|
||||||
(* main CC algo: merge equivalence classes in [st.combine].
|
(* main CC algo: merge equivalence classes in [st.combine].
|
||||||
@raise Exn_unsat if merge fails *)
|
@raise Exn_unsat if merge fails *)
|
||||||
and update_combine cc =
|
and task_merge_ cc a b e_ab : unit =
|
||||||
while not (Vec.is_empty cc.combine) do
|
|
||||||
let a, b, e_ab = Vec.pop_last cc.combine in
|
|
||||||
let ra = find cc a in
|
let ra = find cc a in
|
||||||
let rb = find cc b in
|
let rb = find cc b in
|
||||||
if not (Equiv_class.equal ra rb) then (
|
if not (Equiv_class.equal ra rb) then (
|
||||||
|
|
@ -395,9 +391,6 @@ and update_combine cc =
|
||||||
(* notify listeners of the merge *)
|
(* notify listeners of the merge *)
|
||||||
notify_merge cc r_from ~into:r_into e_ab;
|
notify_merge cc r_from ~into:r_into e_ab;
|
||||||
)
|
)
|
||||||
done;
|
|
||||||
(* now update pending terms again *)
|
|
||||||
update_pending cc
|
|
||||||
|
|
||||||
(* Checks if [ra] and [~into] have compatible normal forms and can
|
(* Checks if [ra] and [~into] have compatible normal forms and can
|
||||||
be merged w.r.t. the theories.
|
be merged w.r.t. the theories.
|
||||||
|
|
@ -452,12 +445,12 @@ and[@inline] add_ cc t : node =
|
||||||
|
|
||||||
let add cc t : node =
|
let add cc t : node =
|
||||||
let n = add_ cc t in
|
let n = add_ cc t in
|
||||||
update_pending cc;
|
update_tasks cc;
|
||||||
n
|
n
|
||||||
|
|
||||||
let add_seq cc seq =
|
let add_seq cc seq =
|
||||||
seq (fun t -> ignore @@ add_ cc t);
|
seq (fun t -> ignore @@ add_ cc t);
|
||||||
update_pending cc
|
update_tasks cc
|
||||||
|
|
||||||
(* assert that this boolean literal holds *)
|
(* assert that this boolean literal holds *)
|
||||||
let assert_lit cc lit : unit =
|
let assert_lit cc lit : unit =
|
||||||
|
|
@ -473,7 +466,7 @@ let assert_lit cc lit : unit =
|
||||||
the corresponding value, so its superterms (like [ite]) can evaluate
|
the corresponding value, so its superterms (like [ite]) can evaluate
|
||||||
properly *)
|
properly *)
|
||||||
push_combine cc n rhs (E_lit lit);
|
push_combine cc n rhs (E_lit lit);
|
||||||
update_combine cc
|
update_tasks cc
|
||||||
|
|
||||||
let assert_eq cc (t:term) (u:term) e : unit =
|
let assert_eq cc (t:term) (u:term) e : unit =
|
||||||
let n1 = add_ cc t in
|
let n1 = add_ cc t in
|
||||||
|
|
@ -482,7 +475,7 @@ let assert_eq cc (t:term) (u:term) e : unit =
|
||||||
let e = Explanation.E_lits e in
|
let e = Explanation.E_lits e in
|
||||||
push_combine cc n1 n2 e;
|
push_combine cc n1 n2 e;
|
||||||
);
|
);
|
||||||
update_pending cc
|
update_tasks cc
|
||||||
|
|
||||||
let assert_distinct cc (l:term list) ~neq (lit:Lit.t) : unit =
|
let assert_distinct cc (l:term list) ~neq (lit:Lit.t) : unit =
|
||||||
assert (match l with[] | [_] -> false | _ -> true);
|
assert (match l with[] | [_] -> false | _ -> true);
|
||||||
|
|
@ -513,8 +506,7 @@ let create ?(size=2048) ~actions (tst:Term.state) : t =
|
||||||
acts=actions;
|
acts=actions;
|
||||||
tbl = Term.Tbl.create size;
|
tbl = Term.Tbl.create size;
|
||||||
signatures_tbl = Sig_tbl.create size;
|
signatures_tbl = Sig_tbl.create size;
|
||||||
pending=Vec.make_empty Equiv_class.dummy;
|
tasks=Vec.make_empty (T_pending Equiv_class.dummy);
|
||||||
combine= Vec.make_empty (nd,nd,E_reduction);
|
|
||||||
ps_lits=Lit.Set.empty;
|
ps_lits=Lit.Set.empty;
|
||||||
ps_queue=Vec.make_empty (nd,nd);
|
ps_queue=Vec.make_empty (nd,nd);
|
||||||
true_ = Equiv_class.dummy;
|
true_ = Equiv_class.dummy;
|
||||||
|
|
@ -526,7 +518,7 @@ let create ?(size=2048) ~actions (tst:Term.state) : t =
|
||||||
|
|
||||||
let final_check cc : unit =
|
let final_check cc : unit =
|
||||||
Log.debug 5 "(CC.final_check)";
|
Log.debug 5 "(CC.final_check)";
|
||||||
update_pending cc
|
update_tasks cc
|
||||||
|
|
||||||
(* model: map each uninterpreted equiv class to some ID *)
|
(* model: map each uninterpreted equiv class to some ID *)
|
||||||
let mk_model (cc:t) (m:Model.t) : Model.t =
|
let mk_model (cc:t) (m:Model.t) : Model.t =
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue