Connect++ 0.4.0
A fast, readable connection prover for first-order logic.
Loading...
Searching...
No Matches
FOF Class Reference

Representation of first order formulas. More...

#include <FOF.hpp>

Collaboration diagram for FOF:

Public Member Functions

 FOF ()=delete
 You don't want this constructor.
 
 FOF (FOFType t)
 You probably don't want this constructor.
 
 FOF (const Literal &)
 Construct FOF from Literal.
 
 FOF (FOFType, const vector< FOF > &, Variable *)
 Construct FOF for a non-literal.
 
void show_indexes () const
 Show the indices.
 
FOFType fof_type ()
 Basic get method.
 
void add_formula (const FOF &f)
 Add a subformula.
 
void clear ()
 Make an FOFType::Empty.
 
bool is_literal () const
 Check if an FOF is a literal.
 
bool is_clause () const
 Check if something is a clause.
 
void remove_negation ()
 Remove the leading negation from an arbitrary FOF, if it has one.
 
void negate ()
 Negate an FOF, applying obvious simplifications if it's already negated or an implication.
 
void simple_negate ()
 Negate an FOF without applying any simplifications.
 
void invert_literal ()
 Self-explanatory!
 
void remove_iff ()
 Replace <-> throughout using ->.
 
void remove_imp ()
 Replace A->B throughout with neg A v B.
 
void make_unique_bound_variables ()
 Replace all bound variables with unique new ones.
 
void remove_redundant_quantifiers ()
 Remove quantifiers if they don't bind anything in their scope.
 
void push_negs ()
 Push all negations in.
 
void convert_to_nnf ()
 Convert to Negation Normal Form.
 
void miniscope ()
 Apply the rules for miniscoping.
 
void convert_to_cnf_clauses (vector< Clause > &)
 Convert to Conjunctive Normal Form.
 
void split_sub_formulas (vector< FOF > &, vector< FOF > &)
 Split subformulas in half.
 
void find_definitional_tuple (FOF &, vector< FOF > &, bool)
 Heavy-lifting for conversion to definitional clause form.
 
void definitional_convert_to_cnf_clauses (vector< Clause > &)
 Convert to Conjunctive Normal Form using a form of definitional conversion.
 
void skolemize ()
 Skolemize the given formula.
 
void remove_universal_quantifiers ()
 Self-explanatory.
 
void skolemize_universals ()
 Skolemize the universal quantifiers in the given formula.
 
void remove_existential_quantifiers ()
 Self-explanatory.
 
void to_Literal (Literal &) const
 Assuming the FOF is a literal, convert it to something of type Literal.
 
void convert_to_clauses (vector< Clause > &) const
 Assuming you have a CNF, convert it to a collection of Clauses.
 
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.
 
size_t find_and () const
 Does the collection of subformulas contain an AND? If so, find it.
 
size_t find_or () const
 Does the collection of subformulas contain an OR? If so, find it.
 
void distribute_or ()
 Distribute ORs to the maximum extent possible.
 
void distribute_and ()
 Distribute ANDs to the maximum extent possible.
 
string to_string () const
 Convert a FOF into a nice-looking string.
 
set< Term * > find_free_variables () const
 Find the free variables in the formula.
 

Static Public Member Functions

static void set_indexes (std::tuple< VariableIndex *, FunctionIndex *, PredicateIndex *, TermIndex * > is)
 Set up pointer to the variable index etc.
 
static FOF make_literal (const Literal &lit)
 Directly make a Literal.
 
static FOF make_neg (const FOF &f)
 Directly negate a FOF.
 
static FOF make_and (const vector< FOF > &fs)
 Directly make a conjunction.
 
static FOF make_or (const vector< FOF > &fs)
 Directly make a disjunction.
 
static FOF make_imp (const FOF &lhs, const FOF &rhs)
 Directly make an implication.
 
static FOF make_iff (const FOF &lhs, const FOF &rhs)
 Directly make an iff.
 
static FOF make_forall (const FOF &f, Variable *v)
 Directly make a universally quantified FOF.
 
static FOF make_exists (const FOF &f, Variable *v)
 Directly make an existentially quantified FOF.
 
static SimplificationResult simplify_cnf (vector< Clause > &)
 Simplify the clauses in a CNF using the method in Clause.
 
static SimplificationResult simplify_cnf (vector< Clause > &, vector< string > &)
 As first version of simplify_cnf, but keep track of corresponding roles as well.
 

Private Member Functions

bool has_free_variable (Variable *)
 Does this formula contain the specified variable unbound?
 
void replace_variable (Variable *, Variable *)
 Self-explanatory.
 
Termmake_skolem_function (const vector< Term * > &)
 Make a new Skolem function.
 
void replace_variable_with_term (Term *, Variable *)
 Replace a Variable with a Term.
 
void skolemize_main (vector< Term * >)
 Main helper function called by FOF::skolemize().
 
void skolemize_universals_main (vector< Term * >)
 The dual of skolemize_main.
 
void miniscope_split (Variable *, vector< FOF > &, vector< FOF > &)
 Helper for miniscope.
 
void miniscope_all ()
 Apply miniscoping to all subformulas.
 
FOF make_definitional_predicate () const
 When doing definitional clause conversion you need to be able to make unique new predicates. This will provide one.
 
bool distribute_or_once ()
 Find an OR that can be distributed and deal with it. Indicate if there isn't one.
 
bool distribute_and_once ()
 Find an AND that can be distributed and deal with it. Indicate if there isn't one.
 

Private Attributes

FOFType type
 Used for all FOFs to denote what kind it it.
 
Literal pred
 FOFType::Atom can store one of these to represent a Literal.
 
vector< FOFsub_formulas
 Most FOFs will have subformulas.
 
Variablevar
 Associate a Variable with a quantifier.
 

Static Private Attributes

static VariableIndexvar_index = nullptr
 Access to the index: static because all FOFs should share it.
 
static FunctionIndexfun_index = nullptr
 Access to the index: static because all FOFs should share it.
 
static TermIndexterm_index = nullptr
 Access to the index: static because all FOFs should share it.
 
static PredicateIndexpred_index = nullptr
 Access to the index: static because all FOFs should share it.
 

Friends

ostream & operator<< (ostream &, const FOF &)
 

Detailed Description

Representation of first order formulas.

First and foremost: I intensely dislike the use of inheritance. I vastly prefer to make the methods static and do everything the obvioous way. If you want the alternative sort of OO, then feel free to implement this yourself.

This has to play nicely with the parser and with the indexing of terms, variables and so on, so it needs pointers to the relevant indices.

Definition at line 57 of file FOF.hpp.

Constructor & Destructor Documentation

◆ FOF() [1/3]

FOF::FOF ( FOFType t)
inline

You probably don't want this constructor.

Definition at line 214 of file FOF.hpp.

215 : type(t), pred(), sub_formulas(), var(nullptr) {}
Variable * var
Associate a Variable with a quantifier.
Definition FOF.hpp:75
FOFType type
Used for all FOFs to denote what kind it it.
Definition FOF.hpp:62
vector< FOF > sub_formulas
Most FOFs will have subformulas.
Definition FOF.hpp:71
Literal pred
FOFType::Atom can store one of these to represent a Literal.
Definition FOF.hpp:67

◆ FOF() [2/3]

FOF::FOF ( const Literal & lit)

Construct FOF from Literal.

Parameters
litReference to Literal to use.

Definition at line 314 of file FOF.cpp.

315: sub_formulas()
316, var(nullptr)
317{
318 if (lit.is_positive()) {
319 type = FOFType::Atom;
320 pred = lit;
321 }
322 else {
323 pred.clear();
324 type = FOFType::Neg;
325 Literal lit_copy = lit;
326 lit_copy.make_positive();
327 FOF f(lit_copy);
328 sub_formulas.push_back(f);
329 }
330}
Representation of first order formulas.
Definition FOF.hpp:57
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
Definition Literal.hpp:50
void make_positive()
Basic manipulation - entirely self-explanatory.
Definition Literal.hpp:95
bool is_positive() const
Basic manipulation - entirely self-explanatory.
Definition Literal.hpp:87
void clear()
Basic manipulation - entirely self-explanatory.
Definition Literal.hpp:115

◆ FOF() [3/3]

FOF::FOF ( FOFType t,
const vector< FOF > & sf,
Variable * v )

Construct FOF for a non-literal.

