Connect++ 0.4.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//----------------------------------------------------------------------
87void Clause::add_lit(const Literal& l) {
88 for (size_t i = 0; i < c.size(); i++)
89 if (c[i] == l) {
90#ifdef DEBUGMESSAGES
91 cerr << "Don't duplicate Literals in a clause!" << endl;
92#endif
93 return;
94 }
95 c.push_back(l);
96}
97//----------------------------------------------------------------------
99#ifdef DEBUGMESSAGES
100 if (c.size() == 0)
101 cerr << "You are making a copy of an empty clause" << endl;
102#endif
103 vector<Literal> new_lits;
104 unordered_map<Variable*,Term*> new_vars;
105 for (size_t i = 0; i < c.size(); i++)
106 new_lits.push_back(c[i].make_copy_with_new_vars_helper(vi, ti, new_vars));
107 return Clause(new_lits);
108}
109//---------------------------------------------------------------------------
110 SimplificationResult Clause::simplify() {
111 // Do this first in case someone has made a clause with
112 // both $true and $false in it.
113 vector<Literal> new_clause;
114 bool clause_is_true = false;
115 for (Literal& lit : c) {
116 if (lit.is_false())
117 continue;
118 if (lit.is_true()) {
119 clause_is_true = true;
120 continue;
121 }
122 new_clause.push_back(lit);
123 }
124 c = new_clause;
125 if (clause_is_true)
126 return SimplificationResult::Tautology;
128 if (c.size() == 0)
129 return SimplificationResult::Contradiction;
131 return SimplificationResult::Tautology;
132 return SimplificationResult::OK;
133}
134//----------------------------------------------------------------------
135void Clause::drop_literal(LitNum l) {
136 if (c.size() == 0) {
137#ifdef DEBUGMESSAGES
138 cerr << "Can't drop_literal from empty clause" << endl;
139#endif
140 return;
141 }
142 if (l > c.size() - 1) {
143#ifdef DEBUGMESSAGES
144 cerr << "drop_literal argument is out of range" << endl;
145#endif
146 return;
147 }
148 if (c.size() == 1) {
149 c.pop_back();
150 return;
151 }
152 c[l] = c.back();
153 c.pop_back();
154}
155//----------------------------------------------------------------------
157 Literal error_lit;
158 if (c.size() == 0) {
159#ifdef DEBUGMESSAGES
160 cerr << "Can't extract_literal from empty clause" << endl;
161#endif
162 return error_lit;
163 }
164 if (l > c.size() - 1) {
165#ifdef DEBUGMESSAGES
166 cerr << "extract_literal argument is out of range" << endl;
167#endif
168 return error_lit;
169 }
170 Literal lit(c[l]);
171 if (c.size() == 1) {
172 c.pop_back();
173 return lit;
174 }
175 c[l] = c.back();
176 c.pop_back();
177 return lit;
178}
179//----------------------------------------------------------------------
181#ifdef DEBUGMESSAGES
182 if (i > c.size() - 1)
183 cerr << "You're out of range accessing a clause" << endl;
184#endif
185 return c[i];
186}
187//----------------------------------------------------------------------
189 // Make a permutation.
190 vector<size_t> new_order;
191 size_t s = c.size();
192 for (size_t i = 0; i < s; i++)
193 new_order.push_back(i);
194 std::shuffle(new_order.begin(), new_order.end(), d);
195 // Re-order.
196 vector<Literal> new_c = c;
197 for (size_t i = 0; i < s; i++) {
198 c[i] = new_c[new_order[i]];
199 }
200}
201//----------------------------------------------------------------------
202string Clause::to_string(bool subbed) const {
203 commas::comma com(c.size());
204 string result("{ ");
205 for (const Literal& l : c) {
206 result += l.to_string(subbed);
207 result += com();
208 }
209 result += " }";
210 return result;
211}
212//----------------------------------------------------------------------
214 commas::comma com(c.size());
215 string result("[ ");
216 for (const Literal& l : c) {
217 result += l.to_prolog_string();
218 result += com();
219 }
220 result += " ]";
221 return result;
222}
223//----------------------------------------------------------------------
225 commas::comma com(c.size());
226 string result("( ");
227 for (const Literal& l : c) {
228 result += l.to_tptp_string();
229 string s = com();
230 if (s == string(", "))
231 s = string(" | ");
232 result += s;
233 }
234 result += " )";
235 return result;
236}
237//----------------------------------------------------------------------
238string Clause::make_LaTeX(bool subbed) const {
239 commas::comma com(c.size());
240 string s ("\\textcolor{blue}{\\{} ");
241 for (const Literal& l : c) {
242 s += l.make_LaTeX(subbed);
243 s += com();
244 }
245 s += "\\textcolor{blue}{\\}}";
246 return s;
247}
248//----------------------------------------------------------------------
249ostream& operator<<(ostream& out, const Clause& cl) {
250 out << "{ ";
251 size_t s = cl.c.size();
252 size_t i = 1;
253 for (const Literal& l : cl.c) {
254 out << l.to_string();
255 if (i < s)
256 out << " " << unicode_symbols::LogSym::or_sym << " ";
257 i++;
258 }
259 out << " }";
260 return out;
261}
Representation of clauses.
Definition Clause.hpp:52
Literal & operator[](size_t)
Direct read of the specified Literal.
Definition Clause.cpp:180
Literal extract_literal(LitNum)
Get rid of and return the specified Literal.
Definition Clause.cpp:156
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:224
void random_reorder()
Randomly re-order the literals.
Definition Clause.cpp:188
void remove_duplicates()
Get rid of identical literals.
Definition Clause.cpp:54
static std::mt19937 d
Randomness for random reordering.
Definition Clause.hpp:61
string to_prolog_string() const
Convert to a string that can be read by Prolog.
Definition Clause.cpp:213
Clause make_copy_with_new_vars(VariableIndex &, TermIndex &) const
Make a copy of an entire clause, introducing new variables.
Definition Clause.cpp:98
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:110
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:87
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:202
string make_LaTeX(bool=false) const
Convert the clause to a LaTeX representation.
Definition Clause.cpp:238
void drop_literal(LitNum)
Get rid of the specified Literal.
Definition Clause.cpp:135
Basic representation of literals, bundling together (pointers to) a Predicate, a collection of argume...
Definition Literal.hpp:50
Look after terms, (ideally) using hash consing to avoid storing copies of terms.
Definition TermIndex.hpp:75
Storage of named variables, and management of new, anonymous variables.
Simple function object for putting commas in lists.