type var = Var.var
type literal = Term.literal
type clause = Term.clause
type subst = Subst.subst
type choice_point = State.choice_point
type state = State.state
type 'a stack = 'a Stack.stack
type candidate_type =
| Close
| Assert
| Split
| CloseAssert
| All
type context_partner = {
cp_element: Context.element;
cp_partial_context_unifier: subst option;
cp_empty_remainder: bool;
}
type context_partners =
context_partner array
type input_partner = {
ip_index: int;
ip_literal: literal;
ip_vars: Subst.var list;
mutable ip_context_partners: context_partner stack;
mutable ip_resolved: context_partner option;
}
type context_unifier_space = {
cus_id: int;
cus_clause: clause;
cus_lemma: bool;
mutable cus_lemma_learned: int;
cus_vars: Subst.var list;
cus_shared_vars: Subst.var list;
cus_local_vars: Subst.var list;
cus_input_partners: input_partner array;
cus_input_partners_ordering: int array;
cus_process_close_candidate: (raw_context_unifier -> unit);
cus_process_assert_candidate: (raw_context_unifier -> bool);
cus_process_split_candidate: (raw_context_unifier -> unit);
cus_is_element_incomplete_assert: Context.element -> bool;
cus_is_element_incomplete_split: Context.element -> bool;
cus_utility: int ref;
}
and raw_context_unifier = {
rcu_space: context_unifier_space;
rcu_context_partners: context_partners;
rcu_exceeding_complexity: bool;
}
exception UNSATISFIABLE
exception CLOSE of raw_context_unifier
let assert_partner = {
cp_element = Context.assert_element;
cp_partial_context_unifier = Some Subst.empty;
cp_empty_remainder = true;
}
let null_partner = {
cp_element = Context.null_element;
cp_partial_context_unifier = Some Subst.empty;
cp_empty_remainder = true;
}
let null_space = {
cus_id = -1;
cus_clause = [];
cus_vars = [];
cus_lemma = false;
cus_lemma_learned = 0;
cus_shared_vars = [];
cus_local_vars = [];
cus_input_partners = [| |];
cus_input_partners_ordering = [| |];
cus_process_close_candidate = (fun _raw_context_unifier -> ());
cus_process_assert_candidate = (fun _raw_context_unifier -> false);
cus_process_split_candidate = (fun _raw_context_unifier -> ());
cus_is_element_incomplete_assert = (fun _ -> false);
cus_is_element_incomplete_split = (fun _ -> false);
cus_utility = ref 0;
}
let null_context_unifier = {
rcu_space = null_space;
rcu_context_partners = [| |];
rcu_exceeding_complexity = false;
}
let get_input_clause (context_unifier_space: context_unifier_space) : clause =
context_unifier_space.cus_clause
let get_context_literals (context_partners: context_partners) : literal array =
Array.map
(fun context_literal ->
context_literal.cp_element.Context.el_literal
)
context_partners
let context_unifier_to_string
(context_unifier_space: context_unifier_space) (context_partners: context_partners)
: string =
let context_literals =
Array.to_list (
Array.map
(fun context_partner ->
Term.literal_to_string context_partner.cp_element.Context.el_literal
)
context_partners
)
in
(
if context_unifier_space.cus_lemma then
"Lemma : "
else
"Clause : "
)
^ Term.clause_to_string (get_input_clause context_unifier_space)
^ "\n"
^ "Context: "
^ "["
^ String.concat ", " context_literals ^ "]"
^ "\n"
let raw_context_unifier_to_string (raw_context_unifier: raw_context_unifier) : string =
context_unifier_to_string
raw_context_unifier.rcu_space
raw_context_unifier.rcu_context_partners
let is_raw_context_unifier_invalid (raw_context_unifier: raw_context_unifier) : bool =
Tools.array_exists
(fun context_partner ->
State.is_choice_point_invalid context_partner.cp_element.Context.el_choice_point
)
raw_context_unifier.rcu_context_partners
let extend_partial_context_unifier ~(recompute: bool) ~(p_preserving: bool)
(subst: subst) (input_partner: input_partner) (context_partner: context_partner) : subst =
match context_partner.cp_partial_context_unifier with
| Some partial_context_unifier ->
Unification.unify_substs
~recompute:recompute
~p_preserving:p_preserving
subst
partial_context_unifier
| None ->
if
Context.element_equal context_partner.cp_element Context.plus_v_element
||
Context.element_equal context_partner.cp_element Context.minus_v_element
then begin
failwith "extend_partial_context_unifier";
end
else begin
let subst =
Unification.unify_terms_
~recompute:recompute
~p_preserving:p_preserving
subst
context_partner.cp_element.Context.el_literal.Term.atom
(Subst.context_literal_offset input_partner.ip_index)
input_partner.ip_literal.Term.atom
Subst.input_literal_offset
in
subst
end
let recompute_unifier ~(recompute: bool) (raw_context_unifier: raw_context_unifier) : subst =
let rec recompute_at (i: int) (acc: subst) : subst =
if i >= Array.length raw_context_unifier.rcu_space.cus_input_partners then
acc
else
let input_partner =
raw_context_unifier.rcu_space.cus_input_partners.(i)
in
let input_index =
input_partner.ip_index
in
let context_partner =
raw_context_unifier.rcu_context_partners.(input_index)
in
let extended_unifier =
try
extend_partial_context_unifier ~recompute:recompute ~p_preserving:false
acc input_partner context_partner
with
| Unification.UNIFICATION_FAIL ->
print_endline (Subst.subst_to_string acc);
print_endline (Term.literal_to_string input_partner.ip_literal);
print_endline (Term.literal_to_string context_partner.cp_element.Context.el_literal);
print_endline (raw_context_unifier_to_string raw_context_unifier);
failwith "Context_unifier.recompute_unifier"
in
recompute_at (i + 1) extended_unifier
in
recompute_at 0 Subst.empty
let recompute_full_unifier ~(recompute: bool) (raw_context_unifier: raw_context_unifier) : subst =
recompute_unifier ~recompute:recompute raw_context_unifier
let is_remainder (subst: subst) (context_element: Context.element) (offset: int) =
let par_offset =
Subst.context_literal_offset offset
in
List.exists
(fun par ->
match Subst.get' subst par par_offset with
| None ->
false
| Some term ->
begin
match term.Subst.st_term with
| Term.Var var ->
Var.is_universal var
| _ ->
true
end
)
context_element.Context.el_pars
let is_remainder' (subst: subst) =
Subst.exists
(fun binding ->
Var.is_parametric binding.Subst.sb_var.Subst.sv_var
&&
match binding.Subst.sb_term.Subst.st_term with
| Term.Var var when Var.is_parametric var ->
false
| _ ->
true
)
subst
let compute_remainder_states (raw_context_unifier: raw_context_unifier) (subst: subst) : bool array =
let remainder_states =
Array.make (Array.length raw_context_unifier.rcu_context_partners) false
in
for i = 0 to Array.length raw_context_unifier.rcu_space.cus_input_partners - 1 do
let input_index =
raw_context_unifier.rcu_space.cus_input_partners.(i).ip_index
in
let context_partner =
raw_context_unifier.rcu_context_partners.(input_index)
in
remainder_states.(input_index) <-
not context_partner.cp_empty_remainder
||
is_remainder
subst
context_partner.cp_element
input_index
done;
remainder_states
let generation_of_candidate (context_partners: context_partners) : int =
let max_generation =
Array.fold_left
(fun acc context_partner ->
Tools.max_int acc context_partner.cp_element.Context.el_generation
)
0
context_partners
in
max_generation + 1
let get_creation_choice_point (context_partners: context_partners) : choice_point =
let youngest_choice_point =
Array.fold_left
(fun acc context_partner ->
match acc with
| Some best_choice_point when
State.compare_age best_choice_point context_partner.cp_element.Context.el_choice_point >= 0 ->
acc
| _ ->
Some context_partner.cp_element.Context.el_choice_point
)
None
context_partners
in
match youngest_choice_point with
| None ->
failwith "Context_unifier.get_creation_choice_point"
| Some choice_point ->
choice_point
let creating_context_element (raw_context_unifier: raw_context_unifier) : Context.element =
let most_recent =
Array.fold_left
(fun acc context_partner ->
match acc with
| Some best when
compare best.Context.el_id context_partner.cp_element.Context.el_id >= 0 ->
acc
| _ ->
Some context_partner.cp_element
)
None
raw_context_unifier.rcu_context_partners
in
match most_recent with
| None ->
failwith "Context_unifier.creating_context_element"
| Some element ->
element
let is_permanently_blocking (blocking: Context.element) (blocked: context_partners) : bool =
Tools.array_exists
(fun partner ->
State.backtracking_depends_on
partner.cp_element.Context.el_choice_point
blocking.Context.el_choice_point
)
blocked
let create_space_utility_inc (space: context_unifier_space) : (unit -> unit) =
let f () =
space.cus_utility := !(space.cus_utility) + 1
in
f
let compare_context_unifiers ~(different: bool) (first: raw_context_unifier) (second: raw_context_unifier) : int =
let rec cmp_context_partners (index: int) =
if index >= Array.length first.rcu_context_partners then begin
if
different
&&
not (is_raw_context_unifier_invalid first)
&&
not (is_raw_context_unifier_invalid second)
then begin
print_endline (raw_context_unifier_to_string first);
print_endline (raw_context_unifier_to_string second);
failwith "Context_unifier.compare_context_unifiers";
end
else begin
0
end
end
else
let cmp =
compare
first.rcu_context_partners.(index).cp_element.Context.el_id
second.rcu_context_partners.(index).cp_element.Context.el_id
in
if cmp <> 0 then
cmp
else
cmp_context_partners (index + 1)
in
if first == second then
0
else
let cmp_creation_point =
Tools.compare_int
(creating_context_element first).Context.el_id
(creating_context_element second).Context.el_id
in
if cmp_creation_point <> 0 then
cmp_creation_point
else
let cmp_clause =
compare first.rcu_space.cus_id second.rcu_space.cus_id
in
if cmp_clause <> 0 then
cmp_clause
else if
Const.debug
&&
(Array.length first.rcu_context_partners != Array.length second.rcu_context_partners)
then
failwith "Context_unifier.cmp_context_partners 1"
else
cmp_context_partners 0
let create_context_unifier space partners complexity =
{
rcu_space = space;
rcu_context_partners = partners;
rcu_exceeding_complexity = complexity;
}
let create_context_partner element subst empty_remainder =
{
cp_element = element;
cp_partial_context_unifier = subst;
cp_empty_remainder = empty_remainder;
}
let create_input_partner index literal vars =
{
ip_index = index;
ip_literal = literal;
ip_vars = vars;
ip_context_partners = Stack.create null_partner;
ip_resolved = None;
}
let create_space id clause clause_vars shared_vars local_vars input_partners ordering
process_close process_assert process_split
is_element_incomplete_assert is_element_incomplete_split is_lemma =
{
cus_id = id;
cus_clause = clause;
cus_vars = clause_vars;
cus_shared_vars = shared_vars;
cus_local_vars = local_vars;
cus_input_partners = input_partners;
cus_input_partners_ordering = ordering;
cus_process_close_candidate = process_close;
cus_process_assert_candidate = process_assert;
cus_process_split_candidate = process_split;
cus_is_element_incomplete_assert = is_element_incomplete_assert;
cus_is_element_incomplete_split = is_element_incomplete_split;
cus_lemma = is_lemma;
cus_lemma_learned = if is_lemma then 1 else 0;
cus_utility = ref 0;
}
let set_resolved input_partner resolved =
input_partner.ip_resolved <- resolved
let increase_lemma_learned space =
space.cus_lemma_learned <- space.cus_lemma_learned + 1