Parameters
tSpecify FOFType for what you're making.
sfReference to vector of FOF for subformulas.
vPointer to Variable.

Definition at line 332 of file FOF.cpp.

333: type(t)
334, pred()
335, sub_formulas(sf)
336, var(v)
337{
338 switch (t) {
339 case FOFType::Atom:
340 cerr << "Stop it! You can't make an atom with this constructor!" << endl;
341 break;
342 case FOFType::Neg:
343 case FOFType::And:
344 case FOFType::Or:
345 case FOFType::Imp:
346 case FOFType::Iff:
347 // Easy as the work gets done above.
348 if (var != nullptr) {
349 cerr << "Are you sure you want to associate a variable with something that's not a quantifier?" << endl;
350 var = nullptr;
351 }
352 break;
353 case FOFType::A:
354 case FOFType::E:
355 if (sf.size() != 1) {
356 cerr << "Careful! A quantifier should only have one subformula." << endl;
357 }
358 if (v == nullptr) {
359 cerr << "Careful! A quantifier needs a variable." << endl;
360 }
361 break;
362 default:
363 break;
364 }
365}

Member Function Documentation

◆ add_formula()

void FOF::add_formula ( const FOF & f)
inline

Add a subformula.

Definition at line 261 of file FOF.hpp.

261{ sub_formulas.push_back(f); }

◆ clear()

void FOF::clear ( )
inline

Make an FOFType::Empty.

Definition at line 265 of file FOF.hpp.

265 {
266 type = FOFType::Empty;
267 pred.clear();
268 sub_formulas.clear();
269 var = nullptr;
270 }

◆ convert_to_clauses()

void FOF::convert_to_clauses ( vector< Clause > & cs) const

Assuming you have a CNF, convert it to a collection of Clauses.

Definition at line 1062 of file FOF.cpp.

1062 {
1063 cs.clear();
1064 if (is_literal()) {
1065 Literal new_lit;
1066 to_Literal(new_lit);
1067 Clause new_c;
1068 new_c.add_lit(new_lit);
1069 cs.push_back(new_c);
1070 return;
1071 }
1072 if (type == FOFType::Or) {
1073 vector<Clause> c;
1074 Clause new_c;
1075 cs.push_back(new_c);
1076 for (size_t i = 0; i < sub_formulas.size(); i++) {
1077 sub_formulas[i].convert_to_clauses(c);
1078 for (size_t j = 0; j < c[0].size(); j++) {
1079 cs[0].add_lit((c[0])[j]);
1080 }
1081 }
1082 return;
1083 }
1084 if (type == FOFType::And) {
1085 vector<Clause> c;
1086 for (size_t i = 0; i < sub_formulas.size(); i++) {
1087 sub_formulas[i].convert_to_clauses(c);
1088 for (size_t j = 0; j < c.size();j++) {
1089 cs.push_back(c[j]);
1090 }
1091 }
1092 }
1093}
Representation of clauses.
Definition Clause.hpp:52
void add_lit(const Literal &)
Add a literal, making sure you don't duplicate.
Definition Clause.cpp:87
void to_Literal(Literal &) const
Assuming the FOF is a literal, convert it to something of type Literal.
Definition FOF.cpp:1052
bool is_literal() const
Check if an FOF is a literal.
Definition FOF.cpp:369

◆ convert_to_cnf_clauses()

void FOF::convert_to_cnf_clauses ( vector< Clause > & cs)

Convert to Conjunctive Normal Form.

Follow the usual recipe (Larry's lecture notes.) BUT there are lots of ways to do this—at present there is nothing sophisticated happening, and the approach is entirely obvious/straightforward. Also, this implementation does miniscoping.

Parameters
csvector of clauses containing the CNF.

Definition at line 784 of file FOF.cpp.

784 {
785 if (type == FOFType::Empty) {
786 cerr << "Don't do this with an Empty FOF!" << endl;
787 return;
788 }
789#ifdef DEBUGOUTPUT
790 cout << "Remove iff:" << endl;
791#endif
792 remove_iff();
793#ifdef DEBUGOUTPUT
794 cout << *this << endl;
795 cout << "Remove imp" << endl;
796#endif
797 remove_imp();
798#ifdef DEBUGOUTPUT
799 cout << *this << endl;
800 cout << "Push negs:" << endl;
801#endif
802 push_negs();
803#ifdef DEBUGOUTPUT
804 cout << *this << endl;
805 cout << "Make unique vars:" << endl;
806#endif
808#ifdef DEBUGOUTPUT
809 cout << *this << endl;
810 cout << "Remove redundant quantifiers:" << endl;
811#endif
813#ifdef DEBUGOUTPUT
814 cout << *this << endl;
815 cout << "Miniscope:" << endl;
816#endif
817 if (params::miniscope) {
818 miniscope();
819 }
820#ifdef DEBUGOUTPUT
821 cout << *this << endl;
822 cout << "Skolemize:" << endl;
823#endif
824 skolemize();
825#ifdef DEBUGOUTPUT
826 cout << *this << endl;
827 cout << "Remove universal quantifiers:" << endl;
828#endif
830#ifdef DEBUGOUTPUT
831 cout << *this << endl;
832 cout << "Distribute or:" << endl;
833#endif
835#ifdef DEBUGOUTPUT
836 cout << *this << endl;
837 cout << "Convert to clauses:" << endl;
838#endif
840#ifdef DEBUGOUTPUT
841 cout << *this << endl;
842#endif
843}
void skolemize()
Skolemize the given formula.
Definition FOF.cpp:986
void remove_iff()
Replace <-> throughout using ->.
Definition FOF.cpp:441
void remove_redundant_quantifiers()
Remove quantifiers if they don't bind anything in their scope.
Definition FOF.cpp:511
void make_unique_bound_variables()
Replace all bound variables with unique new ones.
Definition FOF.cpp:486
void remove_universal_quantifiers()
Self-explanatory.
Definition FOF.cpp:996
void miniscope()
Apply the rules for miniscoping.
Definition FOF.cpp:615
void push_negs()
Push all negations in.
Definition FOF.cpp:540
void convert_to_clauses(vector< Clause > &) const
Assuming you have a CNF, convert it to a collection of Clauses.
Definition FOF.cpp:1062
void remove_imp()
Replace A->B throughout with neg A v B.
Definition FOF.cpp:468
void distribute_or()
Distribute ORs to the maximum extent possible.
Definition FOF.cpp:1152

◆ convert_to_nnf()

void FOF::convert_to_nnf ( )

Convert to Negation Normal Form.

Follows the usual recipe (Larry's lecture notes.)

Definition at line 605 of file FOF.cpp.

605 {
606 if (type == FOFType::Empty) {
607 cerr << "Don't do this with an Empty FOF!" << endl;
608 return;
609 }
610 remove_iff();
611 remove_imp();
612 push_negs();
613}

◆ definitional_convert_to_cnf_clauses()

void FOF::definitional_convert_to_cnf_clauses ( vector< Clause > & cs)

Convert to Conjunctive Normal Form using a form of definitional conversion.

There are lots of ways of doing definitional conversion. However as the restricted backtracking paper describing leanCoP v2.1 gives experimental results demonstrating that a particular approach is preferred, this implements the method as described in that paper.

Parameters
csvector of clauses containing the CNF.
See also
find_definitional_tuple

Definition at line 935 of file FOF.cpp.

935 {
936 if (type == FOFType::Empty) {
937 cerr << "Don't do this with an Empty FOF!" << endl;
938 return;
939 }
940 /*
941 * Note that the description in the restricted backtracking paper produces a
942 * DNF and starts with a Skolemized NNF of the original formula, *not* its
943 * negation. As the difference between this and the current representation, for
944 * connection calculusm ir just that all the literals get negated, this could
945 * be done more efficiently, but for now I'm going to just do a direct
946 * implementation of the procedure described in the paper. So: negate
947 * first, produce a DNF, then negate again.
948 */
950 remove_iff();
951 remove_imp();
952 push_negs();
955 /*
956 * As we're producing a DNF, we skolemize universals and then remove existentials.
957 */
960 /*
961 * Now we do the definitional magic.
962 */
963 FOF f(FOFType::Empty);
964 vector<FOF> d;
965 find_definitional_tuple(f, d, false);
966 /*
967 * f is a DNF so we can invert it and flatten it to
968 * the required CNF.
969 */
970 f.dnf_invert_and_convert_to_clauses(cs);
971 /*
972 * Each element of d now needs to be converted using
973 * a standard conversion, then inverted and transformed
974 * to CNF.
975 */
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) {
981 cs.push_back(new_c);
982 }
983 }
984}
void skolemize_universals()
Skolemize the universal quantifiers in the given formula.
Definition FOF.cpp:991
void find_definitional_tuple(FOF &, vector< FOF > &, bool)
Heavy-lifting for conversion to definitional clause form.
Definition FOF.cpp:869
void simple_negate()
Negate an FOF without applying any simplifications.
Definition FOF.cpp:420
void remove_existential_quantifiers()
Self-explanatory.
Definition FOF.cpp:1024

