(*
This file is part of the first order theorem prover Darwin
Copyright (C) 2006
The University of Iowa
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)
(*** types ***) |
type literal = Term.literal
type clause = Term.clause
(*** functions ***) |
(* remove pure clauses.
returns remaining clauses and pure literals.
if [fix] is given purification is repeated until a fixpoint is reached. *)
let purify ~(print: bool) ~(fix: bool)
(is_pure: clause -> literal -> bool) (clauses: clause list)
: clause list * literal list =
let rec purify' (purified: clause list) (pure: literal list) (clauses: clause list) (fix_reached: bool)
: clause list * literal list =
match clauses with
| [] ->
if fix && not fix_reached then
purify' [] pure (List.rev purified) true
else
List.rev purified, List.rev pure
| clause :: tail ->
begin
try
let pure_literal =
List.find (fun literal -> is_pure clause literal) clause
in
if print then begin
print_endline ("Pure: " ^ Term.literal_to_string pure_literal ^ " --> " ^ Term.clause_to_string clause);
end;
purify' purified (pure_literal :: pure) tail false
with
| Not_found ->
purify' (clause :: purified) pure tail fix_reached
end
in
purify' [] [] clauses true
let simplify ~(print:bool) ~(equality:bool) (clauses: clause list) : clause list * literal list =
if print then begin
print_endline ("Preprocessing: Pure Literals");
end;
(* for equality we can not go by unification,
or perhaps somewhat if we take sorts (Sort_inference) into account.
currently pure is detected by predicate symbol polarity only.
*)
if equality then begin
(* keep from each predicate symbol a mapping index -> contained in claused *)
let index =
Term.LiteralTypeTable.create 1024
in
(* now register all clauses *)
List.iter
(fun clause ->
List.iter
(fun literal ->
let entry =
try
Term.LiteralTypeTable.find index literal
with
| Not_found ->
let new_entry =
ref []
in
Term.LiteralTypeTable.add index literal new_entry;
new_entry
in
entry := clause :: !entry;
)
clause
)
clauses;
(* all unifiable literals must be from the clause itself *)
let is_pure (clause: clause) (literal: literal) : bool =
let matching =
Term.LiteralTypeTable.find index (Term.request_negated_literal literal)
in
List.for_all
(fun clause' -> clause == clause')
!matching
in
(* now check for each clause if one of its literals is pure,
i.e. its negation is not unifiable with a literal from another clause. *)
let purified, pure_literals =
purify ~print:print ~fix:true is_pure clauses
in
if print then begin
print_newline ();
end;
purified, pure_literals
end
(* purity check via unifying literals *)
else begin
(* keep from each literal a mapping index -> contained in claused *)
let index =
Discrimination_tree.create_clause_index false
in
(* now register all clauses *)
List.iter
(fun clause ->
List.iter
(fun literal ->
(index#find literal)#add literal.Term.atom clause
)
clause
)
clauses;
(* all unifiable literals must be from the clause itself *)
let is_pure (clause: clause) (literal: literal) : bool =
let unifiable =
(index#find (Term.request_negated_literal ~insert_db:false literal))#find_all_unifiable
~p_preserving:false literal.Term.atom
in
List.for_all
(fun clause' -> clause == clause')
unifiable
in
(* now check for each clause if one of its literals is pure,
i.e. its negation is not unifiable with a literal from another clause. *)
let purified, pure_literals =
purify ~print:print ~fix:false is_pure clauses
in
if print then begin
print_newline ();
end;
purified, pure_literals
end