1 /** \file
2 * \brief Definition of class Minisat.
3 *
4 * \author Eldor Malessa, Robert Zeranski
5 *
6 * \par License:
7 * This file is part of the Open Graph Drawing Framework (OGDF).
8 *
9 * \par
10 * Copyright (C)<br>
11 * See README.md in the OGDF root directory for details.
12 *
13 * \par
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * Version 2 or 3 as published by the Free Software Foundation;
17 * see the file LICENSE.txt included in the packaging of this file
18 * for details.
19 *
20 * \par
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * \par
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, see
29 * http://www.gnu.org/copyleft/gpl.html
30 */
31
32
33 #include <ogdf/basic/ArrayBuffer.h>
34 #include <ogdf/external/Minisat.h>
35
36 namespace Minisat
37 {
38
addMultiple(int Amount,...)39 void Clause::addMultiple(int Amount, ...)
40 {
41 va_list params;
42 va_start(params, Amount);
43 for (int i = 0; i < Amount; ++i) {
44 Internal::Var paramVar = va_arg(params, Internal::Var);
45 Internal::Lit l;
46 if (paramVar >= 0) {
47 l = Internal::mkLit(paramVar-1, true);
48 }
49 else {
50 l = Internal::mkLit(-(paramVar + 1), false);
51 }
52 m_ps.push(l);
53 }
54 va_end(params);
55 }
56
newClause()57 Clause *Formula::newClause()
58 {
59 m_Clauses.push_back(new Clause);
60 return m_Clauses.back();
61
62 }
63
finalizeClause(const clause cl)64 void Formula::finalizeClause(const clause cl)
65 {
66 for (int i = 0; i < cl->m_ps.size(); ++i) {
67 // if an variable does not exist, it will be generated (and all between the gap)
68 if (!(Internal::var(cl->m_ps[i]) < Solver::nVars())) {
69 int max = Solver::nVars();
70 for (int j = 0; j < Internal::var(cl->m_ps[i]) + 1 - max; ++j) {
71 Solver::newVar();
72 }
73 }
74 }
75 Solver::addClause(cl->m_ps);
76 }
77
finalizeNotExtensibleClause(const clause cl)78 bool Formula::finalizeNotExtensibleClause(const clause cl)
79 {
80 //proves if variables from clause are valid (still known to formula)
81 for (int i = 0; i < cl->m_ps.size(); ++i) {
82 if (!(Internal::var(cl->m_ps[i]) < Solver::nVars())) {
83 m_messages << "Variable " << i << " is not present.";
84 return false;
85 }
86 }
87 Solver::addClause(cl->m_ps);
88 return true;
89 }
90
getClause(const int pos)91 Clause *Formula::getClause( const int pos )
92 {
93 if ( pos < (int)m_Clauses.size() )
94 return m_Clauses[pos];
95 else
96 return nullptr;
97 }
98
solve(Model & ReturnModel)99 bool Formula::solve( Model &ReturnModel )
100 {
101 bool solv = Solver::solve();
102
103 if ( solv )
104 ReturnModel.setModel ( *this );
105
106 return solv;
107 }
108
109
solve(Model & ReturnModel,double & timeLimit)110 bool Formula::solve( Model &ReturnModel, double& timeLimit )
111 {
112 SolverStatus st;
113 bool solv = Solver::solve(timeLimit, st);
114
115 if (solv)
116 ReturnModel.setModel (*this);
117
118 ReturnModel.solverStatus = st;
119
120 return solv;
121 }
122
123
removeClause(int i)124 void Formula::removeClause(int i)
125 {
126 Internal::CRef cr = Solver::clauses[i];
127 Solver::removeClause(cr);
128 int j, k;
129 for (j = k = 0; j < Solver::clauses.size(); ++j) {
130 if (j == !i) {
131 clauses[k++] = clauses[j];
132 }
133 }
134 clauses.shrink( j - k );
135 delete &m_Clauses[i];
136 m_Clauses.erase( m_Clauses.begin() + i );
137 }
138
reset()139 void Formula::reset()
140 {
141 free();
142 Solver::assigns.clear();
143 Solver::vardata.clear();
144 Solver::activity.clear();
145 Solver::seen.clear();
146 Solver::polarity.clear();
147 Solver::decision.clear();
148 Solver::trail.clear();
149 Solver::dec_vars = 0;
150 Solver::model.clear();
151 }
152
free()153 void Formula::free()
154 {
155 for (auto i = 0; i < Solver::clauses.size(); ++i) {
156 Solver::removeClause(Solver::clauses[i]);
157 }
158 for (auto &cl : m_Clauses) {
159 delete cl;
160 }
161 Solver::clauses.shrink(Solver::clauses.size());
162 m_Clauses.clear();
163 }
164
readDimacs(const char * filename)165 bool Formula::readDimacs(const char *filename)
166 {
167 std::ifstream is(filename);
168 return is.is_open() && readDimacs(is);
169 }
170
readDimacs(const string & filename)171 bool Formula::readDimacs(const string &filename)
172 {
173 std::ifstream is(filename);
174 return is.is_open() && readDimacs(is);
175 }
176
readDimacs(std::istream & in)177 bool Formula::readDimacs(std::istream &in)
178 {
179 std::string currentString;
180
181 while (!in.eof()) {
182 in >> currentString;
183 if (currentString == "p") {
184 in >> currentString;
185 if (currentString == "cnf") {
186 break;
187 }
188 }
189 }
190 if (in.eof()) {
191 return false;
192 }
193
194 int numVars = -1;
195 int numClauses = -1;
196 in >> numVars >> numClauses;
197 if (numVars < 0 || numClauses < 0) {
198 return false;
199 }
200 newVars(numVars);
201
202 int clauseCount = 0;
203 ogdf::ArrayBuffer<int> literals;
204 for (int lit; in >> lit;) {
205 if (lit) {
206 if (lit > numVars
207 || -lit > numVars) {
208 ogdf::Logger::slout() << "Literal does not represent a valid variable (index too high)" << std::endl;
209 return false;
210 }
211 literals.push(lit);
212 } else {
213 addClause(literals);
214 literals.clear();
215 clauseCount++;
216 }
217 }
218 if (!literals.empty()) {
219 ogdf::Logger::slout(ogdf::Logger::Level::Minor) << "Last clause is not terminated by 0 marker, but we accept it nonetheless" << std::endl;
220 addClause(literals);
221 }
222 if(clauseCount != numClauses) {
223 ogdf::Logger::slout(ogdf::Logger::Level::Minor) << "Number of clauses differs from file header" << std::endl;
224 }
225
226 return true;
227 }
228
writeDimacs(const char * filename)229 bool Formula::writeDimacs(const char *filename)
230 {
231 std::ofstream os(filename);
232 return os.is_open() && writeDimacs(os);
233 }
234
writeDimacs(const string & filename)235 bool Formula::writeDimacs(const string &filename)
236 {
237 std::ofstream os(filename);
238 return os.is_open() && writeDimacs(os);
239 }
240
writeDimacs(std::ostream & f)241 bool Formula::writeDimacs(std::ostream &f)
242 {
243 f << "p cnf " << getVariableCount() << " " << getClauseCount() << std::endl;
244 for (auto &cl : m_Clauses) {
245 for (int j = 0; j < cl->m_ps.size(); ++j) {
246 #if defined(OGDF_DEBUG)
247 std::cout
248 << "Sign : "
249 << Internal::sign(cl->m_ps[j])
250 << "Var : "
251 << Internal::var(cl->m_ps[j]) + 1
252 << std::endl;
253 #endif
254 f << " "
255 << Clause::convertLitSign(cl->m_ps[j])
256 << Internal::var(cl->m_ps[j]) + 1;
257 }
258 f << " 0" << std::endl;
259 }
260 return true;
261 }
262
263 }
264