◆ distribute_and()

void FOF::distribute_and ( )

Distribute ANDs to the maximum extent possible.

Assumes you have nothing but a quantifier-free DNF in NNF. The result will have a tree structure with ORs at the top, then ANDs, then literals.

Definition at line 1156 of file FOF.cpp.

1156 {
1157 while (distribute_and_once()) {};
1158}
bool distribute_and_once()
Find an AND that can be distributed and deal with it. Indicate if there isn't one.
Definition FOF.cpp:149

◆ distribute_and_once()

bool FOF::distribute_and_once ( )
private

Find an AND that can be distributed and deal with it. Indicate if there isn't one.

Definition at line 149 of file FOF.cpp.

149 {
150 // For literals there is nothing to do.
151 if (is_literal()) {
152 return false;
153 }
154 // If we're at an OR, or an AND with no OR immediately under it,
155 // then we're just going to deal with the subformulas.
156 size_t or_location = find_or();
157 size_t s = sub_formulas.size();
158 if (type == FOFType::Or ||
159 ((type == FOFType::And) && (or_location == s))) {
160 bool result = false;
161 // OK, so it's not, strictly speaking, just "once" but
162 // we don't really mind do we?
163 for (size_t i = 0; i < s; i++) {
165 result = true;
166 }
167 return result;
168 }
169 // It must be an AND with an OR immediately under it. That means
170 // we can distribute. First get the OR's subformulas and
171 // remove it.
172 vector<FOF> or_fof_subs = sub_formulas[or_location].sub_formulas;
173 if (or_location != (s-1)) {
174 sub_formulas[or_location] = sub_formulas[s-1];
175 }
176 sub_formulas.pop_back();
177 // Now you've saved the sub-formulas for the OR, and
178 // removed it. The last remaining child of the AND is
179 // now going to be combined using AND with all
180 // the saved subformulas.
181 FOF f = sub_formulas[s-2];
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));
189 }
190 // You may have started with an AND with only two children. If so
191 // then you can now move the OR upwards.
192 if (s == 2) {
193 type = FOFType::Or;
194 sub_formulas = new_sub_formulas_2;
195 }
196 else {
197 sub_formulas[s-2] = FOF::make_or(new_sub_formulas_2);
198 }
199 return true;
200}
static FOF make_or(const vector< FOF > &fs)
Directly make a disjunction.
Definition FOF.hpp:302
size_t find_or() const
Does the collection of subformulas contain an OR? If so, find it.
Definition FOF.cpp:1142
static FOF make_and(const vector< FOF > &fs)
Directly make a conjunction.
Definition FOF.hpp:295

◆ distribute_or()

void FOF::distribute_or ( )

Distribute ORs to the maximum extent possible.

Assumes you have nothing but a quantifier-free NNF. The result will have a tree structure with ANDs at the top, then ORs, then literals.

Definition at line 1152 of file FOF.cpp.

1152 {
1153 while (distribute_or_once()) {};
1154}
bool distribute_or_once()
Find an OR that can be distributed and deal with it. Indicate if there isn't one.
Definition FOF.cpp:96

◆ distribute_or_once()

bool FOF::distribute_or_once ( )
private

Find an OR that can be distributed and deal with it. Indicate if there isn't one.

Definition at line 96 of file FOF.cpp.

96 {
97 // For literals there is nothing to do.
98 if (is_literal()) {
99 return false;
100 }
101 // If we're at an AND, or an OR with no AND immediately under it,
102 // then we're just going to deal with the subformulas.
103 size_t and_location = find_and();
104 size_t s = sub_formulas.size();
105 if (type == FOFType::And ||
106 ((type == FOFType::Or) && (and_location == s))) {
107 bool result = false;
108 // OK, so it's not, strictly speaking, just "once" but
109 // we don't really mind do we?
110 for (size_t i = 0; i < s; i++) {
112 result = true;
113 }
114 return result;
115 }
116 // It must be an OR with an AND immediately under it. That means
117 // we can distribute. First get the AND's subformulas and
118 // remove it.
119 vector<FOF> and_fof_subs = sub_formulas[and_location].sub_formulas;
120 if (and_location != (s-1)) {
121 sub_formulas[and_location] = sub_formulas[s-1];
122 }
123 sub_formulas.pop_back();
124 // Now you've saved the sub-formulas for the AND, and
125 // removed it. The last remaining child of the OR is
126 // now going to be combined using OR with all
127 // the saved subformulas.
128 FOF f = sub_formulas[s-2];
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));
136 }
137 // You may have started with an OR with only two children. If so
138 // then you can now move the AND upwards.
139 if (s == 2) {
140 type = FOFType::And;
141 sub_formulas = new_sub_formulas_2;
142 }
143 else {
144 sub_formulas[s-2] = FOF::make_and(new_sub_formulas_2);
145 }
146 return true;
147}
size_t find_and() const
Does the collection of subformulas contain an AND? If so, find it.
Definition FOF.cpp:1132

◆ dnf_invert_and_convert_to_clauses()

void FOF::dnf_invert_and_convert_to_clauses ( vector< Clause > & cs) const

Assuming you have a DNF, invert it and convert it to a collection of CNF clauses.

Definition at line 1095 of file FOF.cpp.

1095 {
1096 cs.clear();
1097 if (is_literal()) {
1098 Literal new_lit;
1099 to_Literal(new_lit);
1100 // This is where the inversion happens.
1101 new_lit.invert();
1102 Clause new_c;
1103 new_c.add_lit(new_lit);
1104 cs.push_back(new_c);
1105 return;
1106 }
1107 // Anything under here is essentially ANDed literals.
1108 if (type == FOFType::And) {
1109 vector<Clause> c;
1110 Clause new_c;
1111 cs.push_back(new_c);
1112 for (size_t i = 0; i < sub_formulas.size(); i++) {
1113 sub_formulas[i].dnf_invert_and_convert_to_clauses(c);
1114 for (size_t j = 0; j < c[0].size(); j++) {
1115 cs[0].add_lit((c[0])[j]);
1116 }
1117 }
1118 return;
1119 }
1120 // Anything below here essentially converts to another DNF.
1121 if (type == FOFType::Or) {
1122 vector<Clause> c;
1123 for (size_t i = 0; i < sub_formulas.size(); i++) {
1124 sub_formulas[i].dnf_invert_and_convert_to_clauses(c);
1125 for (size_t j = 0; j < c.size();j++) {
1126 cs.push_back(c[j]);
1127 }
1128 }
1129 }
1130}
void invert()
Basic manipulation - entirely self-explanatory.
Definition Literal.hpp:103

◆ find_and()

size_t FOF::find_and ( ) const

Does the collection of subformulas contain an AND? If so, find it.

Note: does not do any recursion – only looks at the top level.

Definition at line 1132 of file FOF.cpp.

1132 {
1133 size_t s = sub_formulas.size();
1134 for (size_t i = 0; i < s; i++) {
1135 if (sub_formulas[i].type == FOFType::And) {
1136 return i;
1137 }
1138 }
1139 return s;
1140}

◆ find_definitional_tuple()

void FOF::find_definitional_tuple ( FOF & f,
vector< FOF > & d,
bool in_conjunction )

Heavy-lifting for conversion to definitional clause form.

Parameters
fFirst part of definitional tuple.
dSecond part of definitional tuple.
in_conjunctionmIndicates whether or not the parent formula was a conjunction.

Definition at line 869 of file FOF.cpp.

