Connect++ 0.6.0
A fast, readable connection prover for first-order logic.
Loading...
Searching...
No Matches
Clause.cpp
1/*
2
3Copyright © 2023-24 Sean Holden. All rights reserved.
4
5*/
6/*
7
8This file is part of Connect++.
9
10Connect++ is free software: you can redistribute it and/or modify it
11under the terms of the GNU General Public License as published by the
12Free Software Foundation, either version 3 of the License, or (at your
13option) any later version.
14
15Connect++ is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18more details.
19
20You should have received a copy of the GNU General Public License along
21with Connect++. If not, see <https://www.gnu.org/licenses/>.
22
23*/
24
25#include "Clause.hpp"
26
27std::mt19937 Clause::d(params::random_seed);
28
29//----------------------------------------------------------------------
30bool Clause::is_positive() const {
31#ifdef DEBUGMESSAGES
32 if (c.size() == 0)
33 cerr << "Don't check an empty clause for positivity" << endl;
34#endif
35 for (size_t i = 0; i < c.size(); i++) {
36 if (c[i].is_negative())
37 return false;
38 }
39 return true;
40}
41//----------------------------------------------------------------------
42bool Clause::is_negative() const {
43#ifdef DEBUGMESSAGES
44 if (c.size() == 0)
45 cerr << "Don't check an empty clause for negativity" << endl;
46#endif
47 for (size_t i = 0; i < c.size(); i++) {
48 if (c[i].is_positive())
49 return false;
50 }
51 return true;
52}
53//----------------------------------------------------------------------
55 size_t s = c.size();
56 if (s < 2)
57 return;
58 vector<Literal> new_c;
59 for (size_t i = 0; i < s - 1; i++) {
60 bool found = false;
61 for (size_t j = i+1; j < s; j++ ) {
62 if (c[i] == c[j]) {
63 found = true;
64 break;
65 }
66 }
67 if (!found)
68 new_c.push_back(c[i]);
69 }
70 new_c.push_back(c[s - 1]);
71 c = new_c;
72 }
73//----------------------------------------------------------------------
75 size_t s = c.size();
76 if (s < 2)
77 return false;
78 for (size_t i = 0; i < s - 1; i++) {
79 for (size_t j = i+1; j < s; j++) {
80 if (c[i].is_complement_of(c[j]))
81 return true;
82 }
83 }
84 return false;
85}
86//----------------------------------------------------------------------
87bool Clause::is_ground() const {
88 for (const Literal& l : c) {
89 if (!l.is_ground()) {
90 return false;
91 }
92 }
93 return true;
94}
95//----------------------------------------------------------------------
96void Clause::add_lit(const Literal& l) {
97 for (size_t i = 0; i < c.size(); i++)
98 if (c[i] == l) {
99#ifdef DEBUGMESSAGES
100 cerr << "Don't duplicate Literals in a clause!" << endl;
101#endif
102 return;
103 }
104 c.push_back(l);
105}
106//----------------------------------------------------------------------
108#ifdef DEBUGMESSAGES
109 if (c.size() == 0)
110 cerr << "You are making a copy of an empty clause" << endl;
111#endif
112 size_t s = c.size();
113 vector<Literal> new_lits;
114 unordered_map<Variable*,Term*> new_vars;
115 for (size_t i = 0; i < s; i++)
116 new_lits.push_back(c[i].make_copy_with_new_vars_helper(vi, ti, new_vars));
117 return Clause(new_lits);
118}
119//---------------------------------------------------------------------------
121 size_t s = c.size();
122 unordered_map<Variable*,Term*> new_vars;
123 _l.make_copy_with_new_vars_replace_helper(vi, ti, new_vars);
124 // NOTE: make sure _c actually has room in it, unless you want
125 // horror!
126 for (size_t i = 0; i < s; i++)
127 _c.c[i].make_copy_with_new_vars_replace_helper(vi, ti, new_vars);
128}
129//---------------------------------------------------------------------------
130 SimplificationResult Clause::simplify() {
131 // Do this first in case someone has made a clause with
132 // both $true and $false in it.
133 vector<Literal> new_clause;
134 bool clause_is_true = false;
135 for (Literal& lit : c) {
136 if (lit.is_false())
137 continue;
138 if (lit.is_true()) {
139 clause_is_true = true;
140 continue;
141 }
142 new_clause.push_back(lit);
143 }
144 c = new_clause;
145 if (clause_is_true)
146 return SimplificationResult::Tautology;
148 if (c.size() == 0)
149 return SimplificationResult::Contradiction;
151 return SimplificationResult::Tautology;
152 return SimplificationResult::OK;
153}
154//----------------------------------------------------------------------
155void Clause::drop_literal(LitNum l) {
156 if (c.size() == 0) {
157#ifdef DEBUGMESSAGES
158 cerr << "Can't drop_literal from empty clause" << endl;
159#endif
160 return;
161 }
162 if (l > c.size() - 1) {
163#ifdef DEBUGMESSAGES
164 cerr << "drop_literal argument is out of range" << endl;
165#endif
166 return;
167 }
168 if (c.size() == 1) {
169 c.pop_back();
170 return;
171 }
172 c[l] = c.back();
173 c.pop_back();
174}
175//----------------------------------------------------------------------
177 Literal error_lit;
178 if (c.size() == 0) {
179#ifdef DEBUGMESSAGES
180 cerr << "Can't extract_literal from empty clause" << endl;
181#endif
182 return error_lit;
183 }
184 if (l > c.size() - 1) {
185#ifdef DEBUGMESSAGES
186 cerr << "extract_literal argument is out of range" << endl;
187#endif
188 return error_lit;
189 }
190 Literal lit(c[l]);
191 if (c.size() == 1) {
192 c.pop_back();
193 return lit;
194 }
195 c[l] = c.back();
196 c.pop_back();
197 return lit;
198}
199//----------------------------------------------------------------------
201 Literal error_lit;
202 if (c.size() == 0) {
203#ifdef DEBUGMESSAGES
204 cerr << "Can't extract_literal from empty clause" << endl;
205#endif
206 return error_lit;
207 }
208 if (l > c.size() - 1) {
209#ifdef DEBUGMESSAGES
210 cerr << "extract_literal argument is out of range" << endl;
211#endif
212 return error_lit;
213 }
214 Literal lit(c[l]);
215 return lit;
216}
217//----------------------------------------------------------------------
219#ifdef DEBUGMESSAGES
220 if (i > c.size() - 1)
221 cerr << "You're out of range accessing a clause" << endl;
222#endif
223 return c[i];
224}
225//----------------------------------------------------------------------
227 // Make a permutation.
228 vector<size_t> new_order;
229 size_t s = c.size();
230 for (size_t i = 0; i < s; i++)
231 new_order.push_back(i);
232 std::shuffle(new_order.begin(), new_order.end(), d);
233 // Re-order.
234 vector<Literal> new_c = c;
235 for (size_t i = 0; i < s; i++) {
236 c[i] = new_c[new_order[i]];
237 }
238}
239//----------------------------------------------------------------------
241 std::reverse(c.begin(), c.end());
242}
243//----------------------------------------------------------------------
244string Clause::to_string(bool subbed) const {
245 return vector_to_string(c, subbed, "{ ", " }", ", ");
246}
247//----------------------------------------------------------------------
249 commas::comma com(c.size());
250 string result("[ ");
251 for (const Literal& l : c) {
252 result += l.to_prolog_string();
253 result += com();
254 }
255 result += " ]";
256 return result;
257}
258//----------------------------------------------------------------------
260 commas::comma com(c.size());
261 string result("( ");
262 for (const Literal& l : c) {
263 result += l.to_tptp_string();
264 string s = com();
265 if (s == string(", "))
266 s = string(" | ");
267 result += s;
268 }
269 result += " )";
270 return result;
271}
272//----------------------------------------------------------------------
273string Clause::make_LaTeX(bool subbed) const {
274 commas::comma com(c.size());
275 string s ("\\textcolor{blue}{\\{} ");
276 for (const Literal& l : c) {
277 s += l.make_LaTeX(subbed);
278 s += com();
279 }
280 s += "\\textcolor{blue}{\\}}";
281 return s;
282}
283//----------------------------------------------------------------------
284ostream& operator<<(ostream& out, const Clause& cl) {
285 out << "{ ";
286 size_t s = cl.c.size();
287 size_t i = 1;
288 for (const Literal& l : cl.c) {
289 out << l.to_string();
290 if (i < s)
291 out << " " << unicode_symbols::LogSym::or_sym << " ";
292 i++;
293 }
294 out << " }";
295 return out;
296}
Representation of clauses.
Definition Clause.hpp:52
Literal & operator[](size_t)
Direct read of the specified Literal.
Definition Clause.cpp:218
Literal extract_literal(LitNum)
Get rid of and return the specified Literal.
Definition Clause.cpp:176
bool has_complementary_literals() const
Check whether the clause contains complementary literals.
Definition Clause.cpp:74
string to_tptp_string() const
Convert to a string that is compatible with the TPTP.
Definition Clause.cpp:259
void random_reorder()
Randomly re-order the literals.
Definition Clause.cpp:226
void remove_duplicates()
Get rid of identical literals.
Definition Clause.cpp:54
static std::mt19937 d
Randomness for random reordering.
Definition Clause.hpp:61
Literal get_literal(LitNum) const
Get and return the specified Literal.
Definition Clause.cpp:200
string to_prolog_string() const
Convert to a string that can be read by Prolog.
Definition Clause.cpp:248
Clause make_copy_with_new_vars(VariableIndex &, TermIndex &) const
Make a copy of an entire clause, introducing new variables.
Definition Clause.cpp:107
vector< Literal > c
A Clause is just a vector of Literals.
Definition Clause.hpp:57
SimplificationResult simplify()
Simplify a clause by dealing with $true, $false, complementary literals, and duplicates.
Definition Clause.cpp:130
bool is_positive() const
A clause is positive if it has no negated literals.
Definition Clause.cpp:30
void add_lit(const Literal &)
Add a literal, making sure you don't duplicate.
Definition Clause.cpp:96
void reverse()
Reverse the order of the literals in the clause.
Definition Clause.cpp:240
bool is_negative() const
A clause is negative if it has only negated literals.
Definition Clause.cpp:42
string to_string(bool=false) const
Convert to a string.
Definition Clause.cpp:244
string make_LaTeX(bool=false) const
Convert the clause to a LaTeX representation.
Definition Clause.cpp:273
bool is_ground() const
Is this a ground clause?
Definition Clause.cpp:87
void drop_literal(LitNum)
Get rid of the specified Literal.
Definition Clause.cpp:155
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
Definition Literal.hpp:50
void make_copy_with_new_vars_replace_helper(VariableIndex &, TermIndex &, unordered_map< Variable *, Term * > &)
Helper function for making copies with new variables.
Definition Literal.cpp:58
Look after terms, using hash consing to avoid storing copies of terms.
Definition TermIndex.hpp:54
Storage of named variables, and management of new, anonymous and unique variables.
Simple function object for putting commas in lists.