type literal = Term.literal
type clause = Term.clause
type subst = Subst.subst
exception EMPTY_CLAUSE of (clause * clause)
class data =
object
method is_equal (l1, c1, (_: int)) (l2, c2, (_: int)) =
Term.literal_equal l1 l2 && Term.clause_equal c1 c2
method to_string (l, c, (_: int)) =
Term.literal_to_string l ^ " : " ^ Term.clause_to_string c
end
let rec compute_resolvents_for_clause ~(print:bool)
(index: (literal * clause * int) Term_indexing.index)
(resolvents: clause list) (number_of_resolvents: int)
(clause: clause) :
clause list * int =
let length =
List.length clause
in
let rec create_part_resolvent clause literal offset =
match clause with
| [] ->
[]
| literal' :: tail ->
if Term.literal_equal literal literal' then
create_part_resolvent tail literal offset
else
(literal', offset) :: create_part_resolvent tail literal offset
in
List.fold_left
(fun (resolvents, number_of_resolvents) literal ->
if number_of_resolvents >= Const.resolvents_max_number then
(resolvents, number_of_resolvents)
else begin
let unifiable =
(index#find (Term.request_negated_literal ~insert_db:false literal))#find_all_unifiable_subst
~p_preserving:false literal.Term.atom
in
List.fold_left
(fun (resolvents, number_of_resolvents) ((literal', clause', length'), unifier) ->
if number_of_resolvents >= Const.resolvents_max_number then
(resolvents, number_of_resolvents)
else if length + length' > Const.resolvent_max_size + 2 then
(resolvents, number_of_resolvents)
else begin
let left =
create_part_resolvent clause literal Term_indexing.query_offset
and right =
create_part_resolvent clause' literal' Term_indexing.index_offset
in
let resolvent =
Subst.apply_to_literals unifier (left @ right)
in
let resolvent =
Term.remove_duplicates resolvent
in
if List.length resolvent > Const.resolvent_max_size then
(resolvents, number_of_resolvents)
else if Term.is_tautology resolvent then
(resolvents, number_of_resolvents)
else if List.exists (fun clause' -> Term.clause_equal resolvent clause') resolvents then
(resolvents, number_of_resolvents)
else begin
let resolvent =
Subst.normalize_clause (Term.sort_clause resolvent)
in
if print then begin
print_endline ("RESOLVENT: " ^ Term.clause_to_string resolvent);
print_endline (Term.literal_to_string literal ^ "-->: " ^ Term.clause_to_string clause);
print_endline (Term.literal_to_string literal' ^ "-->: " ^ Term.clause_to_string clause');
print_endline (Subst.subst_to_string unifier);
print_newline ();
end;
begin
match resolvent with
| [] ->
raise (EMPTY_CLAUSE (clause, clause'))
| _ ->
(resolvent :: resolvents, number_of_resolvents + 1)
end;
end
end
)
(resolvents, number_of_resolvents)
unifiable
end
)
(resolvents, number_of_resolvents)
clause
let compute_resolvents ~(print:bool) (clauses: clause list) : clause list =
if print then begin
print_endline ("Preprocessing: Computing resolvents of size <= " ^ string_of_int Const.resolvent_max_size);
end;
let index =
Discrimination_tree.create_index false (new data)
in
List.iter
(fun clause ->
let length =
List.length clause
in
if length <= Const.resolvent_max_size + 1 then begin
List.iter
(fun literal ->
(index#find literal)#add literal.Term.atom (literal, clause, length)
)
clause
end;
)
clauses;
let resolvents, _ =
List.fold_left
(fun (resolvents, number_of_resolvents) clause ->
if number_of_resolvents >= Const.resolvents_max_number then
(resolvents, number_of_resolvents)
else if List.length clause <= Const.resolvent_max_size + 1 then
compute_resolvents_for_clause ~print:print
index resolvents number_of_resolvents clause
else
(resolvents, number_of_resolvents)
)
([], 0)
clauses
in
let resolvents =
List.find_all
(fun resolvent ->
List.for_all
(fun clause -> not (Term.clause_equal resolvent clause))
clauses
)
resolvents
in
let resolvents =
Tools.list_first Const.resolvents_max_number
(
List.sort
(fun x y ->
let length =
Tools.compare_int (List.length x) (List.length y)
in
if length != 0 then
length
else
Tools.compare_int (Term_attributes.weight_of_clause x) (Term_attributes.weight_of_clause y)
)
resolvents
)
in
let resolvents', _ =
List.fold_left
(fun (resolvents, number_of_resolvents) clause ->
if number_of_resolvents >= Const.resolvents_max_number then
(resolvents, number_of_resolvents)
else if List.length clause <= Const.resolvent_max_size + 1 then
compute_resolvents_for_clause ~print:print
index resolvents number_of_resolvents clause
else
(resolvents, number_of_resolvents)
)
([], 0)
resolvents
in
let resolvents' =
List.find_all
(fun resolvent ->
List.for_all
(fun clause -> not (Term.clause_equal resolvent clause))
clauses
)
resolvents'
in
let resolvents' =
List.find_all
(fun resolvent ->
List.for_all
(fun clause -> not (Term.clause_equal resolvent clause))
resolvents
)
resolvents'
in
let resolvents =
Tools.list_first Const.resolvents_max_number
(
List.sort
(fun x y ->
let length =
Tools.compare_int (List.length x) (List.length y)
in
if length != 0 then
length
else
Tools.compare_int (Term_attributes.weight_of_clause x) (Term_attributes.weight_of_clause y)
)
resolvents' @ resolvents
)
in
if print then begin
print_newline ();
end;
resolvents