869 {
870 f.clear();
871 d.clear();
872 // Literals are straightforward.
873 if (is_literal()) {
874 f = *this;
875 vector<FOF> new_d;
876 d = new_d;
877 return;
878 }
879 // You must have an And or an Or because we're in NNF.
880 // Let's split half and half, just for the sake of symmetry.
881 vector<FOF> left;
882 vector<FOF> right;
883 split_sub_formulas(left, right);
884 FOF l = left[0];
885 FOF r = right[0];
886 if (left.size() > 1) {
887 l = FOF(type, left, nullptr);
888 }
889 if (right.size() > 1) {
890 r = FOF(type, right, nullptr);
891 }
892 // Somewhere to store results.
893 FOF new_f_1(FOFType::Empty);
894 FOF new_f_2(FOFType::Empty);
895 vector<FOF> new_d_1;
896 vector<FOF> new_d_2;
897 // The tricky case is an Or inside an And.
898 if (in_conjunction && type == FOFType::Or) {
899 l.find_definitional_tuple(new_f_1, new_d_1, false);
900 r.find_definitional_tuple(new_f_2, new_d_2, false);
902 f = def;
903 def.simple_negate();
904 vector<FOF> args1;
905 args1.push_back(def);
906 args1.push_back(new_f_1);
907 d.push_back(FOF::make_and(args1));
908 vector<FOF> args2;
909 args2.push_back(def);
910 args2.push_back(new_f_2);
911 d.push_back(FOF::make_and(args2));
912 for (const FOF& g : new_d_1) {
913 d.push_back(g);
914 }
915 for (const FOF& g : new_d_2) {
916 d.push_back(g);
917 }
918 return;
919 }
920 // The final case is straightforward.
921 bool is_and(type == FOFType::And);
922 l.find_definitional_tuple(new_f_1, new_d_1, is_and);
923 r.find_definitional_tuple(new_f_2, new_d_2, is_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);
928 f = new_f;
929 d = new_d_1;
930 for (const FOF& g : new_d_2){
931 d.push_back(g);
932 }
933}
void clear()
Make an FOFType::Empty.
Definition FOF.hpp:265
void split_sub_formulas(vector< FOF > &, vector< FOF > &)
Split subformulas in half.
Definition FOF.cpp:845
FOF make_definitional_predicate() const
When doing definitional clause conversion you need to be able to make unique new predicates....
Definition FOF.cpp:86
FOF()=delete
You don't want this constructor.

◆ find_free_variables()

set< Term * > FOF::find_free_variables ( ) const

Find the free variables in the formula.

Note: will consider x to be free in:

( P(x) | Ax. Q(x) ).

Definition at line 1289 of file FOF.cpp.

1289 {
1290 set<Term*> result;
1291 set<Term*> free;
1292 Term* to_remove;
1293 switch (type) {
1294 case FOFType::Empty:
1295 cerr << "You shouldn't be doing this with an FOFType::Empty!" << endl;
1296 break;
1297 case FOFType::Atom:
1298 for (const Term* p : pred.get_args()) {
1299 free = p->all_variables();
1300 result.insert(free.begin(), free.end());
1301 }
1302 break;
1303 case FOFType::Neg:
1304 case FOFType::And:
1305 case FOFType::Or:
1306 case FOFType::Imp:
1307 case FOFType::Iff:
1308 for (const FOF& f : sub_formulas) {
1309 free = f.find_free_variables();
1310 result.insert(free.begin(), free.end());
1311 }
1312 break;
1313 case FOFType::A:
1314 case FOFType::E:
1315 result = sub_formulas[0].find_free_variables();
1316 to_remove = term_index->add_variable_term(var);
1317 result.erase(to_remove);
1318 break;
1319 default:
1320 break;
1321 }
1322 return result;
1323}
static TermIndex * term_index
Access to the index: static because all FOFs should share it.
Definition FOF.hpp:90
General representation of terms.
Definition Term.hpp:62
Term * add_variable_term(Variable *)
Self-explanatory: add a Term containing a variable to the index.
Definition TermIndex.cpp:56

◆ find_or()

size_t FOF::find_or ( ) const

Does the collection of subformulas contain an OR? If so, find it.

Note: does not do any recursion – only looks at the top level.

Definition at line 1142 of file FOF.cpp.

1142 {
1143 size_t s = sub_formulas.size();
1144 for (size_t i = 0; i < s; i++) {
1145 if (sub_formulas[i].type == FOFType::Or) {
1146 return i;
1147 }
1148 }
1149 return s;
1150}

◆ fof_type()

FOFType FOF::fof_type ( )
inline

Basic get method.

Definition at line 257 of file FOF.hpp.

257{ return type; }

◆ has_free_variable()

bool FOF::has_free_variable ( Variable * v)
private

Does this formula contain the specified variable unbound?

Only use this if bound variables are unique. (If it finds any quantifier binding the variable it will return false.)

Parameters
vPointer to Variable of interest.

Definition at line 35 of file FOF.cpp.

35 {
36 switch (type) {
37 case FOFType::Empty:
38 cerr << "Don't do this with an Empty FOF!" << endl;
39 return false;
40 break;
41 case FOFType::Atom:
42 return pred.contains_variable(v);
43 case FOFType::Neg:
44 return (sub_formulas[0].has_free_variable(v));
45 break;
46 case FOFType::And:
47 case FOFType::Or:
48 for (size_t i = 0; i < sub_formulas.size(); i++) {
50 return true;
51 }
52 }
53 return false;
54 break;
55 case FOFType::Imp:
56 case FOFType::Iff:
57 return (sub_formulas[0].has_free_variable(v) ||
59 break;
60 case FOFType::A:
61 case FOFType::E:
62 if (var == v)
63 return false;
64 return sub_formulas[0].has_free_variable(v);
65 break;
66 default:
67 break;
68 }
69 return false;
70}
bool has_free_variable(Variable *)
Does this formula contain the specified variable unbound?
Definition FOF.cpp:35
bool contains_variable(Variable *) const
Does this Literal contain the specified variable?
Definition Literal.cpp:105

◆ invert_literal()

void FOF::invert_literal ( )

Self-explanatory!

Definition at line 429 of file FOF.cpp.

429 {
430 if (type == FOFType::Atom) {
432 return;
433 }
434 if (type == FOFType::Neg && sub_formulas[0].type == FOFType::Atom) {
436 return;
437 }
438 cerr << "Don't use this with a non-literal." << endl;
439}
void remove_negation()
Remove the leading negation from an arbitrary FOF, if it has one.
Definition FOF.cpp:391

◆ is_clause()

bool FOF::is_clause ( ) const

Check if something is a clause.

This check in the strict sense: either it must be a literal or a disjunction of literals, including an empty disjunction.

Returns false if FOFType::Empty.

Definition at line 374 of file FOF.cpp.

374 {
375 if (is_literal()) {
376 return true;
377 }
378 if (!(type == FOFType::Or)) {
379 return false;
380 }
381 for (size_t i = 0; i < sub_formulas.size(); i++) {
382 if (!sub_formulas[i].is_literal()) {
383 return false;
384 }
385 }
386 return true;
387}

◆ is_literal()

bool FOF::is_literal ( ) const

Check if an FOF is a literal.

Works in general, not just for NNF.

Definition at line 369 of file FOF.cpp.

369 {
370 return (type == FOFType::Atom) ||
371 (type == FOFType::Neg && sub_formulas[0].type == FOFType::Atom);
372}

◆ make_and()

static FOF FOF::make_and ( const vector< FOF > & fs)
inlinestatic

Directly make a conjunction.

Definition at line 295 of file FOF.hpp.

295 {
296 FOF result(FOFType::And, fs, nullptr);
297 return result;
298 }

◆ make_definitional_predicate()

FOF FOF::make_definitional_predicate ( ) const
private

When doing definitional clause conversion you need to be able to make unique new predicates. This will provide one.

Definition at line 86 of file FOF.cpp.

86 {
87 set<Term*> a = this->find_free_variables();
88 vector<Term*> args;
89 for (Term* p : a)
90 args.push_back(p);
92 Literal lit(name, args, args.size(), true);
93 return FOF(lit);
94}
set< Term * > find_free_variables() const
Find the free variables in the formula.
Definition FOF.cpp:1289
static PredicateIndex * pred_index
Access to the index: static because all FOFs should share it.
Definition FOF.hpp:95
Basic representation of predicates: here just names, ids and arities.
Definition Predicate.hpp:51
Predicate * make_definitional_predicate(Arity arity)
Make a new, unique definitional predicate.

◆ make_exists()

static FOF FOF::make_exists ( const FOF & f,
Variable * v )
inlinestatic

Directly make an existentially quantified FOF.

