type config = Config.config
type bound = Bound.bound
type statistic = Statistic.statistic
type literal = Term.literal
type binding = Subst.binding
type subst = Subst.subst
type choice_point = State.choice_point
type state = State.state
type context = Context.context
type context_partner = Context_unifier.context_partner
type input_partner = Context_unifier.input_partner
type context_unifier_space = Context_unifier.context_unifier_space
type 'data stack = 'data Stack.stack
module Bindings =
Hashtbl.Make (
struct
type t = binding
let equal =
Subst.binding_equal
let hash (binding: binding) : int =
let var_hash =
Var.hash_of_var binding.Subst.sb_var.Subst.sv_var
and term_hash =
Term.hash_of_term binding.Subst.sb_term.Subst.st_term
in
var_hash + (term_hash * 131)
end
)
type element = {
input_partner: input_partner;
mutable spaces: context_unifier_space list;
}
module Elements =
Map.Make (
struct
type t = int
let compare (first: int) (second: int) : int =
Tools.compare_int first second
end
)
type problem_literal = {
literal: literal;
mutable elements: element Elements.t;
mutable subsumed_at: int;
}
module LiteralTable = Term.LiteralTable
class problem_literal_data =
object
method is_equal (first: problem_literal) (second: problem_literal) : bool =
Term.literal_equal first.literal second.literal
method to_string (data: problem_literal) : string =
"problem_literal: " ^ Term.literal_to_string data.literal
end
type predicate_index = problem_literal Term_indexing.predicate_index
type problem_literals = {
config: config;
bound: bound;
statistic: statistic;
state: state;
context: context;
problem_literals: problem_literal LiteralTable.t;
index: problem_literal Term_indexing.index;
bindings: (binding * choice_point) Bindings.t;
mutable subsumed_clauses: int array;
mutable cached_partial_context_unifiers: int;
}
let register_binding (problem_literals: problem_literals) (binding: binding) : binding =
try
fst (Bindings.find problem_literals.bindings binding)
with
| Not_found ->
Bindings.add problem_literals.bindings
binding
(binding, State.active_choice_point problem_literals.state);
binding
let register_subst (problem_literals: problem_literals) (subst: subst) : subst =
Subst.map (register_binding problem_literals) subst
let store_partial_context_unifier (problem_literals: problem_literals) (subst: subst) : subst option =
if Subst.is_empty subst then begin
Some subst
end
else if
problem_literals.cached_partial_context_unifiers < Const.max_cached_partial_context_unifiers
||
(Subst.length subst < 2)
then begin
problem_literals.cached_partial_context_unifiers <- problem_literals.cached_partial_context_unifiers + 1;
let pruned_subst =
Subst.remove_context_var_renamings subst
in
Some (register_subst problem_literals pruned_subst)
end
else
None
let create (config: config) (bound: bound) (statistic : statistic) (state: state) (context: context) : problem_literals =
{
config = config;
bound = bound;
statistic = statistic;
state = state;
context = context;
problem_literals = LiteralTable.create 16;
index = Discrimination_tree.create_index false (new problem_literal_data);
bindings = Bindings.create 128;
subsumed_clauses = Array.create 32 (-1);
cached_partial_context_unifiers = 0;
}
let create_initial_context_partners (problem_literals: problem_literals)
(input_partner: input_partner) : unit =
if
(Config.is_horn problem_literals.config)
||
input_partner.Context_unifier.ip_literal.Term.sign = Config.plus_v problem_literals.config;
then
()
else begin
let subst =
Subst.set' ~recompute:false ~p_preserving:false
Subst.empty
Term.v_par (Subst.context_literal_offset input_partner.Context_unifier.ip_index)
Term.v_term (Subst.context_literal_offset input_partner.Context_unifier.ip_index);
in
let v_cp_element =
if Config.plus_v problem_literals.config then
Context.plus_v_element
else
Context.minus_v_element
in
let registered =
register_subst problem_literals subst
in
let context_partner =
Context_unifier.create_context_partner v_cp_element (Some registered) false
in
Stack.push input_partner.Context_unifier.ip_context_partners context_partner
end
let create_input_partner (problem_literals: problem_literals) (literal: literal) (index: int) : input_partner =
let vars =
List.map
(fun var ->
Subst.make_var var Subst.input_literal_offset
)
(Term.vars_of_literal literal)
in
let input_partner =
Context_unifier.create_input_partner
index literal vars
in
create_initial_context_partners problem_literals input_partner;
input_partner
let create_context_partner (problem_literals: problem_literals)
(_input_partner: input_partner) (context_element: Context.element) (subst: subst) : context_partner =
let p_preserving =
match context_element.Context.el_pars with
| [] -> true
| _ ->
not (Context_unifier.is_remainder' subst)
in
Context_unifier.create_context_partner
context_element (store_partial_context_unifier problem_literals subst) p_preserving
let clone_context_partner (problem_literals: problem_literals)
(context_partner: context_partner) (old_input_partner: input_partner) (new_input_partner: input_partner) :
context_partner =
let partial_context_unifier =
match context_partner.Context_unifier.cp_partial_context_unifier with
| None ->
None
| Some subst ->
store_partial_context_unifier
problem_literals
(
Subst.replace_offset
subst
(Subst.context_literal_offset old_input_partner.Context_unifier.ip_index)
(Subst.context_literal_offset new_input_partner.Context_unifier.ip_index)
)
in
Context_unifier.create_context_partner
context_partner.Context_unifier.cp_element
partial_context_unifier
context_partner.Context_unifier.cp_empty_remainder
let is_space_subsumed (problem_literals: problem_literals)
(context_unifier_space: context_unifier_space) : bool =
problem_literals.subsumed_clauses.(context_unifier_space.Context_unifier.cus_id) <> -1
let is_space_subsumed_at (problem_literals: problem_literals)
(context_unifier_space: context_unifier_space) (context_element: Context.element) : bool =
problem_literals.subsumed_clauses.(context_unifier_space.Context_unifier.cus_id) <> -1
&&
(
problem_literals.subsumed_clauses.(context_unifier_space.Context_unifier.cus_id)
<
context_element.Context.el_id
)
let is_problem_literal_subsumed_at ~(directly: bool) (problem_literals: problem_literals)
(problem_literal: problem_literal) (context_element: Context.element) : bool =
let directly = true in
if problem_literal.subsumed_at = -1 then begin
if directly then
false
else
try
Elements.iter
(fun _ element ->
List.iter
(fun space ->
if not (is_space_subsumed_at problem_literals space context_element) then
raise Exit
)
element.spaces;
)
problem_literal.elements;
true
with
| Exit ->
false
end
else begin
problem_literal.subsumed_at < context_element.Context.el_id
end
let mark_space_subsumed (problem_literals: problem_literals)
(context_unifier_space: context_unifier_space) (context_element: Context.element) : unit =
if not (is_space_subsumed_at problem_literals context_unifier_space context_element) then begin
Statistic.inc_subsume problem_literals.statistic;
problem_literals.subsumed_clauses.(context_unifier_space.Context_unifier.cus_id) <- context_element.Context.el_id
end
let subsume_problem_literal (problem_literals: problem_literals)
(problem_literal: problem_literal) (context_element: Context.element) : unit =
if is_problem_literal_subsumed_at ~directly:false problem_literals problem_literal context_element then
()
else begin
Elements.iter
(fun _ element ->
List.iter
(fun space ->
mark_space_subsumed problem_literals space context_element
)
element.spaces;
)
problem_literal.elements;
problem_literal.subsumed_at <- context_element.Context.el_id;
if
not Const.stable_derivation
&&
Config.is_horn problem_literals.config
then begin
Elements.iter
(fun _ element ->
Stack.clear element.input_partner.Context_unifier.ip_context_partners;
)
problem_literal.elements
end;
end
let subsume (problem_literals: problem_literals) (context_element: Context.element) : unit =
if
(Config.subsume problem_literals.config)
&&
(match context_element.Context.el_pars with
| [] -> true
| _ -> false
)
then begin
let subsume_candidates =
let index =
problem_literals.index#find context_element.Context.el_literal
in
index#find_all_instances ~p_preserving:true context_element.Context.el_literal.Term.atom
in
List.iter
(fun problem_literal ->
subsume_problem_literal problem_literals problem_literal context_element
)
subsume_candidates;
end
let is_input_partner_resolved_at (input_partner: input_partner) (context_element: Context.element) : bool =
match input_partner.Context_unifier.ip_resolved with
| Some resolving_partner when
resolving_partner.Context_unifier.cp_element.Context.el_id
<
context_element.Context.el_id
->
true
| _ ->
false
let mark_resolved (problem_literals: problem_literals)
(input_partner: input_partner) (resolving_element: Context.element): context_partner =
Statistic.inc_resolve problem_literals.statistic;
let resolving_partner =
create_context_partner problem_literals input_partner resolving_element Subst.empty
in
Context_unifier.set_resolved input_partner (Some resolving_partner);
if
not Const.stable_derivation
&&
Config.is_horn problem_literals.config
then begin
Stack.clear input_partner.Context_unifier.ip_context_partners;
end;
resolving_partner
let resolve (problem_literals: problem_literals)
(input_partner: input_partner) (context_element: Context.element) : context_partner option =
if not (Config.resolve problem_literals.config) then
None
else if
context_element.Context.el_literal.Term.sign
=
input_partner.Context_unifier.ip_literal.Term.sign
then
None
else begin
let context_term =
context_element.Context.el_literal.Term.atom
and problem_term =
input_partner.Context_unifier.ip_literal.Term.atom
in
if Term.are_terms_variants context_term problem_term then begin
Some (mark_resolved problem_literals input_partner context_element)
end
else begin
try
ignore (
Unification.match_terms
~recompute:false
~p_preserving:true
context_term
(Subst.context_literal_offset input_partner.Context_unifier.ip_index)
problem_term
Subst.input_literal_offset
: subst);
Some (mark_resolved problem_literals input_partner context_element)
with
| Unification.UNIFICATION_FAIL ->
None
end
end
let copy_initial_context_partners
(problem_literals: problem_literals) (problem_literal: problem_literal) (input_partner: input_partner) : unit =
Elements.iter
(fun _ element ->
let old_input_partner =
element.input_partner
in
begin
match old_input_partner.Context_unifier.ip_resolved with
| Some old_resolving_partner ->
ignore (
mark_resolved problem_literals input_partner old_resolving_partner.Context_unifier.cp_element
: context_partner)
| None ->
()
end;
Stack.clear input_partner.Context_unifier.ip_context_partners;
Stack.iter
(fun context_partner ->
Stack.push input_partner.Context_unifier.ip_context_partners
(clone_context_partner problem_literals context_partner old_input_partner input_partner)
)
old_input_partner.Context_unifier.ip_context_partners
)
problem_literal.elements
let compute_initial_context_partners
(problem_literals: problem_literals) (problem_literal: problem_literal) (input_partner: input_partner) : unit =
if Config.resolve problem_literals.config then begin
let resolve_candidates =
Context.find_all_subsuming problem_literals.context
(Term.request_negated_literal ~insert_db:false input_partner.Context_unifier.ip_literal)
in
let oldest_resolving =
List.fold_left
(fun acc candidate ->
if is_problem_literal_subsumed_at ~directly:true problem_literals problem_literal candidate then
acc
else
match acc with
| Some best when
best.Context.el_id > candidate.Context.el_id ->
Some candidate
| _ ->
acc
)
None
resolve_candidates
in
begin
match oldest_resolving with
| Some resolving_element ->
ignore (mark_resolved problem_literals input_partner resolving_element : context_partner);
| None ->
()
end;
end;
let candidates =
Context.find_all_unifiable
problem_literals.context (Term.request_negated_literal ~insert_db:false input_partner.Context_unifier.ip_literal)
in
List.iter
(fun context_element ->
if is_problem_literal_subsumed_at ~directly:true problem_literals problem_literal context_element then
()
else if is_input_partner_resolved_at input_partner context_element then
()
else try
let subst =
Unification.unify_terms ~recompute:false
context_element.Context.el_literal.Term.atom
(Subst.context_literal_offset input_partner.Context_unifier.ip_index)
input_partner.Context_unifier.ip_literal.Term.atom
Subst.input_literal_offset
in
let context_partner =
create_context_partner problem_literals input_partner context_element subst
in
Stack.push input_partner.Context_unifier.ip_context_partners context_partner;
with
| Unification.UNIFICATION_FAIL ->
failwith "Problem_literals.compute_initial_partial_context_unifiers"
)
candidates;
Stack.sort
(fun x y ->
compare
x.Context_unifier.cp_element.Context.el_id
y.Context_unifier.cp_element.Context.el_id
)
input_partner.Context_unifier.ip_context_partners
let set_initial_context_partners
(problem_literals: problem_literals) (problem_literal: problem_literal) (input_partner: input_partner) : unit =
if Elements.is_empty problem_literal.elements then begin
compute_initial_context_partners problem_literals problem_literal input_partner
end
else begin
copy_initial_context_partners problem_literals problem_literal input_partner
end
let register_to_index (problem_literals: problem_literals) (problem_literal: problem_literal) : unit =
let index =
problem_literals.index#find problem_literal.literal
in
index#add problem_literal.literal.Term.atom problem_literal
let get_problem_literal (problem_literals: problem_literals) (literal: literal) : problem_literal =
try
LiteralTable.find problem_literals.problem_literals literal
with
| Not_found ->
let new_problem_literal = {
literal = literal;
elements = Elements.empty;
subsumed_at = -1;
}
in
if Config.subsume problem_literals.config then begin
let subsumption_candidates =
Context.find_all_subsuming problem_literals.context literal
in
List.iter
(fun element ->
if
new_problem_literal.subsumed_at = -1
||
element.Context.el_id < new_problem_literal.subsumed_at
then
new_problem_literal.subsumed_at <- element.Context.el_id
)
subsumption_candidates;
end;
LiteralTable.add problem_literals.problem_literals literal new_problem_literal;
register_to_index problem_literals new_problem_literal;
new_problem_literal
let register_literal
(problem_literals: problem_literals) (literal: literal) (index: int) : input_partner =
let problem_literal =
get_problem_literal problem_literals literal
in
let element =
try
Elements.find index problem_literal.elements
with
| Not_found ->
let new_input_partner =
create_input_partner problem_literals literal index
in
let new_element = {
input_partner = new_input_partner;
spaces = [];
}
in
set_initial_context_partners problem_literals problem_literal new_input_partner;
problem_literal.elements <- Elements.add index new_element problem_literal.elements;
new_element
in
element.input_partner
let extend_subsumed_clauses (problem_literals: problem_literals) (space: context_unifier_space) : unit =
if Array.length problem_literals.subsumed_clauses <= space.Context_unifier.cus_id then begin
if space.Context_unifier.cus_id >= Sys.max_array_length - 1 then begin
raise (Const.NO_SOLUTION "Problem_literals.register_clause_literal: OVERFLOW")
end;
let new_size =
let desired_size =
Tools.max_int (space.Context_unifier.cus_id + 1) (2 * (Array.length problem_literals.subsumed_clauses))
in
min Sys.max_array_length desired_size
in
let new_array =
Array.make new_size (-1)
in
Array.blit problem_literals.subsumed_clauses 0 new_array 0 (Array.length problem_literals.subsumed_clauses);
problem_literals.subsumed_clauses <- new_array;
end
let register_input_partner
(problem_literals: problem_literals) (input_partner: input_partner) (space: context_unifier_space) : unit =
extend_subsumed_clauses problem_literals space;
let literal =
input_partner.Context_unifier.ip_literal
in
let index =
input_partner.Context_unifier.ip_index
in
let problem_literal =
try
LiteralTable.find problem_literals.problem_literals literal
with
| Not_found ->
failwith "register_clause_literal: problem_literal"
in
let element =
try
Elements.find index problem_literal.elements
with
| Not_found ->
failwith "register_clause_literal: element"
in
element.spaces <- space :: element.spaces
let unregister_space (problem_literals: problem_literals) (space: context_unifier_space) : unit =
Array.iter
(fun input_partner ->
let literal =
input_partner.Context_unifier.ip_literal
in
let index =
input_partner.Context_unifier.ip_index
in
let problem_literal =
try
LiteralTable.find problem_literals.problem_literals literal
with
| Not_found ->
failwith "unregister_clause_literal: problem_literal"
in
let element =
try
Elements.find index problem_literal.elements
with
| Not_found ->
failwith "unregister_clause_literal: element"
in
element.spaces <- List.find_all (fun space' -> space != space') element.spaces;
begin
match element.spaces with
| [] ->
problem_literal.elements <- Elements.remove index problem_literal.elements;
begin
Stack.iter
(fun context_partner ->
match context_partner.Context_unifier.cp_partial_context_unifier with
| None ->
()
| Some subst ->
Subst.iter (Bindings.remove problem_literals.bindings) subst
)
input_partner.Context_unifier.ip_context_partners;
match input_partner.Context_unifier.ip_resolved with
| None ->
()
| Some context_partner ->
begin
match context_partner.Context_unifier.cp_partial_context_unifier with
| None ->
()
| Some subst ->
Subst.iter (Bindings.remove problem_literals.bindings) subst
end
end
| _ ->
()
end;
if Elements.is_empty problem_literal.elements then begin
LiteralTable.remove problem_literals.problem_literals literal;
let index =
problem_literals.index#find problem_literal.literal
in
if not (index#remove problem_literal.literal.Term.atom (Some problem_literal)) then
failwith "unregister_clause_literal: problem literal 2"
end;
)
space.Context_unifier.cus_input_partners
let move_increased_input_literal (context_unifier_space: context_unifier_space)
(move: input_partner) (config: config) : unit =
let input_partners =
context_unifier_space.Context_unifier.cus_input_partners
in
let ordering =
context_unifier_space.Context_unifier.cus_input_partners_ordering
in
let move_index =
let rec inverse i =
if i >= Array.length ordering then
failwith "move_increased_input_literal"
else if ordering.(i) = move.Context_unifier.ip_index then
i
else
inverse (i + 1)
in
inverse 0
in
let rec find_position i =
if i >= Array.length input_partners then
i - 1
else if
match input_partners.(ordering.(i)).Context_unifier.ip_resolved with
| None -> false
| _ -> true
then
find_position (i + 1)
else if
Stack.size input_partners.(ordering.(move_index)).Context_unifier.ip_context_partners
<=
Stack.size input_partners.(ordering.(i)).Context_unifier.ip_context_partners
then
i - 1
else
find_position (i + 1)
in
let new_position =
find_position (move_index + 1)
in
let swap =
ordering.(new_position)
in
ordering.(new_position) <- ordering.(move_index);
ordering.(move_index) <- swap;
if Const.debug && not (Config.is_horn config) then begin
for i = 1 to Array.length input_partners - 1 do
if
(
(
Stack.size input_partners.(ordering.(i)).Context_unifier.ip_context_partners
>=
Stack.size input_partners.(ordering.(i - 1)).Context_unifier.ip_context_partners
)
||
(match input_partners.(ordering.(i)).Context_unifier.ip_resolved with
| Some _ -> true
| None -> false
)
||
(match input_partners.(ordering.(i - 1)).Context_unifier.ip_resolved with
| Some _ -> true
| None -> false
)
)
then
()
else begin
print_endline ("MOVED INDIRECTION: " ^ string_of_int move_index
^ " to " ^ string_of_int new_position);
for i = 0 to Array.length input_partners - 1 do
print_endline (
string_of_int i ^ ": " ^ string_of_int ordering.(i) ^ ": " ^
(match input_partners.(ordering.(i)).Context_unifier.ip_resolved with
| Some _ ->
"RESOLVED"
| None ->
string_of_int (Stack.size input_partners.(ordering.(i)).Context_unifier.ip_context_partners)
)
);
done;
failwith "Problem_literals.move_increased_input_literal: input partner order not intact."
end
done;
end
let move_updated_input_literal
(context_unifier_space: context_unifier_space)
(input_partner: input_partner) (context_partner: context_partner) (config: config)
: unit =
if is_input_partner_resolved_at input_partner context_partner.Context_unifier.cp_element then
()
else
move_increased_input_literal context_unifier_space input_partner config
let add_to_clause
(config: config)
(bound: bound)
(context: context)
(context_unifier_space: context_unifier_space)
(input_partner: input_partner)
(context_partner: context_partner)
(candidate_type: Context_unifier.candidate_type)
(close_found: bool)
: bool =
if
candidate_type == Context_unifier.Split
&&
context_unifier_space.Context_unifier.cus_lemma
then
close_found
else begin
let search =
if
not Const.stable_derivation && close_found
then
Context_unifier_search.SearchClose.search_context_unifiers
else
match candidate_type with
| Context_unifier.Close ->
Context_unifier_search.SearchClose.search_context_unifiers
| Context_unifier.Assert ->
Context_unifier_search.SearchAssert.search_context_unifiers
| Context_unifier.Split ->
Context_unifier_search.SearchSplit.search_context_unifiers
| Context_unifier.CloseAssert ->
Context_unifier_search.SearchCloseAssert.search_context_unifiers
| Context_unifier.All ->
if context_unifier_space.Context_unifier.cus_lemma then
Context_unifier_search.SearchCloseAssert.search_context_unifiers
else
Context_unifier_search.SearchAll.search_context_unifiers
in
let subst =
Context_unifier.extend_partial_context_unifier
~recompute:false ~p_preserving:false
Subst.empty input_partner context_partner
in
let close_found' =
search
config
bound
context
context_unifier_space
input_partner.Context_unifier.ip_index
context_partner
subst
in
begin
match candidate_type with
| Context_unifier.Close
| Context_unifier.CloseAssert
| Context_unifier.All ->
move_updated_input_literal
context_unifier_space input_partner context_partner config;
| Context_unifier.Assert
| Context_unifier.Split ->
()
end;
close_found || close_found'
end
let add_to_problem_literal
(problem_literals: problem_literals)
(problem_literal: problem_literal)
(context_element: Context.element)
(candidate_type: Context_unifier.candidate_type)
(close_found: bool)
subst
: bool =
if is_problem_literal_subsumed_at ~directly:false problem_literals problem_literal context_element then begin
close_found
end
else begin
try
let close_found =
ref close_found
in
let (_: (input_partner * context_partner * context_partner option) option) =
Elements.fold
(fun _ element cache ->
match cache with
| None ->
if is_input_partner_resolved_at element.input_partner context_element then begin
raise Exit
end
else begin
let resolved : context_partner option =
resolve problem_literals element.input_partner context_element
in
let context_partner =
match resolved with
| Some partner ->
partner
| None ->
let subst =
Subst.replace_offset
subst
1
(Subst.context_literal_offset element.input_partner.Context_unifier.ip_index)
in
create_context_partner
problem_literals element.input_partner context_element subst
in
Stack.push element.input_partner.Context_unifier.ip_context_partners context_partner;
List.iter
(fun space ->
if is_space_subsumed_at problem_literals space context_element then
()
else begin
close_found :=
add_to_clause problem_literals.config problem_literals.bound
problem_literals.context space
element.input_partner context_partner candidate_type !close_found
end
)
element.spaces;
Some (element.input_partner, context_partner, resolved)
end
| Some (cached_input_partner, cached_context_partner, cached_resolved) ->
let new_context_partner =
match cached_resolved with
| Some _ ->
mark_resolved problem_literals element.input_partner context_element
| None ->
clone_context_partner problem_literals cached_context_partner
cached_input_partner element.input_partner
in
Stack.push element.input_partner.Context_unifier.ip_context_partners new_context_partner;
List.iter
(fun space ->
if is_space_subsumed_at problem_literals space context_element then
()
else begin
close_found :=
add_to_clause problem_literals.config problem_literals.bound problem_literals.context space
element.input_partner new_context_partner candidate_type !close_found
end
)
element.spaces;
cache
)
problem_literal.elements
None
in
!close_found
with
| Exit ->
close_found
end
let add (problem_literals: problem_literals)
(context_element: Context.element) (candidate_type: Context_unifier.candidate_type) : unit =
match candidate_type with
| Context_unifier.Assert
| Context_unifier.Split ->
failwith "Problem_literals.add"
| Context_unifier.Close
| Context_unifier.CloseAssert
| Context_unifier.All ->
subsume problem_literals context_element;
let unifying_candidates =
let index =
problem_literals.index#find (Term.request_negated_literal ~insert_db:false context_element.Context.el_literal)
in
index#find_all_unifiable_subst ~p_preserving:false context_element.Context.el_literal.Term.atom
in
ignore (
List.fold_left
(fun close_found (problem_literal, subst) ->
add_to_problem_literal
problem_literals
problem_literal
context_element
candidate_type
close_found
subst
)
false
unifying_candidates
: bool)
let compute_deferred' (problem_literals: problem_literals) (candidate_type: Context_unifier.candidate_type)
: unit =
problem_literals.index#iter
(fun _ index ->
index#iter
(fun _ problem_literal ->
Elements.iter
(fun _ element ->
Stack.iter
(fun context_partner ->
if
Context.element_equal context_partner.Context_unifier.cp_element Context.plus_v_element
||
Context.element_equal context_partner.Context_unifier.cp_element Context.minus_v_element
then
()
else if is_problem_literal_subsumed_at ~directly:false
problem_literals problem_literal context_partner.Context_unifier.cp_element then
()
else if is_input_partner_resolved_at
element.input_partner context_partner.Context_unifier.cp_element then
()
else
List.iter
(fun space ->
if is_space_subsumed_at problem_literals space context_partner.Context_unifier.cp_element then
()
else begin
ignore (
add_to_clause problem_literals.config problem_literals.bound problem_literals.context space
element.input_partner context_partner candidate_type false
: bool);
end
)
element.spaces;
)
element.input_partner.Context_unifier.ip_context_partners
)
problem_literal.elements
)
)
let compute_deferred (problem_literals: problem_literals) (candidate_type: Context_unifier.candidate_type) : unit =
match candidate_type with
| Context_unifier.Close
| Context_unifier.CloseAssert
| Context_unifier.All ->
failwith "Problem_literals.compute_deferred"
| Context_unifier.Assert
| Context_unifier.Split ->
compute_deferred' problem_literals candidate_type
let compute_for_element (problem_literals: problem_literals) (context_element: Context.element)
(candidate_type: Context_unifier.candidate_type) : unit =
let unifying_candidates =
let index =
problem_literals.index#find (Term.request_negated_literal ~insert_db:false context_element.Context.el_literal)
in
index#find_all_unifiable ~p_preserving:false context_element.Context.el_literal.Term.atom
in
List.iter
(fun problem_literal ->
if is_problem_literal_subsumed_at ~directly:false
problem_literals problem_literal context_element then
()
else
Elements.iter
(fun _ element ->
if is_input_partner_resolved_at element.input_partner context_element then
()
else begin
try
let context_partner =
Stack.find
element.input_partner.Context_unifier.ip_context_partners
(fun x ->
compare
context_element.Context.el_id
x.Context_unifier.cp_element.Context.el_id
)
in
List.iter
(fun space ->
if is_space_subsumed_at problem_literals space context_partner.Context_unifier.cp_element then
()
else begin
ignore (
add_to_clause problem_literals.config problem_literals.bound problem_literals.context space
element.input_partner context_partner candidate_type false
: bool);
end
)
element.spaces;
with
| Not_found ->
()
end
)
problem_literal.elements
)
unifying_candidates
let backtrack (problem_literals: problem_literals) : unit =
let unneeded_bindings =
Bindings.fold
(fun _ (binding, choice_point) acc ->
if State.is_choice_point_invalid choice_point then
binding :: acc
else
acc
)
problem_literals.bindings
[]
in
List.iter
(Bindings.remove problem_literals.bindings)
unneeded_bindings;
let context_id =
try
(Context.most_recent_element problem_literals.context).Context.el_id
with
| Not_found ->
-1
in
for i = 0 to Array.length problem_literals.subsumed_clauses - 1 do
if
problem_literals.subsumed_clauses.(i) >= 0
&&
problem_literals.subsumed_clauses.(i) > context_id
then
problem_literals.subsumed_clauses.(i) <- -1;
done;
problem_literals.index#iter
(fun _ index ->
index#iter
(fun _ problem_literal ->
if
problem_literal.subsumed_at >= 0
&&
problem_literal.subsumed_at > context_id
then begin
problem_literal.subsumed_at <- -1;
end;
Elements.iter
(fun _ element ->
begin
match element.input_partner.Context_unifier.ip_resolved with
| Some context_partner when
State.is_choice_point_invalid
context_partner.Context_unifier.cp_element.Context.el_choice_point ->
Context_unifier.set_resolved element.input_partner None
| _ ->
()
end;
let rec remove_invalid_context_partner () =
if Stack.size element.input_partner.Context_unifier.ip_context_partners = 0 then
()
else begin
let context_partner =
Stack.top element.input_partner.Context_unifier.ip_context_partners
in
if State.is_choice_point_invalid
context_partner.Context_unifier.cp_element.Context.el_choice_point
then begin
Stack.remove_top element.input_partner.Context_unifier.ip_context_partners;
begin
match context_partner.Context_unifier.cp_partial_context_unifier with
| Some subst when
Subst.is_empty subst ->
problem_literals.cached_partial_context_unifiers <-
problem_literals.cached_partial_context_unifiers - 1;
| _ ->
()
end;
remove_invalid_context_partner ()
end
else
()
end
in
remove_invalid_context_partner ();
)
problem_literal.elements;
)
)