39 cerr <<
"Don't do this with an Empty FOF!" << endl;
74 if (
type == FOFType::Empty) {
75 cerr <<
"Don't do this with an Empty FOF!" << endl;
78 if (
type == FOFType::Atom) {
83 f.replace_variable(new_var, old_var);
93 Literal lit(name, args, args.size(),
true);
106 if (
type == FOFType::And ||
107 ((
type == FOFType::Or) && (and_location == s))) {
111 for (
size_t i = 0; i < s; i++) {
120 vector<FOF> and_fof_subs =
sub_formulas[and_location].sub_formulas;
121 if (and_location != (s-1)) {
130 size_t s2 = and_fof_subs.size();
131 vector<FOF> new_sub_formulas_2;
132 for (
int i = 0; i < s2; i++) {
133 vector<FOF> new_sub_formulas;
134 new_sub_formulas.push_back(f);
135 new_sub_formulas.push_back(and_fof_subs[i]);
136 new_sub_formulas_2.push_back(
FOF::make_or(new_sub_formulas));
157 size_t or_location =
find_or();
159 if (
type == FOFType::Or ||
160 ((
type == FOFType::And) && (or_location == s))) {
164 for (
size_t i = 0; i < s; i++) {
173 vector<FOF> or_fof_subs =
sub_formulas[or_location].sub_formulas;
174 if (or_location != (s-1)) {
183 size_t s2 = or_fof_subs.size();
184 vector<FOF> new_sub_formulas_2;
185 for (
int i = 0; i < s2; i++) {
186 vector<FOF> new_sub_formulas;
187 new_sub_formulas.push_back(f);
188 new_sub_formulas.push_back(or_fof_subs[i]);
189 new_sub_formulas_2.push_back(
FOF::make_and(new_sub_formulas));
212 if (
type == FOFType::Empty) {
213 cerr <<
"Don't do this with an Empty FOF!" << endl;
216 if (
type == FOFType::Atom) {
221 f.replace_variable_with_term(new_term, old_var);
229 FOF f(FOFType::Atom);
238 sub_formulas[0].skolemize_main(skolem_arguments, whole_f, tptp);
245 g.skolemize_main(skolem_arguments, whole_f, tptp);
249 sub_formulas[0].skolemize_main(skolem_arguments, whole_f, tptp);
264 recs_p->add_skolemization_record(f_s, var_s, sk_t_s, sk_s);
277 FOF f(FOFType::Atom);
286 sub_formulas[0].skolemize_universals_main(skolem_arguments, whole_f, tptp);
293 g.skolemize_universals_main(skolem_arguments, whole_f, tptp);
297 sub_formulas[0].skolemize_universals_main(skolem_arguments, whole_f, tptp);
312 recs_p->add_herbrandization_record(f_s, var_s, sk_t_s, sk_s);
325 vector<FOF>& absent) {
330 for (
size_t i = 0; i < subs.size(); i++) {
352 type = FOFType::Atom;
358 Literal lit_copy = lit;
359 lit_copy.make_positive();
361 sub_formulas.push_back(f);
373 cerr <<
"Stop it! You can't make an atom with this constructor!" << endl;
381 if (
var !=
nullptr) {
382 cerr <<
"Are you sure you want to associate a variable with something that's not a quantifier?" << endl;
388 if (sf.size() != 1) {
389 cerr <<
"Careful! A quantifier should only have one subformula." << endl;
392 cerr <<
"Careful! A quantifier needs a variable." << endl;
403 return (
type == FOFType::Atom) ||
411 if (!(
type == FOFType::Or)) {
425 if (
type == FOFType::Neg) {
432 if (
type == FOFType::Empty) {
433 cerr <<
"Don't do this with an Empty FOF!" << endl;
436 if (
type == FOFType::Imp) {
440 else if (
type == FOFType::Neg) {
463 if (
type == FOFType::Atom) {
471 cerr <<
"Don't use this with a non-literal." << endl;
475 if (
type == FOFType::Empty) {
476 cerr <<
"Don't do this with an Empty FOF!" << endl;
480 if (
type == FOFType::Atom)
483 if (
type == FOFType::Iff) {
486 lhs.
type = FOFType::Imp;
487 rhs.
type = FOFType::Imp;
502 if (
type == FOFType::Empty) {
503 cerr <<
"Don't do this with an Empty FOF!" << endl;
507 if (
type == FOFType::Atom)
510 if (
type == FOFType::Imp) {
530 sf.make_unique_bound_variables();
555 sf.remove_redundant_quantifiers();
614 cerr <<
"Stop it!!! You don't push negations through -> or <->." << endl;
631 cerr <<
"Stop it!!! You don't push negations through -> or <->." << endl;
639 if (
type == FOFType::Empty) {
640 cerr <<
"Don't do this with an Empty FOF!" << endl;
651 FOF new_sub(FOFType::Empty);
652 vector<FOF> new_subs;
656 cerr <<
"Don't do this with an empty formula" << endl;
667 cerr <<
"Don't do this unless you've removed -> and <->" << endl;
686 if (free.size() ==
sub_formulas[0].sub_formulas.size()) {
687 for (
size_t i = 0; i < free.size(); i++) {
692 new_subs.push_back(new_sub);
699 else if (free.size() > 0) {
701 if (free.size() == 1)
719 if (absent.size() == 0)
721 else if (free.size() > 0) {
724 if (free.size() == 1)
756 if (free.size() ==
sub_formulas[0].sub_formulas.size()) {
757 for (
size_t i = 0; i < free.size(); i++) {
762 new_subs.push_back(new_sub);
768 else if (free.size() > 0) {
770 if (free.size() == 1)
788 if (absent.size() == 0)
790 else if (free.size() !=
sub_formulas[0].sub_formulas.size()) {
793 if (free.size() == 1)
818 if (
type == FOFType::Empty) {
819 cerr <<
"Don't do this with an Empty FOF!" << endl;
823 cout <<
"Remove iff:" << endl;
827 cout << *
this << endl;
828 cout <<
"Remove imp" << endl;
832 cout << *
this << endl;
833 cout <<
"Push negs:" << endl;
836 recs_p->add_fof_inference_record(
"fof_nnf,[status(thm)]",
840 cout << *
this << endl;
841 cout <<
"Make unique vars:" << endl;
844 recs_p->add_fof_inference_record(
"variable_rename,[status(thm)]",
847 cout << *
this << endl;
848 cout <<
"Remove redundant quantifiers:" << endl;
852 cout << *
this << endl;
853 cout <<
"Miniscope:" << endl;
855 if (params::miniscope) {
858 recs_p->add_fof_inference_record(
"miniscope,[status(thm)]",
861 cout << *
this << endl;
862 cout <<
"Skolemize:" << endl;
866 cout << *
this << endl;
867 cout <<
"Remove universal quantifiers:" << endl;
871 cout << *
this << endl;
872 cout <<
"Distribute or:" << endl;
876 cout << *
this << endl;
877 cout <<
"Convert to clauses:" << endl;
880 for (
const Clause& c : cs) {
882 if (_role !=
string(
"negated_conjecture"))
884 string name =
recs_p->add_clause_record(c, role);
885 _names.push_back(name);
888 cout << *
this << endl;
907 size_t left_size = s / 2;
908 for (
size_t i = 0; i < left_size; i++) {
911 for (
size_t i = left_size; i < s; i++) {
933 if (left.size() > 1) {
936 if (right.size() > 1) {
940 FOF new_f_1(FOFType::Empty);
941 FOF new_f_2(FOFType::Empty);
945 if (in_conjunction &&
type == FOFType::Or) {
950 d_preds.push_back(def);
954 args1.push_back(def);
955 args1.push_back(new_f_1);
958 args2.push_back(def);
959 args2.push_back(new_f_2);
961 for (
const FOF& g : new_d_1) {
964 for (
const FOF& g : new_d_2) {
970 bool is_and(
type == FOFType::And);
973 vector<FOF> new_args;
974 new_args.push_back(new_f_1);
975 new_args.push_back(new_f_2);
976 FOF new_f(
type, new_args,
nullptr);
979 for (
const FOF& g : new_d_2){
985 if (
type == FOFType::Empty) {
986 cerr <<
"Don't do this with an Empty FOF!" << endl;
1000 recs_p->add_fof_inference_record(
"def_negate,[status(cth)]",
1007 recs_p->add_fof_inference_record(
"fof_nnf,[status(thm)]",
1012 recs_p->add_fof_inference_record(
"variable_rename,[status(thm)]",
1024 FOF f(FOFType::Empty);
1026 vector<FOF> d_preds;
1038 for (
FOF& formula : d) {
1039 vector<Clause> new_cs;
1040 formula.distribute_and();
1041 formula.dnf_invert_and_convert_to_clauses(new_cs);
1042 for (
const Clause& new_c : new_cs) {
1043 cs.push_back(new_c);
1056 string tptp_fof_string(
"( ");
1057 int remaining = cs.size();
1058 for (
const Clause& c : cs) {
1059 tptp_fof_string += c.to_tptp_fof_string();
1060 if (--remaining > 0) {
1061 tptp_fof_string +=
" & ";
1064 tptp_fof_string +=
" )";
1069 string role = _role;
1070 if (_role !=
string(
"negated_conjecture"))
1074 if (d_preds.size() > 0) {
1077 for (
const FOF& f : d_preds) {
1079 def_symbols += com();
1083 recs_p->add_definitional_record(tptp_fof_string, def_symbols);
1087 for (
const Clause& c : cs) {
1088 string name =
recs_p->add_clause_record(c, role);
1089 _names.push_back(name);
1094 vector<Term*> skolem_arguments;
1099 vector<Term*> skolem_arguments;
1104 FOF f(FOFType::Atom);
1116 g.remove_universal_quantifiers();
1132 FOF f(FOFType::Atom);
1144 g.remove_existential_quantifiers();
1160 if (
type == FOFType::Atom) {
1176 cs.push_back(new_c);
1179 if (
type == FOFType::Or) {
1182 cs.push_back(new_c);
1185 for (
size_t j = 0; j < c[0].size(); j++) {
1186 cs[0].add_lit((c[0])[j]);
1191 if (
type == FOFType::And) {
1195 for (
size_t j = 0; j < c.size();j++) {
1211 cs.push_back(new_c);
1215 if (
type == FOFType::And) {
1218 cs.push_back(new_c);
1221 for (
size_t j = 0; j < c[0].size(); j++) {
1222 cs[0].add_lit((c[0])[j]);
1228 if (
type == FOFType::Or) {
1232 for (
size_t j = 0; j < c.size();j++) {
1241 for (
size_t i = 0; i < s; i++) {
1251 for (
size_t i = 0; i < s; i++) {
1276 result = unicode_symbols::LogSym::neg;
1284 result += g.to_string();
1287 result += unicode_symbols::LogSym::and_sym;
1297 result += g.to_string();
1300 result += unicode_symbols::LogSym::or_sym;
1311 result += unicode_symbols::LogSym::ifthen;
1320 result += unicode_symbols::LogSym::iff;
1326 result = unicode_symbols::LogSym::forall;
1333 result = unicode_symbols::LogSym::exists;
1349 bool nested =
false;
1363 result += g.to_tptp_string();
1376 result += g.to_tptp_string();
1439 if (
type != FOFType::Atom) {
1440 cerr <<
"You should only be doing this with an atom!" << endl;
1448 vector<string>& roles,
1449 vector<string>& names) {
1450 vector<Clause> new_cnf;
1451 vector<string> new_roles;
1452 vector<string> new_names;
1453 bool cnf_is_contradiction =
false;
1457 SimplificationResult result = c.
simplify();
1458 if (result == SimplificationResult::Tautology) {
1459 recs_p->add_tf_clause_record(names[i], roles[i],
"$true");
1463 if (result == SimplificationResult::Contradiction) {
1464 cnf_is_contradiction =
true;
1465 recs_p->add_tf_clause_record(names[i], roles[i],
"$false");
1469 new_cnf.push_back(c);
1470 new_roles.push_back(roles[i]);
1472 new_names.push_back(names[i]);
1475 string new_name =
recs_p->add_clause_record(c, roles[i], names[i]);
1476 new_names.push_back(new_name);
1483 if (cnf_is_contradiction)
1484 return SimplificationResult::Contradiction;
1485 if (cnf.size() == 0)
1486 return SimplificationResult::Tautology;
1487 return SimplificationResult::OK;
1491 vector<Clause> new_cnf;
1492 bool cnf_is_contradiction =
false;
1494 SimplificationResult result = c.simplify();
1495 if (result == SimplificationResult::Tautology)
1497 if (result == SimplificationResult::Contradiction) {
1498 cnf_is_contradiction =
true;
1501 new_cnf.push_back(c);
1504 if (cnf_is_contradiction)
1505 return SimplificationResult::Contradiction;
1506 if (cnf.size() == 0)
1507 return SimplificationResult::Tautology;
1508 return SimplificationResult::OK;
1516 case FOFType::Empty:
1517 cerr <<
"You shouldn't be doing this with an FOFType::Empty!" << endl;
1521 free = p->all_variables();
1522 result.insert(free.begin(), free.end());
1531 free = f.find_free_variables();
1532 result.insert(free.begin(), free.end());
1539 result.erase(to_remove);
1547ostream& operator<<(ostream& out,
const FOF& f) {
Representation of clauses.
SimplificationResult simplify()
Simplify a clause by dealing with $true, $false, complementary literals, and duplicates.
void add_lit(const Literal &)
Add a literal, making sure you don't duplicate.
Representation of first order formulas.
void skolemize()
Skolemize the given formula.
void remove_iff()
Replace <-> throughout using ->.
static FOF make_or(const vector< FOF > &fs)
Directly make a disjunction.
void miniscope_all()
Apply miniscoping to all subformulas.
size_t find_or() const
Does the collection of subformulas contain an OR? If so, find it.
static VariableIndex * var_index
Access to the index: static because all FOFs should share it.
void convert_to_nnf()
Convert to Negation Normal Form.
void clear()
Make an FOFType::Empty.
string to_tptp_string(bool=false) const
Convert a FOF into a nice-looking string in the TPTP format.
void dnf_invert_and_convert_to_clauses(vector< Clause > &) const
Assuming you have a DNF, invert it and convert it to a collection of CNF clauses.
set< Term * > find_free_variables() const
Find the free variables in the formula.
void remove_redundant_quantifiers()
Remove quantifiers if they don't bind anything in their scope.
void miniscope_split(Variable *, vector< FOF > &, vector< FOF > &)
Helper for miniscope.
void split_sub_formulas(vector< FOF > &, vector< FOF > &)
Split subformulas in half.
void make_unique_bound_variables()
Replace all bound variables with unique new ones.
static SimplificationResult simplify_cnf(vector< Clause > &)
Simplify the clauses in a CNF using the method in Clause.
void remove_universal_quantifiers()
Self-explanatory.
void skolemize_main(vector< Term * >, FOF *, bool=false)
Main helper function called by FOF::skolemize().
Variable * var
Associate a Variable with a quantifier.
bool distribute_or_once()
Find an OR that can be distributed and deal with it. Indicate if there isn't one.
FOFType type
Used for all FOFs to denote what kind it it.
static FOF make_and(const vector< FOF > &fs)
Directly make a conjunction.
void miniscope()
Apply the rules for miniscoping.
void push_negs()
Push all negations in.
bool distribute_and_once()
Find an AND that can be distributed and deal with it. Indicate if there isn't one.
bool has_free_variable(Variable *)
Does this formula contain the specified variable unbound?
void skolemize_universals()
Skolemize the universal quantifiers in the given formula.
void replace_variable(Variable *, Variable *)
Self-explanatory.
vector< FOF > sub_formulas
Most FOFs will have subformulas.
void to_Literal(Literal &) const
Assuming the FOF is a literal, convert it to something of type Literal.
FOF make_definitional_predicate() const
When doing definitional clause conversion you need to be able to make unique new predicates....
static FOF make_exists(const FOF &f, Variable *v)
Directly make an existentially quantified FOF.
void definitional_convert_to_cnf_clauses(vector< Clause > &, vector< string > &, const string &)
Convert to Conjunctive Normal Form using a form of definitional conversion.
static TermIndex * term_index
Access to the index: static because all FOFs should share it.
void remove_negation()
Remove the leading negation from an arbitrary FOF, if it has one.
static PredicateIndex * pred_index
Access to the index: static because all FOFs should share it.
static FOF make_forall(const FOF &f, Variable *v)
Directly make a universally quantified FOF.
void convert_to_clauses(vector< Clause > &) const
Assuming you have a CNF, convert it to a collection of Clauses.
void remove_imp()
Replace A->B throughout with neg A v B.
size_t find_and() const
Does the collection of subformulas contain an AND? If so, find it.
static FunctionIndex * fun_index
Access to the index: static because all FOFs should share it.
FOF()=delete
You don't want this constructor.
void distribute_and()
Distribute ANDs to the maximum extent possible.
Term * make_skolem_function(const vector< Term * > &)
Make a new Skolem function.
void distribute_or()
Distribute ORs to the maximum extent possible.
static TPTPRecords * recs_p
Allow FOF to add TPTP outputs.
void convert_to_cnf_clauses(vector< Clause > &, vector< string > &, const string &)
Convert to Conjunctive Normal Form.
void find_definitional_tuple(FOF &, vector< FOF > &, vector< FOF > &, bool)
Heavy-lifting for conversion to definitional clause form.
void simple_negate()
Negate an FOF without applying any simplifications.
bool is_literal() const
Check if an FOF is a literal.
void skolemize_universals_main(vector< Term * >, FOF *, bool=false)
The dual of skolemize_main.
string to_string() const
Convert a FOF into a nice-looking string.
void negate()
Negate an FOF, applying obvious simplifications if it's already negated or an implication.
string predicate_to_tptp_string() const
Assuming this is an Atom, return the predicate name as a string.
void remove_existential_quantifiers()
Self-explanatory.
void invert_literal()
Self-explanatory!
bool is_clause() const
Check if something is a clause.
Literal pred
FOFType::Atom can store one of these to represent a Literal.
void replace_variable_with_term(Term *, Variable *)
Replace a Variable with a Term.
Basic representation of functions.
string get_name() const
Most basic access function.
Mechanism for looking after functions.
Function * make_skolem_function(Arity)
Add a new Skolem function. Naming is automatic.
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
void replace_variable_with_term(Term *, Variable *, TermIndex *)
Replace one variable with a term throughout.
const vector< Term * > & get_args() const
Basic get method.
string to_string(bool=false) const
Full conversion of Literal to string.
bool contains_variable(Variable *) const
Does this Literal contain the specified variable?
void replace_variable(Variable *, Variable *, TermIndex *)
Replace one variable with another throughout.
bool is_positive() const
Basic manipulation - entirely self-explanatory.
string to_tptp_string(bool=false) const
Convert to a string in a format compatible with the TPTP.
void invert()
Basic manipulation - entirely self-explanatory.
void clear()
Basic manipulation - entirely self-explanatory.
void make_negative()
Basic manipulation - entirely self-explanatory.
Predicate * get_pred() const
Basic get method.
Basic representation of predicates: here just names, ids and arities.
string to_tptp_string() const
At present returns only the name.
Management of Predicate objects.
Predicate * make_definitional_predicate(Arity arity)
Make a new, unique definitional predicate.
Class collecting a bunch of TPTPRecord items for later formatting.
General representation of terms.
Function * get_f() const
Self-explanatory access function.
string to_prolog_string(bool=false) const
Convert to a string that can be read by Prolog.
Look after terms, using hash consing to avoid storing copies of terms.
Term * add_function_term(Function *, const vector< Term * > &)
Self-explanatory: add a Term containing a function to the index.
Term * add_variable_term(Variable *)
Self-explanatory: add a Term containing a variable to the index.
Basic representation of variables.
string to_prolog_string(bool=false) const
Convert to a Prolog string.
string to_string(bool=false) const
Convert to a (coloured) string.
Storage of named variables, and management of new, anonymous and unique variables.
Variable * add_unique_var()
Add a unique variable when converting to CNF.
Simple function object for putting commas in lists.