Definition at line 338 of file FOF.hpp.

338 {
339 vector<FOF> fs;
340 fs.push_back(f);
341 FOF result(FOFType::E, fs, v);
342 return result;
343 }

◆ make_forall()

static FOF FOF::make_forall ( const FOF & f,
Variable * v )
inlinestatic

Directly make a universally quantified FOF.

Definition at line 329 of file FOF.hpp.

329 {
330 vector<FOF> fs;
331 fs.push_back(f);
332 FOF result(FOFType::A, fs, v);
333 return result;
334 }

◆ make_iff()

static FOF FOF::make_iff ( const FOF & lhs,
const FOF & rhs )
inlinestatic

Directly make an iff.

Definition at line 319 of file FOF.hpp.

319 {
320 vector<FOF> fs;
321 fs.push_back(lhs);
322 fs.push_back(rhs);
323 FOF result(FOFType::Iff, fs, nullptr);
324 return result;
325 }

◆ make_imp()

static FOF FOF::make_imp ( const FOF & lhs,
const FOF & rhs )
inlinestatic

Directly make an implication.

Definition at line 309 of file FOF.hpp.

309 {
310 vector<FOF> fs;
311 fs.push_back(lhs);
312 fs.push_back(rhs);
313 FOF result(FOFType::Imp, fs, nullptr);
314 return result;
315 }

◆ make_literal()

static FOF FOF::make_literal ( const Literal & lit)
inlinestatic

Directly make a Literal.

Definition at line 277 of file FOF.hpp.

277 {
278 FOF result(lit);
279 return result;
280 }

◆ make_neg()

static FOF FOF::make_neg ( const FOF & f)
inlinestatic

Directly negate a FOF.

Careful: no attempt here to make any obvious simplifications.

Definition at line 286 of file FOF.hpp.

286 {
287 vector<FOF> fs;
288 fs.push_back(f);
289 FOF result(FOFType::Neg, fs, nullptr);
290 return result;
291 }

◆ make_or()

static FOF FOF::make_or ( const vector< FOF > & fs)
inlinestatic

Directly make a disjunction.

Definition at line 302 of file FOF.hpp.

302 {
303 FOF result(FOFType::Or, fs, nullptr);
304 return result;
305 }

◆ make_skolem_function()

Term * FOF::make_skolem_function ( const vector< Term * > & args)
private

Make a new Skolem function.

Mainly achieved using methods from other classes.

Parameters
argsVector of pointers to Term. These are the Skolem function arguments.

Definition at line 204 of file FOF.cpp.

204 {
205 Function* sk = fun_index->make_skolem_function(args.size());
206 Term* sk_t = term_index->add_function_term(sk, args);
207 return sk_t;
208}
static FunctionIndex * fun_index
Access to the index: static because all FOFs should share it.
Definition FOF.hpp:85
Basic representation of functions.
Definition Function.hpp:54
Function * make_skolem_function(Arity)
Add a new Skolem function. Naming is automatic.
Term * add_function_term(Function *, const vector< Term * > &)
Self-explanatory: add a Term containing a function to the index.
Definition TermIndex.cpp:73

◆ make_unique_bound_variables()

void FOF::make_unique_bound_variables ( )

Replace all bound variables with unique new ones.

Has to be done with care to maintain the indexes correctly.

Definition at line 486 of file FOF.cpp.

486 {
487 Variable* new_var;
488 switch (type) {
489 case FOFType::Atom:
490 break;
491 case FOFType::Neg:
492 case FOFType::And:
493 case FOFType::Or:
494 case FOFType::Imp:
495 case FOFType::Iff:
496 for (FOF& sf : sub_formulas)
498 break;
499 case FOFType::A:
500 case FOFType::E:
501 sub_formulas[0].make_unique_bound_variables();
502 new_var = var_index->add_unique_var();
503 sub_formulas[0].replace_variable(new_var, var);
504 var = new_var;
505 break;
506 default:
507 break;
508 }
509}
static VariableIndex * var_index
Access to the index: static because all FOFs should share it.
Definition FOF.hpp:80
Basic representation of variables.
Definition Variable.hpp:58
Variable * add_unique_var()
Add a unique variable when converting to CNF.

◆ miniscope()

void FOF::miniscope ( )

Apply the rules for miniscoping.

Push the quantifiers in as much as you can. Don't use this unless your formula is in NNF.

Definition at line 615 of file FOF.cpp.

615 {
616 vector<FOF> free;
617 vector<FOF> absent;
618 FOF new_sub(FOFType::Empty);
619 vector<FOF> new_subs;
620 Variable* new_var;
621 switch (type) {
622 case FOFType::Empty:
623 cerr << "Don't do this with an empty formula" << endl;
624 break;
625 case FOFType::Atom:
626 case FOFType::Neg:
627 break;
628 case FOFType::And:
629 case FOFType::Or:
631 break;
632 case FOFType::Imp:
633 case FOFType::Iff:
634 cerr << "Don't do this unless you've removed -> and <->" << endl;
635 break;
636 // Remember you're only dealing with stuff in NNF. You
637 // do however have to handle nested quantifiers.
638 case FOFType::A:
639 sub_formulas[0].miniscope();
640 if (!(sub_formulas[0].type == FOFType::And ||
641 sub_formulas[0].type == FOFType::Or)) {
642 return;
643 }
644 // You have \forall followed by (miniscoped) AND or OR.
645 miniscope_split(var, free, absent);
646 // If the quantifier is followed by AND you can just
647 // make a \forall for every subformula involving the
648 // variable.
649 if (sub_formulas[0].type == FOFType::And) {
650 type = FOFType::And;
651 // If everything is bound then make a new forall everywhere
652 // with a new variable.
653 if (free.size() == sub_formulas[0].sub_formulas.size()) {
654 for (size_t i = 0; i < free.size(); i++) {
655 new_var = var_index->add_unique_var();
656 new_sub = free[i];
657 new_sub.replace_variable(new_var, var);
658 new_sub = FOF::make_forall(new_sub, new_var);
659 new_subs.push_back(new_sub);
660 }
661 sub_formulas = new_subs;
662 }
663 // If any subformula doesn't have the variable then just
664 // move the forall in. Remember you need to consider the
665 // possibility that the quantifier can just be removed.
666 else if (free.size() > 0) {
667 sub_formulas = absent;
668 if (free.size() == 1)
669 new_sub = free[0];
670 else
671 new_sub = FOF::make_and(free);
672 new_sub = FOF::make_forall(new_sub, var);
673 sub_formulas.push_back(new_sub);
674 }
675 // You're just going to remove the quantifier.
676 else {
677 sub_formulas = sub_formulas[0].sub_formulas;
678 }
679 var = nullptr;
681 return;
682 }
683 if (sub_formulas[0].type == FOFType::Or) {
684 // You have a \forall followed by an OR.
685 // If eveything is bound there's nothing to do.
686 if (absent.size() == 0)
687 return;
688 else if (free.size() > 0) {
689 type = FOFType::Or;
690 sub_formulas = absent;
691 if (free.size() == 1)
692 new_sub = free[0];
693 else
694 new_sub = FOF::make_or(free);
695 new_sub = FOF::make_forall(new_sub, var);
696 sub_formulas.push_back(new_sub);
697 var = nullptr;
699 }
700 // You can just drop the quantifier.
701 else {
702 type = FOFType::Or;
703 vector<FOF> sf(sub_formulas);
704 sub_formulas = sf[0].sub_formulas;
705 var = nullptr;
706 }
707 return;
708 }
709 break;
710 // You have an \exists.
711 case FOFType::E:
712 sub_formulas[0].miniscope();
713 if (!(sub_formulas[0].type == FOFType::And ||
714 sub_formulas[0].type == FOFType::Or)) {
715 return;
716 }
717 // You have an \exists followed by AND or OR.
718 miniscope_split(var, free, absent);
719 if (sub_formulas[0].type == FOFType::Or) {
720 type = FOFType::Or;
721 // If everything is bound then make a new exists everywhere
722 // with a new variable.
723 if (free.size() == sub_formulas[0].sub_formulas.size()) {
724 for (size_t i = 0; i < free.size(); i++) {
725 new_var = var_index->add_unique_var();
726 new_sub = free[i];
727 new_sub.replace_variable(new_var, var);
728 new_sub = FOF::make_exists(new_sub, new_var);
729 new_subs.push_back(new_sub);
730 }
731 sub_formulas = new_subs;
732 }
733 // If any subformula doesn't have the variable then just
734 // move the \exists in.
735 else if (free.size() > 0) {
736 sub_formulas = absent;
737 if (free.size() == 1)
738 new_sub = free[0];
739 else
740 new_sub = FOF::make_or(free);
741 new_sub = FOF::make_exists(new_sub, var);
742 sub_formulas.push_back(new_sub);
743 }
744 // We're just going to drop the quantifier.
745 else {
746 sub_formulas = sub_formulas[0].sub_formulas;
747 }
748 var = nullptr;
750 return;
751 }
752 // You have an \exists followed by and AND.
753 if (sub_formulas[0].type == FOFType::And) {
754 // If eveything is bound there's nothing to do.
755 if (absent.size() == 0)
756 return;
757 else if (free.size() != sub_formulas[0].sub_formulas.size()) {
758 type = FOFType::And;
759 sub_formulas = absent;
760 if (free.size() == 1)
761 new_sub = free[0];
762 else
763 new_sub = FOF::make_and(free);
764 new_sub = FOF::make_exists(new_sub, var);
765 sub_formulas.push_back(new_sub);
766 var = nullptr;
768 }
769 // We can just drop the quantifier.
770 else {
771 type = FOFType::And;
772 vector<FOF> sf(sub_formulas);
773 sub_formulas = sf[0].sub_formulas;
774 var = nullptr;
775 }
776 return;
777 }
778 break;
779 default:
780 break;
781 }
782}
void miniscope_all()
Apply miniscoping to all subformulas.
Definition FOF.cpp:306
void miniscope_split(Variable *, vector< FOF > &, vector< FOF > &)
Helper for miniscope.
Definition FOF.cpp:290
static FOF make_exists(const FOF &f, Variable *v)
Directly make an existentially quantified FOF.
Definition FOF.hpp:338
static FOF make_forall(const FOF &f, Variable *v)
Directly make a universally quantified FOF.
Definition FOF.hpp:329

