38 cerr <<
"Don't do this with an Empty FOF!" << endl;
73 if (
type == FOFType::Empty) {
74 cerr <<
"Don't do this with an Empty FOF!" << endl;
77 if (
type == FOFType::Atom) {
82 f.replace_variable(new_var, old_var);
92 Literal lit(name, args, args.size(),
true);
105 if (
type == FOFType::And ||
106 ((
type == FOFType::Or) && (and_location == s))) {
110 for (
size_t i = 0; i < s; i++) {
119 vector<FOF> and_fof_subs =
sub_formulas[and_location].sub_formulas;
120 if (and_location != (s-1)) {
129 size_t s2 = and_fof_subs.size();
130 vector<FOF> new_sub_formulas_2;
131 for (
int i = 0; i < s2; i++) {
132 vector<FOF> new_sub_formulas;
133 new_sub_formulas.push_back(f);
134 new_sub_formulas.push_back(and_fof_subs[i]);
135 new_sub_formulas_2.push_back(
FOF::make_or(new_sub_formulas));
156 size_t or_location =
find_or();
158 if (
type == FOFType::Or ||
159 ((
type == FOFType::And) && (or_location == s))) {
163 for (
size_t i = 0; i < s; i++) {
172 vector<FOF> or_fof_subs =
sub_formulas[or_location].sub_formulas;
173 if (or_location != (s-1)) {
182 size_t s2 = or_fof_subs.size();
183 vector<FOF> new_sub_formulas_2;
184 for (
int i = 0; i < s2; i++) {
185 vector<FOF> new_sub_formulas;
186 new_sub_formulas.push_back(f);
187 new_sub_formulas.push_back(or_fof_subs[i]);
188 new_sub_formulas_2.push_back(
FOF::make_and(new_sub_formulas));
211 if (
type == FOFType::Empty) {
212 cerr <<
"Don't do this with an Empty FOF!" << endl;
215 if (
type == FOFType::Atom) {
220 f.replace_variable_with_term(new_term, old_var);
226 FOF f(FOFType::Atom);
238 g.skolemize_main(skolem_arguments);
258 FOF f(FOFType::Atom);
263 sub_formulas[0].skolemize_universals_main(skolem_arguments);
270 g.skolemize_universals_main(skolem_arguments);
274 sub_formulas[0].skolemize_universals_main(skolem_arguments);
279 sub_formulas[0].skolemize_universals_main(skolem_arguments);
292 vector<FOF>& absent) {
297 for (
size_t i = 0; i < subs.size(); i++) {
319 type = FOFType::Atom;
340 cerr <<
"Stop it! You can't make an atom with this constructor!" << endl;
348 if (
var !=
nullptr) {
349 cerr <<
"Are you sure you want to associate a variable with something that's not a quantifier?" << endl;
355 if (sf.size() != 1) {
356 cerr <<
"Careful! A quantifier should only have one subformula." << endl;
359 cerr <<
"Careful! A quantifier needs a variable." << endl;
370 return (
type == FOFType::Atom) ||
378 if (!(
type == FOFType::Or)) {
392 if (
type == FOFType::Neg) {
399 if (
type == FOFType::Empty) {
400 cerr <<
"Don't do this with an Empty FOF!" << endl;
403 if (
type == FOFType::Imp) {
407 else if (
type == FOFType::Neg) {
430 if (
type == FOFType::Atom) {
438 cerr <<
"Don't use this with a non-literal." << endl;
442 if (
type == FOFType::Empty) {
443 cerr <<
"Don't do this with an Empty FOF!" << endl;
447 if (
type == FOFType::Atom)
450 if (
type == FOFType::Iff) {
453 lhs.
type = FOFType::Imp;
454 rhs.
type = FOFType::Imp;
469 if (
type == FOFType::Empty) {
470 cerr <<
"Don't do this with an Empty FOF!" << endl;
474 if (
type == FOFType::Atom)
477 if (
type == FOFType::Imp) {
497 sf.make_unique_bound_variables();
522 sf.remove_redundant_quantifiers();
581 cerr <<
"Stop it!!! You don't push negations through -> or <->." << endl;
598 cerr <<
"Stop it!!! You don't push negations through -> or <->." << endl;
606 if (
type == FOFType::Empty) {
607 cerr <<
"Don't do this with an Empty FOF!" << endl;
618 FOF new_sub(FOFType::Empty);
619 vector<FOF> new_subs;
623 cerr <<
"Don't do this with an empty formula" << endl;
634 cerr <<
"Don't do this unless you've removed -> and <->" << endl;
653 if (free.size() ==
sub_formulas[0].sub_formulas.size()) {
654 for (
size_t i = 0; i < free.size(); i++) {
659 new_subs.push_back(new_sub);
666 else if (free.size() > 0) {
668 if (free.size() == 1)
686 if (absent.size() == 0)
688 else if (free.size() > 0) {
691 if (free.size() == 1)
723 if (free.size() ==
sub_formulas[0].sub_formulas.size()) {
724 for (
size_t i = 0; i < free.size(); i++) {
729 new_subs.push_back(new_sub);
735 else if (free.size() > 0) {
737 if (free.size() == 1)
755 if (absent.size() == 0)
757 else if (free.size() !=
sub_formulas[0].sub_formulas.size()) {
760 if (free.size() == 1)
785 if (
type == FOFType::Empty) {
786 cerr <<
"Don't do this with an Empty FOF!" << endl;
790 cout <<
"Remove iff:" << endl;
794 cout << *
this << endl;
795 cout <<
"Remove imp" << endl;
799 cout << *
this << endl;
800 cout <<
"Push negs:" << endl;
804 cout << *
this << endl;
805 cout <<
"Make unique vars:" << endl;
809 cout << *
this << endl;
810 cout <<
"Remove redundant quantifiers:" << endl;
814 cout << *
this << endl;
815 cout <<
"Miniscope:" << endl;
817 if (params::miniscope) {
821 cout << *
this << endl;
822 cout <<
"Skolemize:" << endl;
826 cout << *
this << endl;
827 cout <<
"Remove universal quantifiers:" << endl;
831 cout << *
this << endl;
832 cout <<
"Distribute or:" << endl;
836 cout << *
this << endl;
837 cout <<
"Convert to clauses:" << endl;
841 cout << *
this << endl;
860 size_t left_size = s / 2;
861 for (
size_t i = 0; i < left_size; i++) {
864 for (
size_t i = left_size; i < s; i++) {
886 if (left.size() > 1) {
889 if (right.size() > 1) {
893 FOF new_f_1(FOFType::Empty);
894 FOF new_f_2(FOFType::Empty);
898 if (in_conjunction &&
type == FOFType::Or) {
905 args1.push_back(def);
906 args1.push_back(new_f_1);
909 args2.push_back(def);
910 args2.push_back(new_f_2);
912 for (
const FOF& g : new_d_1) {
915 for (
const FOF& g : new_d_2) {
921 bool is_and(
type == FOFType::And);
924 vector<FOF> new_args;
925 new_args.push_back(new_f_1);
926 new_args.push_back(new_f_2);
927 FOF new_f(
type, new_args,
nullptr);
930 for (
const FOF& g : new_d_2){
936 if (
type == FOFType::Empty) {
937 cerr <<
"Don't do this with an Empty FOF!" << endl;
963 FOF f(FOFType::Empty);
976 for (
FOF& formula : d) {
977 vector<Clause> new_cs;
978 formula.distribute_and();
979 formula.dnf_invert_and_convert_to_clauses(new_cs);
980 for (
const Clause& new_c : new_cs) {
987 vector<Term*> skolem_arguments;
992 vector<Term*> skolem_arguments;
997 FOF f(FOFType::Atom);
1009 g.remove_universal_quantifiers();
1025 FOF f(FOFType::Atom);
1037 g.remove_existential_quantifiers();
1053 if (
type == FOFType::Atom) {
1069 cs.push_back(new_c);
1072 if (
type == FOFType::Or) {
1075 cs.push_back(new_c);
1078 for (
size_t j = 0; j < c[0].size(); j++) {
1079 cs[0].add_lit((c[0])[j]);
1084 if (
type == FOFType::And) {
1088 for (
size_t j = 0; j < c.size();j++) {
1104 cs.push_back(new_c);
1108 if (
type == FOFType::And) {
1111 cs.push_back(new_c);
1114 for (
size_t j = 0; j < c[0].size(); j++) {
1115 cs[0].add_lit((c[0])[j]);
1121 if (
type == FOFType::Or) {
1125 for (
size_t j = 0; j < c.size();j++) {
1134 for (
size_t i = 0; i < s; i++) {
1144 for (
size_t i = 0; i < s; i++) {
1169 result = unicode_symbols::LogSym::neg;
1177 result += g.to_string();
1180 result += unicode_symbols::LogSym::and_sym;
1190 result += g.to_string();
1193 result += unicode_symbols::LogSym::or_sym;
1204 result += unicode_symbols::LogSym::ifthen;
1213 result += unicode_symbols::LogSym::iff;
1219 result = unicode_symbols::LogSym::forall;
1226 result = unicode_symbols::LogSym::exists;
1239 vector<string>& roles) {
1240 vector<Clause> new_cnf;
1241 vector<string> new_roles;
1242 bool cnf_is_contradiction =
false;
1245 SimplificationResult result = c.simplify();
1246 if (result == SimplificationResult::Tautology) {
1250 if (result == SimplificationResult::Contradiction) {
1252 cnf_is_contradiction =
true;
1255 new_cnf.push_back(c);
1256 new_roles.push_back(roles[i]);
1261 if (cnf_is_contradiction)
1262 return SimplificationResult::Contradiction;
1263 if (cnf.size() == 0)
1264 return SimplificationResult::Tautology;
1265 return SimplificationResult::OK;
1269 vector<Clause> new_cnf;
1270 bool cnf_is_contradiction =
false;
1272 SimplificationResult result = c.simplify();
1273 if (result == SimplificationResult::Tautology)
1275 if (result == SimplificationResult::Contradiction) {
1276 cnf_is_contradiction =
true;
1279 new_cnf.push_back(c);
1282 if (cnf_is_contradiction)
1283 return SimplificationResult::Contradiction;
1284 if (cnf.size() == 0)
1285 return SimplificationResult::Tautology;
1286 return SimplificationResult::OK;
1294 case FOFType::Empty:
1295 cerr <<
"You shouldn't be doing this with an FOFType::Empty!" << endl;
1299 free = p->all_variables();
1300 result.insert(free.begin(), free.end());
1309 free = f.find_free_variables();
1310 result.insert(free.begin(), free.end());
1317 result.erase(to_remove);
1325ostream& operator<<(ostream& out,
const FOF& f) {
Representation of clauses.
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.
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 convert_to_cnf_clauses(vector< Clause > &)
Convert to Conjunctive Normal Form.
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 skolemize_main(vector< Term * >)
Main helper function called by FOF::skolemize().
void remove_universal_quantifiers()
Self-explanatory.
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 definitional_convert_to_cnf_clauses(vector< Clause > &)
Convert to Conjunctive Normal Form using a form of definitional conversion.
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.
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 skolemize_universals_main(vector< Term * >)
The dual of skolemize_main.
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.
void find_definitional_tuple(FOF &, vector< FOF > &, bool)
Heavy-lifting for conversion to definitional clause form.
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.
void simple_negate()
Negate an FOF without applying any simplifications.
bool is_literal() const
Check if an FOF is a literal.
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.
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.
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 make_positive()
Basic manipulation - entirely self-explanatory.
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.
void invert()
Basic manipulation - entirely self-explanatory.
void clear()
Basic manipulation - entirely self-explanatory.
void make_negative()
Basic manipulation - entirely self-explanatory.
Basic representation of predicates: here just names, ids and arities.
Management of Predicate objects.
Predicate * make_definitional_predicate(Arity arity)
Make a new, unique definitional predicate.
General representation of terms.
Look after terms, (ideally) 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_string(bool=false) const
Convert to a (coloured) string.
Storage of named variables, and management of new, anonymous variables.
Variable * add_unique_var()
Add a unique variable when converting to CNF.