type symbol = Symbol.symbol
type var = Var.var
type term = Term.term
type literal = Term.literal
type clause = Term.clause
type problem = Problem.problem
type arities = Problem.arities
type sorts = Sort_inference.sorts
class counter_data =
object
method is_equal (x0, x1: term * int) (y0, y1: term * int) =
Term.term_equal x0 y0
&&
x1 == y1
method to_string (x, y) =
Term.term_to_string x ^ " : " ^ string_of_int y
end
class definition_data =
object
method is_equal (x0, x1) (y0, y1) =
Term.term_equal x0 y0
&&
Term.term_equal x1 y1
method to_string (x, y) =
Term.term_to_string x ^ " : " ^ Term.term_to_string y
end
type term_definitions = {
definitions : (term * term) Term_indexing.index;
mutable new_definitions: clause list;
mutable function_arities: arities;
mutable constants: (symbol * symbol) list;
}
type finite_domain = {
original: problem;
flattened: problem;
sorts: sorts;
term_definitions: term_definitions;
}
let create_equality (left: term) (right: term) : term =
Term.request_func (Symbol.equality, [| left; right |])
let create_pos_equality (left: term) (right: term) : literal =
Term.request_literal
true
(create_equality left right)
let create_neg_equality (left: term) (right: term) : literal =
Term.request_literal
false
(create_equality left right)
let to_diff_literal literal =
if not Const.fd_use_diff then
literal
else
match literal.Term.atom with
| Term.Func func when Symbol.equal Symbol.equality func.Term.symbol ->
Term.request_literal
(not literal.Term.sign)
(Term.request_func (Symbol.diff, func.Term.subterms ))
| _ ->
literal
let to_diff_clause clause =
List.map to_diff_literal clause
let is_flat term =
match term with
| Term.Func func ->
Tools.array_for_all
(fun term' ->
match term' with
| Term.Var _ -> true
| _ -> false
)
func.Term.subterms
| _ ->
true
let scan_clauses (clauses: clause list) : term Term_indexing.index =
let occurrences =
Discrimination_tree.create_term_index false
in
let rec scan_term term =
match term with
| Term.Func func ->
if Term.is_term_ground term then begin
let index =
occurrences#find (Term.request_literal ~insert_db:false true term)
in
let definition =
index#find_generalization ~p_preserving:true term
in
match definition with
| None ->
let instances =
index#find_all_instances ~p_preserving:true term
in
List.iter
(fun term ->
if not (index#remove term (Some term)) then
failwith "Finite_domain.find_term_definitions 1";
)
instances;
index#add term term
| Some _ ->
()
end;
Array.iter scan_term func.Term.subterms
| _ ->
()
in
List.iter
(fun clause ->
List.iter
(fun literal ->
match literal.Term.atom with
| Term.Func func ->
Array.iter scan_term func.Term.subterms
| _ ->
()
)
clause
)
clauses;
occurrences
let create_term_definitions ~(print: bool) (problem: problem) : term_definitions =
let term_definitions =
{
definitions = Discrimination_tree.create_index false (new definition_data);
new_definitions = [];
constants = [];
function_arities = problem#getFunctionArities;
}
in
if not Const.fd_use_term_definitions then begin
term_definitions
end
else begin
let occurrences =
scan_clauses problem#getClauses
in
occurrences#iter
(fun _ index ->
index#iter
(fun _ term ->
let normalized =
Subst.normalize_term term
in
let vars =
Term.vars_of_term normalized
in
let number_of_vars =
List.length vars
in
let symbol =
Symbol.create_skolem ~arity:number_of_vars ()
in
let definition =
Term.create_schema_term symbol
in
let var0, var1 =
Term.request_var (Var.create_universal number_of_vars),
Term.request_var (Var.create_universal (number_of_vars + 1))
in
let head =
create_pos_equality var0 var1
and left =
create_neg_equality definition var0
and right =
create_neg_equality normalized var1
in
let definition_clause =
head :: left :: right :: []
in
let index =
term_definitions.definitions#find (Term.request_literal ~insert_db:false true term)
in
index#add normalized (normalized, definition);
term_definitions.new_definitions <- definition_clause :: term_definitions.new_definitions;
if number_of_vars > 0 then begin
term_definitions.function_arities <- Problem.update_arities term_definitions.function_arities symbol;
end
else begin
match term with
| Term.Func func ->
term_definitions.constants <- (symbol, func.Term.symbol) :: term_definitions.constants;
| _ ->
failwith "Finite_domain.get_term_definition"
end;
if print then begin
print_endline ("Term-Def: " ^ Term.clause_to_string definition_clause);
end;
)
);
term_definitions
end
let rec get_term_definition ~(print: bool) (term: term) (definitions: term_definitions) : term =
let index =
definitions.definitions#find (Term.request_literal ~insert_db:false true term)
in
let definition =
index#find_generalization ~p_preserving:true term
in
match definition with
| Some (term', definition') ->
let subst =
Unification.match_terms ~recompute:true
term' 0
term 1
in
Subst.apply_to_term ~normalize:false subst definition' 0;
| None ->
term
let get_abstraction term abstractions fresh_var_id =
try
let (_, abstraction_var) =
List.find
(fun (term', _) -> Term.term_equal term term')
abstractions
in
abstraction_var, abstractions, [], fresh_var_id
with
| Not_found ->
let abstraction_var =
Term.request_var (Var.create_universal fresh_var_id)
in
let abstraction =
create_neg_equality term abstraction_var
in
abstraction_var,
((term, abstraction_var) :: abstractions),
[abstraction],
(fresh_var_id + 1)
let is_abstracted term abstractions =
List.exists
(fun (term', _) -> Term.term_equal term term')
abstractions
let abstract ~(print: bool) term abstractions definitions fresh_var_id =
let term' =
get_term_definition ~print:print term definitions
in
let abstraction_var', abstractions', fresh_literals, fresh_var_id' =
get_abstraction term' abstractions fresh_var_id
in
abstraction_var', abstractions', fresh_literals, fresh_var_id'
let rec break_equalities' ~(print: bool) (broken: clause) (to_break: clause)
(abstractions: (term * term) list) (definitions: term_definitions) (fresh_var_id: int)
: clause * (term * term) list * int =
match to_break with
| [] ->
broken, abstractions, fresh_var_id
| literal :: tail ->
begin
match literal.Term.atom with
| Term.Func func when
Symbol.equal Symbol.equality func.Term.symbol ->
begin
match func.Term.subterms.(0), func.Term.subterms.(1) with
| Term.Var _, Term.Var _ when
literal.Term.sign ->
break_equalities' ~print:print (literal :: broken) tail abstractions definitions fresh_var_id
| (Term.Var _ as var_term), term
| term, (Term.Var _ as var_term) ->
if not literal.Term.sign then begin
let oriented =
Term.request_literal
literal.Term.sign
(Term.request_func (func.Term.symbol, [| term; var_term |]))
in
break_equalities' ~print:print (oriented :: broken) tail
((term, var_term) :: abstractions) definitions fresh_var_id
end
else begin
let abstraction_var, abstractions', fresh_literals', fresh_var_id' =
abstract ~print:print term abstractions definitions fresh_var_id
in
let literal' =
create_pos_equality var_term abstraction_var
in
break_equalities' ~print:print (literal' :: broken) (fresh_literals' @ tail)
abstractions' definitions fresh_var_id'
end
| term1, term2 ->
let replace, keep =
if is_abstracted term2 abstractions then
term2, term1
else
term1, term2
in
let abstraction_var, abstractions', fresh_literals', fresh_var_id' =
abstract ~print:print replace abstractions definitions fresh_var_id
in
let literal' =
Term.request_literal
literal.Term.sign
(create_equality keep abstraction_var)
in
break_equalities' ~print:print broken (literal' :: fresh_literals' @ tail)
abstractions' definitions fresh_var_id'
end
| _ ->
break_equalities' ~print:print (literal :: broken) tail abstractions definitions fresh_var_id
end
let break_equalities ~(print: bool) (clause: clause) (definitions: term_definitions) (fresh_var_id: int)
: clause * (term * term) list * int =
break_equalities' ~print:print [] clause [] definitions fresh_var_id
let rec flatten_at ~(print: bool) (i : int) symbol subterms to_flatten abstractions definitions fresh_var_id :
term array * literal list * (term * term) list * int =
if i >= Array.length subterms then begin
subterms, to_flatten, abstractions, fresh_var_id
end
else begin
let term =
subterms.(i)
in
if
Symbol.equal Symbol.equality symbol
&&
i = 0
then begin
match term with
| Term.Var _
| Term.Const _ ->
flatten_at ~print:print (i + 1) symbol subterms to_flatten abstractions definitions fresh_var_id
| Term.Func func' ->
let subterms', to_flatten', abstractions', fresh_var_id' =
flatten_at ~print:print 0 func'.Term.symbol func'.Term.subterms to_flatten abstractions definitions fresh_var_id
in
let subterms'' =
Array.copy subterms
in
subterms''.(i) <- Term.request_func (func'.Term.symbol, subterms');
flatten_at ~print:print (i + 1) symbol subterms'' to_flatten' abstractions' definitions fresh_var_id'
end
else begin
match term with
| Term.Var _ ->
flatten_at ~print:print (i + 1) symbol subterms to_flatten abstractions definitions fresh_var_id
| Term.Const _
| Term.Func _ ->
let abstraction_var, abstractions', fresh_literals', fresh_var_id' =
abstract ~print:print term abstractions definitions fresh_var_id
in
let subterms' =
Array.copy subterms
in
subterms'.(i) <- abstraction_var;
flatten_at ~print:print (i + 1) symbol subterms' (fresh_literals' @ to_flatten)
abstractions' definitions fresh_var_id'
end
end
let rec flatten' ~(print: bool) (flattened: clause) (to_flatten: clause)
(abstractions: (term * term) list) (definitions: term_definitions) (fresh_var_id: int) :
clause * int =
match to_flatten with
| [] ->
flattened, fresh_var_id
| literal :: tail ->
begin
match literal.Term.atom with
| Term.Func func ->
let term', to_flatten', abstractions', fresh_var_id' =
flatten_at ~print:print 0 func.Term.symbol func.Term.subterms tail abstractions definitions fresh_var_id
in
let flat =
Term.request_literal literal.Term.sign (Term.request_func (func.Term.symbol, term'))
in
flatten' ~print:print (flat :: flattened) to_flatten' abstractions' definitions fresh_var_id'
| Term.Var _
| Term.Const _ ->
flatten' ~print:print (literal :: flattened) tail abstractions definitions fresh_var_id
end
let flatten_clause ~(print:bool) (clause: clause) (abstractions: (term * term) list)
(definitions: term_definitions) (fresh_var_id: int) : clause * int =
flatten' ~print:print [] clause abstractions definitions fresh_var_id
let create_relation (sign: bool) (symbol: symbol) (subterms: term array) (result: term) : literal =
let arity =
Symbol.arity symbol
in
let relation_symbol =
Symbol.get_fd_relation (arity + 2)
in
let function_symbol =
Symbol.create_fd_symbol symbol
in
let relation_subterms =
Array.make (arity + 2) result
in
relation_subterms.(0) <- Term.request_const function_symbol;
Array.blit subterms 0 relation_subterms 1 arity;
let relation_term =
Term.request_func (relation_symbol, relation_subterms)
in
let relation_literal =
Term.request_literal sign relation_term
in
relation_literal
let rec make_relational (clause: clause) : clause =
match clause with
| [] ->
[]
| literal :: tail ->
begin
match literal.Term.atom with
| Term.Func func when
not literal.Term.sign
&&
Symbol.equal Symbol.equality func.Term.symbol
->
begin
match func.Term.subterms.(0) with
| Term.Var _ ->
failwith ("Finite_domain.make_relational: " ^ Term.literal_to_string literal);
| Term.Const symbol ->
let relation_literal =
create_relation literal.Term.sign symbol [| |] func.Term.subterms.(1)
in
relation_literal :: make_relational tail
| Term.Func func' ->
let relation_literal =
create_relation literal.Term.sign func'.Term.symbol func'.Term.subterms func.Term.subterms.(1)
in
relation_literal :: make_relational tail
end
| _ ->
literal :: make_relational tail
end
let rec find_pos_equality clause diff =
match clause with
| [] ->
diff
| literal :: tail ->
begin
match literal.Term.atom with
| Term.Func func when
literal.Term.sign
&&
Symbol.equal Symbol.equality func.Term.symbol ->
begin
match diff with
| None ->
find_pos_equality tail (Some literal)
| Some _ ->
None
end
| _ ->
find_pos_equality tail diff
end
let rec inline_pos_equality _clause clause equality var rep =
match clause with
| [] ->
None
| literal :: tail ->
begin
match literal.Term.atom with
| Term.Func func when
Symbol.is_fd_relation func.Term.symbol
&&
Term.term_equal func.Term.subterms.(Array.length func.Term.subterms - 1) var
->
if
List.exists
(fun literal' ->
not (Term.literal_equal literal' equality)
&&
not (Term.literal_equal literal' literal)
&&
Term.term_contains_term literal'.Term.atom var
)
_clause
then
None
else begin
let subterms' =
Array.copy func.Term.subterms
in
subterms'.(Array.length func.Term.subterms - 1) <- rep;
let literal' =
Term.request_literal
true
(Term.request_func (func.Term.symbol, subterms'))
in
let clause' =
List.find_all
(fun literal' ->
not (Term.literal_equal equality literal')
&&
not (Term.literal_equal literal literal')
)
_clause
in
Some (Subst.normalize_clause (Term.sort_clause (literal' :: clause')))
end
| _ ->
inline_pos_equality _clause tail equality var rep
end
let create_definitions (clause: clause) : clause list =
if List.exists (fun literal -> literal.Term.sign) clause then
[]
else begin
match find_pos_equality clause None with
| None ->
[]
| Some equality ->
begin
match equality.Term.atom with
| Term.Func func ->
let left_def =
inline_pos_equality clause clause equality func.Term.subterms.(0) func.Term.subterms.(1)
and right_def =
inline_pos_equality clause clause equality func.Term.subterms.(1) func.Term.subterms.(0)
in
begin
match left_def, right_def with
| None, None ->
[]
| None, Some definition
| Some definition, None ->
definition :: []
| Some definition1, Some definition2 ->
definition1 :: definition2 :: []
end
| _ ->
failwith "Finite_model.create_definitions"
end
end
let rec flatten ~(print: bool) (clauses: clause list) (term_definitions: term_definitions) : clause list =
match clauses with
| [] ->
[]
| clause :: tail ->
let fresh_var_id =
List.length (Term.vars_of_clause clause)
in
let clause_equalities_broken, abstractions, fresh_var_id =
break_equalities ~print:print clause term_definitions fresh_var_id
in
let flattened, _ =
flatten_clause ~print:print clause_equalities_broken abstractions term_definitions fresh_var_id
in
let relational =
make_relational flattened
in
let definitions =
if Const.fd_use_definitions then
create_definitions relational
else
[]
in
if print then begin
print_endline ("Clause : " ^ Term.clause_to_string clause);
print_endline ("EQ-Break: " ^ Term.clause_to_string clause_equalities_broken);
print_endline ("Flat : " ^ Term.clause_to_string flattened);
print_endline ("Relation: " ^ Term.clause_to_string relational);
List.iter
(fun definition ->
print_endline ("Definite: " ^ Term.clause_to_string definition);
)
definitions;
print_newline ();
end;
let relational_clause =
Subst.normalize_clause (Term.sort_clause relational)
in
let flattened_tail =
flatten ~print:print tail term_definitions
in
Tools.lists_merge
Term.clause_equal
(relational_clause :: flattened_tail)
definitions
let create ~(print_transformation: bool) ~(print_sorts: bool) (problem: problem) : finite_domain =
if print_transformation then begin
print_endline ("Finite domain flattening:");
print_newline ();
end;
let definitions =
create_term_definitions ~print:print_transformation problem
in
let flattened =
flatten ~print:print_transformation (definitions.new_definitions @ problem#getClauses) definitions
in
let flattened =
Preprocessing_split_nonground.split ~print:false flattened
in
let flattened =
List.map to_diff_clause flattened
in
let flattened_problem =
Problem.create ~equality:problem#containsEquality ~horn:false flattened []
in
let sorts =
Sort_inference.infer ~print:false problem#getClauses
in
List.iter
(fun (definition_symbol, term_symbol) ->
Sort_inference.add_constant sorts definition_symbol term_symbol
)
definitions.constants;
if print_sorts then
Sort_inference.print sorts;
{
original = problem;
flattened = flattened_problem;
sorts = sorts;
term_definitions = definitions;
}
let get_problem (finite_domain: finite_domain) : problem =
finite_domain.original
let get_flattened (finite_domain: finite_domain) : problem =
finite_domain.flattened
let get_sorts (finite_domain: finite_domain) : sorts =
finite_domain.sorts
let get_domain_size_marker (domain_size: int) : term =
if domain_size <= 0 then
failwith "get_domain_size_marker";
Term.request_const (Symbol.get_fd_size_marker domain_size)
let get_domain_element (number: int) : term =
if number <= 0 then
failwith "Finite_domain.get_domain_element";
let symbol =
Symbol.get_fd_element number
in
Term.request_const symbol
let get_domain_elements (domain_size: int) : term list =
let rec get_domain_elements (current_domain_size: int) : term list =
if current_domain_size > domain_size then
[]
else
(get_domain_element current_domain_size)
::
(get_domain_elements (current_domain_size + 1))
in
if domain_size <= 0 then
failwith "Finite_domain.get_domain_elements"
else
get_domain_elements 1
let get_domain_size_axioms ~(print: bool) ~(print_tptp: bool) (domain_size: int) : clause list =
let domain_size_marker =
Term.request_literal false (get_domain_size_marker domain_size)
in
let axiom =
[domain_size_marker]
in
if print then begin
print_endline ("Domain size axioms:");
print_endline (Term.clause_to_string axiom);
print_newline ();
end;
if print_tptp then begin
print_endline (
Term.tptp_clause_to_tptp_string
("domain_size")
axiom
)
end;
[axiom]
let get_symmetry_reduction_axioms (constant_symbols: symbol list list) (domain_size: int) : clause list =
let domain_size_marker =
Term.request_literal true (get_domain_size_marker domain_size)
in
let rec get_symmetry_reduction_axioms' (symbols: symbol list) (i : int) : clause list =
match symbols with
| [] ->
[]
| symbol :: tail ->
let axiom =
get_symmetry_reduction_axiom symbol i 1
in
axiom :: get_symmetry_reduction_axioms' tail (i + 1)
and get_symmetry_reduction_axiom (symbol: symbol) (symbol_domain_size: int) (i: int) : clause =
if i > symbol_domain_size then
[]
else if i > domain_size then
domain_size_marker :: []
else begin
let literal =
create_relation true symbol [| |] (get_domain_element i)
in
literal :: get_symmetry_reduction_axiom symbol symbol_domain_size (i + 1)
end
in
let axioms =
List.fold_left
(fun acc symbols ->
get_symmetry_reduction_axioms' symbols 1 @ acc
)
[]
(List.rev constant_symbols)
in
axioms
let get_totality_axioms ~(print: bool) ~(print_tptp: bool) (finite_domain: finite_domain) (domain_size: int) : clause list =
let domain_size_marker =
Term.request_literal true (get_domain_size_marker domain_size)
in
let rec get_totality_axioms' (arities': arities) : clause list =
match arities' with
| [] ->
[]
| (arity, symbols) :: tail ->
let axiom =
get_totality_axiom arity symbols 1
in
axiom :: get_totality_axioms' tail
and get_totality_axiom (arity: int) (symbols: symbol list) (i: int) : clause =
if i > domain_size then begin
domain_size_marker :: []
end
else begin
let subterms =
Array.make (arity + 2) (get_domain_element i)
in
for i = 0 to Array.length subterms - 2 do
subterms.(i) <- Term.request_var (Var.create_universal i);
done;
if Const.fd_instantiate_totality_axiom then begin
match symbols with
| symbol :: [] ->
subterms.(0) <- Term.request_const (Symbol.create_fd_symbol symbol);
| _ -> ()
end;
let relation_term =
Term.request_func (Symbol.get_fd_relation (arity + 2), subterms)
in
let relation_literal =
Term.request_literal true relation_term
in
relation_literal :: get_totality_axiom arity symbols (i + 1)
end
in
let constants_axioms =
if Const.fd_static_symmetry_reduction then
get_symmetry_reduction_axioms (Sort_inference.constants_partition finite_domain.sorts) domain_size
else
let constants =
(List.map fst finite_domain.term_definitions.constants) @ finite_domain.original#getConstantSymbols
in
get_totality_axioms' [(0, constants)]
in
let functions_axioms =
get_totality_axioms' finite_domain.term_definitions.function_arities
in
let axioms =
constants_axioms @ functions_axioms
in
if print then begin
print_endline ("Totality axioms:");
List.iter (fun axiom -> print_endline (Term.clause_to_string axiom)) axioms;
print_newline ();
end;
if print_tptp then begin
Array.iteri
(fun i axiom ->
print_endline (
Term.tptp_clause_to_tptp_string
("totality_" ^ string_of_int i)
axiom
)
)
(Array.of_list axioms);
end;
axioms
let get_canonicity_axioms ~(print: bool) ~(print_tptp: bool) (constant_symbols: symbol list list) (domain_size: int) : clause list =
let rec get_canonicity_axioms_for_domain_size (symbols: symbol array) (current_domain_size : int)
(current_symbol_index: int) : clause list =
if current_symbol_index > Array.length symbols then
[]
else
let rec get_axiom current_symbol_index' =
if current_symbol_index' = current_symbol_index then
let literal =
create_relation false symbols.(current_symbol_index' - 1)
[| |] (get_domain_element current_domain_size)
in
literal :: []
else
let literal =
create_relation true symbols.(current_symbol_index' - 1)
[| |] (get_domain_element (current_domain_size - 1))
in
literal :: get_axiom (current_symbol_index' + 1)
in
let axiom =
get_axiom (current_domain_size - 1)
in
axiom
::
get_canonicity_axioms_for_domain_size symbols current_domain_size (current_symbol_index + 1)
in
let rec get_canonicity_axioms' (symbols: symbol array) (current_domain_size : int) : clause list =
if current_domain_size > domain_size then
[]
else
let axioms =
get_canonicity_axioms_for_domain_size symbols current_domain_size current_domain_size
in
axioms @ get_canonicity_axioms' symbols (current_domain_size + 1)
in
let axioms =
List.fold_left
(fun acc symbols ->
get_canonicity_axioms' (Array.of_list symbols) 3 @ acc
)
[]
(List.rev constant_symbols)
in
if print then begin
print_endline ("Canonicity axioms:");
List.iter (fun axiom -> print_endline (Term.clause_to_string axiom)) axioms;
print_newline ();
end;
if print_tptp then begin
Array.iteri
(fun i axiom ->
print_endline (
Term.tptp_clause_to_tptp_string
("canonicity_" ^ string_of_int i)
axiom
)
)
(Array.of_list axioms);
end;
axioms
let get_functionality_axioms ~(print: bool) ~(print_tptp: bool) (finite_domain: finite_domain) (domain_size: int) : clause list =
let rec get_functionality_axioms_for_arity (arity: int) (current_domain_size: int) : clause list =
if current_domain_size >= domain_size then
[]
else begin
let rec get_functionality_axioms_for_arity' (current_domain_size': int) : clause list =
if current_domain_size' > domain_size then
[]
else
let subterms =
Array.make (arity + 2) Term.null_term
in
let subterms' =
Array.make (arity + 2) Term.null_term
in
for i = 0 to arity do
subterms.(i) <- Term.request_var (Var.create_universal i);
subterms'.(i) <- Term.request_var (Var.create_universal i);
done;
subterms.(arity + 1) <- get_domain_element current_domain_size;
subterms'.(arity + 1) <- get_domain_element current_domain_size';
let left =
Term.request_literal
false
(Term.request_func (Symbol.get_fd_relation (arity + 2), subterms))
and right =
Term.request_literal
false
(Term.request_func (Symbol.get_fd_relation (arity + 2), subterms'))
in
let axiom =
[ left; right ]
in
axiom :: get_functionality_axioms_for_arity' (current_domain_size' + 1)
in
let axioms =
get_functionality_axioms_for_arity' (current_domain_size + 1)
in
axioms @ get_functionality_axioms_for_arity arity (current_domain_size + 1)
end
in
let rec get_functionality_axioms' (arities': arities) : clause list =
match arities' with
| [] ->
[]
| (arity, _symbols) :: tail ->
(get_functionality_axioms_for_arity arity 1)
@
(get_functionality_axioms' tail)
in
let axioms =
(get_functionality_axioms_for_arity 0 1)
@
(get_functionality_axioms' finite_domain.term_definitions.function_arities)
in
if print then begin
print_endline ("Functionality axioms:");
List.iter (fun axiom -> print_endline (Term.clause_to_string axiom)) axioms;
print_newline ();
end;
if print_tptp then begin
Array.iteri
(fun i axiom ->
print_endline (
Term.tptp_clause_to_tptp_string
("functionality_" ^ string_of_int i)
axiom
)
)
(Array.of_list axioms);
end;
axioms
let get_equality_axioms ~(print: bool) ~(print_tptp: bool) (domain_size: int) : clause list =
let rec outer_loop i =
if i > domain_size then begin
[]
end
else begin
inner_loop i 1
end
and inner_loop i j =
if j > domain_size then
outer_loop (i + 1)
else if i = j then
inner_loop i (j + 1)
else
let diff =
create_neg_equality (get_domain_element i) (get_domain_element j)
in
[diff] :: inner_loop i (j + 1)
in
let reflexivity =
create_pos_equality
(Term.request_var (Var.create_universal 0))
(Term.request_var (Var.create_universal 0))
in
let axioms =
[reflexivity] :: outer_loop 1
in
if print then begin
print_endline ("Equality axioms:");
List.iter (fun axiom -> print_endline (Term.clause_to_string axiom)) axioms;
print_newline ();
end;
if print_tptp then begin
Array.iteri
(fun i axiom ->
print_endline (
Term.tptp_clause_to_tptp_string
("equality_" ^ string_of_int i)
axiom
)
)
(Array.of_list axioms);
end;
axioms
let get_axioms ~(print: bool) ~(print_tptp: bool) ~(use_functionality_axioms: bool)
(finite_domain: finite_domain) (domain_size: int) : clause list =
if print then begin
print_newline ();
print_endline ("Finite domain axioms for domain size " ^ string_of_int domain_size ^ ":");
print_newline ();
end;
let domain_size_axioms =
get_domain_size_axioms ~print:print ~print_tptp:print_tptp domain_size
and totality_axioms =
get_totality_axioms ~print:print ~print_tptp:print_tptp finite_domain domain_size
and canonicity_axioms =
if Const.fd_use_canonicity then
get_canonicity_axioms ~print:print ~print_tptp:print_tptp
(Sort_inference.constants_partition finite_domain.sorts) domain_size
else
[]
and functionality_axioms =
if use_functionality_axioms then
get_functionality_axioms ~print:print ~print_tptp:print_tptp finite_domain domain_size
else
[]
and equality_axioms =
if
finite_domain.original#containsEquality
||
not finite_domain.term_definitions.definitions#is_empty
then
get_equality_axioms ~print:print ~print_tptp:print_tptp domain_size
else
[]
in
let axioms =
List.map to_diff_clause
(domain_size_axioms @ totality_axioms @ canonicity_axioms @ functionality_axioms @ equality_axioms)
in
axioms
let relation_to_equations (finite_domain: finite_domain) (term: term) : term list =
match term with
| Term.Func func ->
if not (Symbol.is_fd_relation func.Term.symbol) then
term :: []
else begin
match func.Term.subterms.(0) with
| Term.Func _ ->
failwith ("Finite_domain.relation_to_equation: " ^ Term.term_to_string term)
| Term.Const symbol ->
let symbol' =
Symbol.get_symbol_from_fd_symbol symbol
in
let result =
func.Term.subterms.(Array.length func.Term.subterms - 1)
in
let function_term =
if Symbol.arity symbol' = 0 then
Term.request_const symbol'
else
let arguments =
Array.sub func.Term.subterms 1 (Array.length func.Term.subterms - 2)
in
Term.request_func (symbol', arguments)
in
Term.request_func (Symbol.equality, [| function_term; result |]) :: []
| Term.Var _ ->
let function_symbols =
Problem.get_arity
(get_problem finite_domain)#getFunctionArities
(Symbol.arity func.Term.symbol - 2)
in
List.map
(fun symbol ->
let result =
func.Term.subterms.(Array.length func.Term.subterms - 1)
in
let arguments =
Array.sub func.Term.subterms 1 (Array.length func.Term.subterms - 2)
in
let function_term =
Term.request_func (symbol, arguments)
in
Term.request_func (Symbol.equality, [| function_term; result |])
)
function_symbols
end
| _ ->
term :: []