◆ miniscope_all()

void FOF::miniscope_all ( )
private

Apply miniscoping to all subformulas.

Definition at line 306 of file FOF.cpp.

306 {
307 for (size_t i = 0; i < sub_formulas.size(); i++ ) {
308 sub_formulas[i].miniscope();
309 }
310}

◆ miniscope_split()

void FOF::miniscope_split ( Variable * v,
vector< FOF > & free,
vector< FOF > & absent )
private

Helper for miniscope.

Split subformulas into ones that do and don't have the relevant variable.

Parameters
vPointer to Variable of interest.
freeReference to vector of FOF. Collect FOFs with the Variable.
absentReference to vector of FOF. Collect FOFs without the Variable.

Definition at line 290 of file FOF.cpp.

292 {
293 // Remember that at this point you have a NNF with
294 // unique variables. So whatever is in the subformula
295 // is AND, OR, Atom or Neg (Literal).
296 vector<FOF>& subs = sub_formulas[0].sub_formulas;
297 for (size_t i = 0; i < subs.size(); i++) {
298 FOF f(subs[i]);
299 if (f.has_free_variable(v))
300 free.push_back(f);
301 else
302 absent.push_back(f);
303 }
304}

◆ negate()

void FOF::negate ( )

Negate an FOF, applying obvious simplifications if it's already negated or an implication.

Definition at line 398 of file FOF.cpp.

398 {
399 if (type == FOFType::Empty) {
400 cerr << "Don't do this with an Empty FOF!" << endl;
401 return;
402 }
403 if (type == FOFType::Imp) {
404 type = FOFType::And;
405 sub_formulas[1].negate();
406 }
407 else if (type == FOFType::Neg) {
409 }
410 else {
411 FOF f = *this;
412 type = FOFType::Neg;
413 pred.clear();
414 var = nullptr;
415 sub_formulas.clear();
416 sub_formulas.push_back(f);
417 }
418}

◆ push_negs()

void FOF::push_negs ( )

Push all negations in.

DON'T call it on anything with a -> or <->.

Definition at line 540 of file FOF.cpp.

540 {
541 switch (type) {
542 case FOFType::Neg:
543 switch (sub_formulas[0].type) {
544 case FOFType::Neg:
547 push_negs();
548 break;
549 case FOFType::Atom:
550 break;
551 case FOFType::And:
553 type = FOFType::Or;
554 for (FOF& f : sub_formulas) {
555 f.negate();
556 f.push_negs();
557 }
558 break;
559 case FOFType::Or:
561 type = FOFType::And;
562 for (FOF& f : sub_formulas) {
563 f.negate();
564 f.push_negs();
565 }
566 break;
567 case FOFType::A:
569 type = FOFType::E;
570 sub_formulas[0].negate();
571 sub_formulas[0].push_negs();
572 break;
573 case FOFType::E:
575 type = FOFType::A;
576 sub_formulas[0].negate();
577 sub_formulas[0].push_negs();
578 break;
579 case FOFType::Imp:
580 case FOFType::Iff:
581 cerr << "Stop it!!! You don't push negations through -> or <->." << endl;
582 break;
583 default:
584 break;
585 }
586 break;
587 case FOFType::Atom:
588 break;
589 case FOFType::And:
590 case FOFType::Or:
591 case FOFType::A:
592 case FOFType::E:
593 for (FOF& f : sub_formulas)
594 f.push_negs();
595 break;
596 case FOFType::Imp:
597 case FOFType::Iff:
598 cerr << "Stop it!!! You don't push negations through -> or <->." << endl;
599 break;
600 default:
601 break;
602 }
603}

◆ remove_existential_quantifiers()

void FOF::remove_existential_quantifiers ( )

Self-explanatory.

Definition at line 1024 of file FOF.cpp.

1024 {
1025 FOF f(FOFType::Atom);
1026 switch (type) {
1027 case FOFType::Atom:
1028 break;
1029 case FOFType::Neg:
1030 sub_formulas[0].remove_existential_quantifiers();
1031 break;
1032 case FOFType::And:
1033 case FOFType::Or:
1034 case FOFType::Imp:
1035 case FOFType::Iff:
1036 for (FOF& g : sub_formulas)
1038 break;
1039 case FOFType::E:
1040 sub_formulas[0].remove_existential_quantifiers();
1041 f = sub_formulas[0];
1042 *this = f;
1043 break;
1044 case FOFType::A:
1045 sub_formulas[0].remove_existential_quantifiers();
1046 break;
1047 default:
1048 break;
1049 }
1050}

◆ remove_iff()

void FOF::remove_iff ( )

Replace <-> throughout using ->.

Definition at line 441 of file FOF.cpp.

441 {
442 if (type == FOFType::Empty) {
443 cerr << "Don't do this with an Empty FOF!" << endl;
444 return;
445 }
446 // End of recursion.
447 if (type == FOFType::Atom)
448 return;
449 // Do the relevant transformation.
450 if (type == FOFType::Iff) {
451 FOF lhs = *this;
452 FOF rhs = *this;
453 lhs.type = FOFType::Imp;
454 rhs.type = FOFType::Imp;
455 FOF store = rhs.sub_formulas[1];
456 rhs.sub_formulas[1] = rhs.sub_formulas[0];
457 rhs.sub_formulas[0] = store;
458 type = FOFType::And;
459 sub_formulas.clear();
460 sub_formulas.push_back(lhs);
461 sub_formulas.push_back(rhs);
462 }
463 // Finish the job. Also applies the transformation to other FOF types.
464 for (FOF& f : sub_formulas)
465 f.remove_iff();
466}

◆ remove_imp()

void FOF::remove_imp ( )

Replace A->B throughout with neg A v B.

Definition at line 468 of file FOF.cpp.

468 {
469 if (type == FOFType::Empty) {
470 cerr << "Don't do this with an Empty FOF!" << endl;
471 return;
472 }
473 // End of recursion.
474 if (type == FOFType::Atom)
475 return;
476 // Do the relevant transformation.
477 if (type == FOFType::Imp) {
478 type = FOFType::Or;
479 sub_formulas[0].negate();
480 }
481 // Finish the job. Also applies the transformation to other FOF types.
482 for (FOF& f : sub_formulas)
483 f.remove_imp();
484}

◆ remove_negation()

void FOF::remove_negation ( )

Remove the leading negation from an arbitrary FOF, if it has one.

Definition at line 391 of file FOF.cpp.

