(*
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.
*)
type symbol = Symbol.symbol
type var = Var.var
type term = Term.term
type literal = Term.literal
type clause = Term.clause
exception EMPTY_CLAUSE of clause
(*
Disequalities
1) -(x = t) \/ C -> C{x -> t} where t a term or variable and x not in t
2) -(t = t) \/ C -> C where t a term or variable
*)
let rec apply_disequality (clause: clause) =
(* try to find a disequality in to_check and apply it *)
let rec apply_disequality' (to_check: clause) : clause =
match to_check with
| [] ->
(* no more suitable disequality found *)
begin
match clause with
| [] ->
(* clause has been simplified to the empty clause
because no disequality was satisfiable *)
raise (EMPTY_CLAUSE clause)
| _ ->
clause
end;
| literal :: tail ->
(* skip - not a negative disequality *)
if literal.Term.sign then
apply_disequality' tail
else begin
match literal.Term.atom with
| Term.Func func when
Symbol.equal Symbol.equality func.Term.symbol ->
(* drop the literal: -(t = t) *)
if Term.term_equal func.Term.subterms.(0) func.Term.subterms.(1) then begin
let clause' =
List.find_all
(fun literal' -> not (Term.literal_equal literal literal'))
clause
in
apply_disequality clause'
end
(* a suitable disequality: -(x = t) *)
else begin
match func.Term.subterms.(0), func.Term.subterms.(1) with
| Term.Var var, term
| term, Term.Var var ->
(* keep the literal: -(x = t(x)) *)
if Term.term_contains_var term var then begin
apply_disequality' tail
end
(* try to apply the disequality *)
else begin
let clause'' =
apply_disequality'' clause literal var term
in
apply_disequality clause''
end
| _ ->
(* skip - an inequality between non-variable terms *)
apply_disequality' tail
end
| _ ->
(* skip - not a disequality *)
apply_disequality' tail
end
in
apply_disequality' clause
(* apply the literal -(var = term) to the clause *)
and apply_disequality'' clause literal var term : clause =
match clause with
| [] ->
[]
| literal' :: tail ->
(* skip the disequality to remove *)
if Term.literal_equal literal literal' then
apply_disequality'' tail literal var term
(* optimization: don't create a new term
if the variable to replace does not occur in it *)
else if not (Term.literal_contains_var literal' var) then
literal' :: apply_disequality'' tail literal var term
(* apply disequality *)
else
let literal'' =
Term.replace_vars_in_literal
literal'
(fun var' term' ->
if Var.equal var var' then
term
else
term'
)
in
literal'' :: apply_disequality'' tail literal var term
let rec simplify' ~(print: bool) (clauses: clause list) : clause list =
match clauses with
| [] ->
[]
| clause :: tail ->
begin
try
(* inline disequalities *)
let clause' =
apply_disequality clause
in
(* remove tautologies *)
if Term.is_tautology clause' then begin
if print then begin
print_endline ("Tautology: " ^ Term.clause_to_string clause);
(* print simplification, if done *)
if clause != clause' then
print_endline ("--> : " ^ Term.clause_to_string clause');
print_newline ();
end;
simplify' ~print:print tail
end
(* no simplification, keep original clause *)
else if clause == clause' then begin
clause :: simplify' ~print:print tail
end
(* keep simplified clause *)
else begin
if print then begin
print_endline ("Transform: " ^ Term.clause_to_string clause);
print_endline ("---> " ^ Term.clause_to_string clause');
print_newline ();
end;
(Subst.normalize_clause (Term.sort_clause clause')) :: simplify' ~print:print tail
end;
with
| EMPTY_CLAUSE _ ->
raise (EMPTY_CLAUSE clause)
end
let simplify ~(print: bool) (clauses: clause list) : clause list =
if print then begin
print_endline ("Preprocessing: Ground Splitting");
end;
let clauses' =
simplify' ~print:print clauses
in
if print then begin
print_newline ();
end;
clauses'