391 {
392 if (type == FOFType::Neg) {
393 FOF f = sub_formulas[0];
394 *this = f;
395 }
396}

◆ remove_redundant_quantifiers()

void FOF::remove_redundant_quantifiers ( )

Remove quantifiers if they don't bind anything in their scope.

Yes, the TPTP does contain such formulas. Use this only if bound variables are unique.

Definition at line 511 of file FOF.cpp.

511 {
512 Variable* new_var;
513 switch (type) {
514 case FOFType::Atom:
515 break;
516 case FOFType::Neg:
517 case FOFType::And:
518 case FOFType::Or:
519 case FOFType::Imp:
520 case FOFType::Iff:
521 for (FOF& sf : sub_formulas)
523 break;
524 case FOFType::A:
525 case FOFType::E:
526 sub_formulas[0].remove_redundant_quantifiers();
528 vector<FOF> sf(sub_formulas);
529 type = sub_formulas[0].type;
530 pred = sub_formulas[0].pred;
531 var = sub_formulas[0].var;
532 sub_formulas = sf[0].sub_formulas;
533 }
534 break;
535 default:
536 break;
537 }
538}

◆ remove_universal_quantifiers()

void FOF::remove_universal_quantifiers ( )

Self-explanatory.

Definition at line 996 of file FOF.cpp.

996 {
997 FOF f(FOFType::Atom);
998 switch (type) {
999 case FOFType::Atom:
1000 break;
1001 case FOFType::Neg:
1002 sub_formulas[0].remove_universal_quantifiers();
1003 break;
1004 case FOFType::And:
1005 case FOFType::Or:
1006 case FOFType::Imp:
1007 case FOFType::Iff:
1008 for (FOF& g : sub_formulas)
1010 break;
1011 case FOFType::A:
1012 sub_formulas[0].remove_universal_quantifiers();
1013 f = sub_formulas[0];
1014 *this = f;
1015 break;
1016 case FOFType::E:
1017 sub_formulas[0].remove_universal_quantifiers();
1018 break;
1019 default:
1020 break;
1021 }
1022}

◆ replace_variable()

void FOF::replace_variable ( Variable * new_var,
Variable * old_var )
private

Self-explanatory.

However note that this works only on Atoms: quantifiers will be unaffected.

Parameters
new_varPointer to new Variable.
old_varPointer to Variable to replace.

Definition at line 72 of file FOF.cpp.

72 {
73 if (type == FOFType::Empty) {
74 cerr << "Don't do this with an Empty FOF!" << endl;
75 return;
76 }
77 if (type == FOFType::Atom) {
78 pred.replace_variable(new_var, old_var, term_index);
79 }
80 else {
81 for (FOF& f : sub_formulas)
82 f.replace_variable(new_var, old_var);
83 }
84}
void replace_variable(Variable *, Variable *)
Self-explanatory.
Definition FOF.cpp:72
void replace_variable(Variable *, Variable *, TermIndex *)
Replace one variable with another throughout.
Definition Literal.cpp:232

◆ replace_variable_with_term()

void FOF::replace_variable_with_term ( Term * new_term,
Variable * old_var )
private

Replace a Variable with a Term.

Mainly achieved using methods from other classes.

Note that this works only on Atoms: quantifiers will be unaffected.

Parameters
new_termPointer to new Term to use.
old_varPointer to Variable to replace.

Definition at line 210 of file FOF.cpp.

210 {
211 if (type == FOFType::Empty) {
212 cerr << "Don't do this with an Empty FOF!" << endl;
213 return;
214 }
215 if (type == FOFType::Atom) {
216 pred.replace_variable_with_term(new_term, old_var, term_index);
217 }
218 else {
219 for (FOF& f : sub_formulas)
220 f.replace_variable_with_term(new_term, old_var);
221 }
222}
void replace_variable_with_term(Term *, Variable *)
Replace a Variable with a Term.
Definition FOF.cpp:210
void replace_variable_with_term(Term *, Variable *, TermIndex *)
Replace one variable with a term throughout.
Definition Literal.cpp:243

◆ set_indexes()

static void FOF::set_indexes ( std::tuple< VariableIndex *, FunctionIndex *, PredicateIndex *, TermIndex * > is)
inlinestatic

Set up pointer to the variable index etc.

Definition at line 236 of file FOF.hpp.

239 {
240 var_index = std::get<0>(is);
241 fun_index = std::get<1>(is);
242 pred_index = std::get<2>(is);
243 term_index = std::get<3>(is);
244 }

◆ show_indexes()

void FOF::show_indexes ( ) const
inline

Show the indices.

Definition at line 248 of file FOF.hpp.

248 {
249 cout << var_index << " " << fun_index
250 << " " << pred_index
251 << " " << term_index
252 << endl;
253 }

◆ simple_negate()

void FOF::simple_negate ( )

Negate an FOF without applying any simplifications.

Definition at line 420 of file FOF.cpp.

420 {
421 FOF f = *this;
422 type = FOFType::Neg;
423 pred.clear();
424 var = nullptr;
425 sub_formulas.clear();
426 sub_formulas.push_back(f);
427}

◆ simplify_cnf() [1/2]

SimplificationResult FOF::simplify_cnf ( vector< Clause > & cnf)
static

Simplify the clauses in a CNF using the method in Clause.

Definition at line 1268 of file FOF.cpp.

1268 {
1269 vector<Clause> new_cnf;
1270 bool cnf_is_contradiction = false;
1271 for (Clause& c : cnf) {
1272 SimplificationResult result = c.simplify();
1273 if (result == SimplificationResult::Tautology)
1274 continue;
1275 if (result == SimplificationResult::Contradiction) {
1276 cnf_is_contradiction = true;
1277 continue;
1278 }
1279 new_cnf.push_back(c);
1280 }
1281 cnf = new_cnf;
1282 if (cnf_is_contradiction)
1283 return SimplificationResult::Contradiction;
1284 if (cnf.size() == 0)
1285 return SimplificationResult::Tautology;
1286 return SimplificationResult::OK;
1287}

◆ simplify_cnf() [2/2]

SimplificationResult FOF::simplify_cnf ( vector< Clause > & cnf,
vector< string > & roles )
static

As first version of simplify_cnf, but keep track of corresponding roles as well.

Definition at line 1238 of file FOF.cpp.

1239 {
1240 vector<Clause> new_cnf;
1241 vector<string> new_roles;
1242 bool cnf_is_contradiction = false;
1243 size_t i = 0;
1244 for (Clause& c : cnf) {
1245 SimplificationResult result = c.simplify();
1246 if (result == SimplificationResult::Tautology) {
1247 i++;
1248 continue;
1249 }
1250 if (result == SimplificationResult::Contradiction) {
1251 i++;
1252 cnf_is_contradiction = true;
1253 continue;
1254 }
1255 new_cnf.push_back(c);
1256 new_roles.push_back(roles[i]);
1257 i++;
1258 }
1259 cnf = new_cnf;
1260 roles = new_roles;
1261 if (cnf_is_contradiction)
1262 return SimplificationResult::Contradiction;
1263 if (cnf.size() == 0)
1264 return SimplificationResult::Tautology;
1265 return SimplificationResult::OK;
1266}

◆ skolemize()

void FOF::skolemize ( )

Skolemize the given formula.

All the hard work is done by skolemize_main.

See also
skolemize_main

Definition at line 986 of file FOF.cpp.

986 {
987 vector<Term*> skolem_arguments;
988 skolemize_main(skolem_arguments);
989}
void skolemize_main(vector< Term * >)
Main helper function called by FOF::skolemize().
Definition FOF.cpp:224

◆ skolemize_main()

void FOF::skolemize_main ( vector< Term * > skolem_arguments)
private

Main helper function called by FOF::skolemize().

The parameter is used to collect variables for the universal quantifiers inside which you find an existential quantifier. Those then become the parameters for the Skolem function.

Parameters
skolem_argumentsVector of pointers to Term.
See also
make_skolem_function.
replace_variable_with_term.

Definition at line 224 of file FOF.cpp.

224 {
225 Term* sk_t;
226 FOF f(FOFType::Atom);
227 switch (type) {
228 case FOFType::Atom:
229 break;
230 case FOFType::Neg:
231 sub_formulas[0].skolemize_main(skolem_arguments);
232 break;
233 case FOFType::And:
234 case FOFType::Or:
235 case FOFType::Imp:
236 case FOFType::Iff:
237 for (FOF& g : sub_formulas)
238 g.skolemize_main(skolem_arguments);
239 break;
240 case FOFType::A:
241 skolem_arguments.push_back(term_index->add_variable_term(var));
242 sub_formulas[0].skolemize_main(skolem_arguments);
243 break;
244 case FOFType::E:
245 sk_t = make_skolem_function(skolem_arguments);
246 sub_formulas[0].replace_variable_with_term(sk_t, var);
247 sub_formulas[0].skolemize_main(skolem_arguments);
248 f = sub_formulas[0];
249 *this = f;
250 break;
251 default:
252 break;
253 }
254}
Term * make_skolem_function(const vector< Term * > &)
Make a new Skolem function.
Definition FOF.cpp:204

◆ skolemize_universals()

void FOF::skolemize_universals ( )

Skolemize the universal quantifiers in the given formula.

All the hard work is done by skolemize_universals_main.

See also
skolemize_universals_main

Definition at line 991 of file FOF.cpp.

991 {
992 vector<Term*> skolem_arguments;
993 skolemize_universals_main(skolem_arguments);
994}
void skolemize_universals_main(vector< Term * >)
The dual of skolemize_main.
Definition FOF.cpp:256

◆ skolemize_universals_main()

void FOF::skolemize_universals_main ( vector< Term * > skolem_arguments)
private

The dual of skolemize_main.

See also
skolemize_main

Definition at line 256 of file FOF.cpp.

256 {
257 Term* sk_t;
258 FOF f(FOFType::Atom);
259 switch (type) {
260 case FOFType::Atom:
261 break;
262 case FOFType::Neg:
263 sub_formulas[0].skolemize_universals_main(skolem_arguments);
264 break;
265 case FOFType::And:
266 case FOFType::Or:
267 case FOFType::Imp:
268 case FOFType::Iff:
269 for (FOF& g : sub_formulas)
270 g.skolemize_universals_main(skolem_arguments);
271 break;
272 case FOFType::E:
273 skolem_arguments.push_back(term_index->add_variable_term(var));
274 sub_formulas[0].skolemize_universals_main(skolem_arguments);
275 break;
276 case FOFType::A:
277 sk_t = make_skolem_function(skolem_arguments);
278 sub_formulas[0].replace_variable_with_term(sk_t, var);
279 sub_formulas[0].skolemize_universals_main(skolem_arguments);
280 f = sub_formulas[0];
281 *this = f;
282 break;
283 default:
284 break;
285 }
286}

◆ split_sub_formulas()

void FOF::split_sub_formulas ( vector< FOF > & left_sub,
vector< FOF > & right_sub )

Split subformulas in half.

Parameters
left_subFirst half of the subformulas.
right_subSecond half of subformulas.

Definition at line 845 of file FOF.cpp.

845 {
846 left_sub.clear();
847 right_sub.clear();
848 size_t s = sub_formulas.size();
849 if (s == 2) {
850 left_sub.push_back(sub_formulas[0]);
851 right_sub.push_back(sub_formulas[1]);
852 return;
853 }
854 if (s == 3) {
855 right_sub.push_back(sub_formulas[2]);
856 left_sub = sub_formulas;
857 left_sub.pop_back();
858 return;
859 }
860 size_t left_size = s / 2;
861 for (size_t i = 0; i < left_size; i++) {
862 left_sub.push_back(sub_formulas[i]);
863 }
864 for (size_t i = left_size; i < s; i++) {
865 right_sub.push_back(sub_formulas[i]);
866 }
867}

◆ to_Literal()

void FOF::to_Literal ( Literal & new_lit) const

Assuming the FOF is a literal, convert it to something of type Literal.

This is straightforward as most of the heavy lifting has already been done. DON'T use it on an FOF that isn't in the form of a literal.

Definition at line 1052 of file FOF.cpp.

1052 {
1053 if (type == FOFType::Atom) {
1054 new_lit = pred;
1055 }
1056 else {
1057 new_lit = sub_formulas[0].pred;
1058 new_lit.make_negative();
1059 }
1060}
void make_negative()
Basic manipulation - entirely self-explanatory.
Definition Literal.hpp:99

◆ to_string()

string FOF::to_string ( ) const

Convert a FOF into a nice-looking string.

Definition at line 1160 of file FOF.cpp.

1160 {
1161 string result;
1162 size_t s = sub_formulas.size();;
1163 size_t i = 1;
1164 switch (type) {
1165 case FOFType::Atom:
1166 result = pred.to_string();
1167 break;
1168 case FOFType::Neg:
1169 result = unicode_symbols::LogSym::neg;
1170 result += "( ";
1171 result += sub_formulas[0].to_string();
1172 result += " )";
1173 break;
1174 case FOFType::And:
1175 result = "( ";
1176 for (const FOF& g : sub_formulas) {
1177 result += g.to_string();
1178 if (i < s) {
1179 result += " ";
1180 result += unicode_symbols::LogSym::and_sym;
1181 result += " ";
1182 }
1183 i++;
1184 }
1185 result += " )";
1186 break;
1187 case FOFType::Or:
1188 result = "( ";
1189 for (const FOF& g : sub_formulas) {
1190 result += g.to_string();
1191 if (i < s) {
1192 result += " ";
1193 result += unicode_symbols::LogSym::or_sym;
1194 result += " ";
1195 }
1196 i++;
1197 }
1198 result += " )";
1199 break;
1200 case FOFType::Imp:
1201 result = "( ";
1202 result += sub_formulas[0].to_string();
1203 result += " ";
1204 result += unicode_symbols::LogSym::ifthen;
1205 result += " ";
1206 result += sub_formulas[1].to_string();
1207 result += " )";
1208 break;
1209 case FOFType::Iff:
1210 result = "( ";
1211 result += sub_formulas[0].to_string();
1212 result += " ";
1213 result += unicode_symbols::LogSym::iff;
1214 result += " ";
1215 result += sub_formulas[1].to_string();
1216 result += " )";
1217 break;
1218 case FOFType::A:
1219 result = unicode_symbols::LogSym::forall;
1220 result += var->to_string();
1221 result += " . [ ";
1222 result += sub_formulas[0].to_string();
1223 result += " ]";
1224 break;
1225 case FOFType::E:
1226 result = unicode_symbols::LogSym::exists;
1227 result += var->to_string();
1228 result += " . [ ";
1229 result += sub_formulas[0].to_string();
1230 result += " ]";
1231 break;
1232 default:
1233 break;
1234 }
1235 return result;
1236}
string to_string(bool=false) const
Full conversion of Literal to string.
Definition Literal.cpp:150
string to_string(bool=false) const
Convert to a (coloured) string.
Definition Term.cpp:276

Friends And Related Symbol Documentation

◆ operator<<

ostream & operator<< ( ostream & out,
const FOF & f )
friend

Definition at line 1325 of file FOF.cpp.

1325 {
1326 out << f.to_string();
1327 return out;
1328}
string to_string() const
Convert a FOF into a nice-looking string.
Definition FOF.cpp:1160

Member Data Documentation

◆ fun_index

FunctionIndex * FOF::fun_index = nullptr
staticprivate

Access to the index: static because all FOFs should share it.

Definition at line 85 of file FOF.hpp.

◆ pred

Literal FOF::pred
private

FOFType::Atom can store one of these to represent a Literal.

Definition at line 67 of file FOF.hpp.

◆ pred_index

PredicateIndex * FOF::pred_index = nullptr
staticprivate

Access to the index: static because all FOFs should share it.

Definition at line 95 of file FOF.hpp.

◆ sub_formulas

vector<FOF> FOF::sub_formulas
private

Most FOFs will have subformulas.

Definition at line 71 of file FOF.hpp.

◆ term_index

TermIndex * FOF::term_index = nullptr
staticprivate

Access to the index: static because all FOFs should share it.

Definition at line 90 of file FOF.hpp.

◆ type

FOFType FOF::type
private

Used for all FOFs to denote what kind it it.

Definition at line 62 of file FOF.hpp.

◆ var

Variable* FOF::var
private

Associate a Variable with a quantifier.

Definition at line 75 of file FOF.hpp.

◆ var_index

VariableIndex * FOF::var_index = nullptr
staticprivate

Access to the index: static because all FOFs should share it.

Definition at line 80 of file FOF.hpp.


The documentation for this class was generated from the following files: