yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ezminisat.cc
Go to the documentation of this file.
1 /*
2  * ezSAT -- A simple and easy to use CNF generator for SAT solvers
3  *
4  * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 // needed for MiniSAT headers (see Minisat Makefile)
21 #define __STDC_LIMIT_MACROS
22 #define __STDC_FORMAT_MACROS
23 
24 #include "ezminisat.h"
25 
26 #include <limits.h>
27 #include <stdint.h>
28 #include <csignal>
29 #include <cinttypes>
30 
31 #ifndef _WIN32
32 # include <unistd.h>
33 #endif
34 
35 #include "../minisat/Solver.h"
36 #include "../minisat/SimpSolver.h"
37 
38 ezMiniSAT::ezMiniSAT() : minisatSolver(NULL)
39 {
41  foundContradiction = false;
42 
45 }
46 
48 {
49  if (minisatSolver != NULL)
50  delete minisatSolver;
51 }
52 
54 {
55  if (minisatSolver != NULL) {
56  delete minisatSolver;
58  }
59  foundContradiction = false;
60  minisatVars.clear();
61 #if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
62  cnfFrozenVars.clear();
63 #endif
64  ezSAT::clear();
65 }
66 
67 #if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
68 void ezMiniSAT::freeze(int id)
69 {
70  if (!mode_non_incremental())
71  cnfFrozenVars.insert(bind(id));
72 }
73 
74 bool ezMiniSAT::eliminated(int idx)
75 {
76  idx = idx < 0 ? -idx : idx;
77  if (minisatSolver != NULL && idx > 0 && idx <= int(minisatVars.size()))
78  return minisatSolver->isEliminated(minisatVars.at(idx-1));
79  return false;
80 }
81 #endif
82 
83 #ifndef _WIN32
86 
88 {
89  if (clock() > alarmHandlerTimeout) {
92  } else
93  alarm(1);
94 }
95 #endif
96 
97 bool ezMiniSAT::solver(const std::vector<int> &modelExpressions, std::vector<bool> &modelValues, const std::vector<int> &assumptions)
98 {
100 
101  solverTimoutStatus = false;
102 
103  if (0) {
104 contradiction:
105  delete minisatSolver;
107  minisatVars.clear();
108  foundContradiction = true;
109  return false;
110  }
111 
112  if (foundContradiction) {
113  consumeCnf();
114  return false;
115  }
116 
117  std::vector<int> extraClauses, modelIdx;
118 
119  for (auto id : assumptions)
120  extraClauses.push_back(bind(id));
121  for (auto id : modelExpressions)
122  modelIdx.push_back(bind(id));
123 
124  if (minisatSolver == NULL) {
125  minisatSolver = new Solver;
127  }
128 
129 #if EZMINISAT_INCREMENTAL
130  std::vector<std::vector<int>> cnf;
131  consumeCnf(cnf);
132 #else
133  const std::vector<std::vector<int>> &cnf = this->cnf();
134 #endif
135 
136  while (int(minisatVars.size()) < numCnfVariables())
137  minisatVars.push_back(minisatSolver->newVar());
138 
139 #if EZMINISAT_SIMPSOLVER && EZMINISAT_INCREMENTAL
140  for (auto idx : cnfFrozenVars)
141  minisatSolver->setFrozen(minisatVars.at(idx > 0 ? idx-1 : -idx-1), true);
142  cnfFrozenVars.clear();
143 #endif
144 
145  for (auto &clause : cnf) {
147  for (auto idx : clause) {
148  if (idx > 0)
149  ps.push(Minisat::mkLit(minisatVars.at(idx-1)));
150  else
151  ps.push(Minisat::mkLit(minisatVars.at(-idx-1), true));
152 #if EZMINISAT_SIMPSOLVER
153  if (minisatSolver->isEliminated(minisatVars.at(idx > 0 ? idx-1 : -idx-1))) {
154  fprintf(stderr, "Assert in %s:%d failed! Missing call to ezsat->freeze(): %s (lit=%d)\n",
155  __FILE__, __LINE__, cnfLiteralInfo(idx).c_str(), idx);
156  abort();
157  }
158 #endif
159  }
160  if (!minisatSolver->addClause(ps))
161  goto contradiction;
162  }
163 
164  if (cnf.size() > 0 && !minisatSolver->simplify())
165  goto contradiction;
166 
168 
169  for (auto idx : extraClauses) {
170  if (idx > 0)
171  assumps.push(Minisat::mkLit(minisatVars.at(idx-1)));
172  else
173  assumps.push(Minisat::mkLit(minisatVars.at(-idx-1), true));
174 #if EZMINISAT_SIMPSOLVER
175  if (minisatSolver->isEliminated(minisatVars.at(idx > 0 ? idx-1 : -idx-1))) {
176  fprintf(stderr, "Assert in %s:%d failed! Missing call to ezsat->freeze(): %s\n", __FILE__, __LINE__, cnfLiteralInfo(idx).c_str());
177  abort();
178  }
179 #endif
180  }
181 
182 #ifndef _WIN32
183  struct sigaction sig_action;
184  struct sigaction old_sig_action;
185  int old_alarm_timeout = 0;
186 
187  if (solverTimeout > 0) {
188  sig_action.sa_handler = alarmHandler;
189  sigemptyset(&sig_action.sa_mask);
190  sig_action.sa_flags = SA_RESTART;
191  alarmHandlerThis = this;
192  alarmHandlerTimeout = clock() + solverTimeout*CLOCKS_PER_SEC;
193  old_alarm_timeout = alarm(0);
194  sigaction(SIGALRM, &sig_action, &old_sig_action);
195  alarm(1);
196  }
197 #endif
198 
199  bool foundSolution = minisatSolver->solve(assumps);
200 
201 #ifndef _WIN32
202  if (solverTimeout > 0) {
203  if (alarmHandlerTimeout == 0)
204  solverTimoutStatus = true;
205  alarm(0);
206  sigaction(SIGALRM, &old_sig_action, NULL);
207  alarm(old_alarm_timeout);
208  }
209 #endif
210 
211  if (!foundSolution) {
212 #if !EZMINISAT_INCREMENTAL
213  delete minisatSolver;
215  minisatVars.clear();
216 #endif
217  return false;
218  }
219 
220  modelValues.clear();
221  modelValues.resize(modelIdx.size());
222 
223  for (size_t i = 0; i < modelIdx.size(); i++)
224  {
225  int idx = modelIdx[i];
226  bool refvalue = true;
227 
228  if (idx < 0)
229  idx = -idx, refvalue = false;
230 
231  using namespace Minisat;
233  modelValues[i] = (value == Minisat::lbool(refvalue));
234  }
235 
236 #if !EZMINISAT_INCREMENTAL
237  delete minisatSolver;
239  minisatVars.clear();
240 #endif
241  return true;
242 }
243 
Solver * minisatSolver
Definition: ezminisat.h:46
void interrupt()
Definition: Solver.h:371
const std::vector< std::vector< int > > & cnf() const
Definition: ezsat.h:168
std::string cnfLiteralInfo(int idx) const
Definition: ezsat.cc:503
#define EZMINISAT_VERBOSITY
Definition: ezminisat.h:24
bool simplify()
Definition: Solver.cc:643
Lit mkLit(Var var, bool sign=false)
Definition: SolverTypes.h:63
int solverTimeout
Definition: ezsat.h:80
lbool modelValue(Var x) const
Definition: Solver.h:352
Minisat::SimpSolver Solver
Definition: ezminisat.h:42
void setFrozen(Var v, bool b)
Definition: SimpSolver.h:192
static const int CONST_FALSE
Definition: ezsat.h:49
static std::string idx(std::string str)
Definition: test_autotb.cc:57
static void alarmHandler(int)
Definition: ezminisat.cc:87
int value(bool val)
Definition: ezsat.cc:68
void consumeCnf()
Definition: ezsat.cc:606
void preSolverCallback()
Definition: ezsat.cc:632
std::set< int > cnfFrozenVars
Definition: ezminisat.h:51
int numCnfVariables() const
Definition: ezsat.h:166
static ezMiniSAT * alarmHandlerThis
Definition: ezminisat.h:55
Var newVar(lbool upol=l_Undef, bool dvar=true)
Definition: SimpSolver.cc:79
virtual bool eliminated(int idx)
void push(void)
Definition: Vec.h:74
bool addClause(const vec< Lit > &ps)
Definition: SimpSolver.h:186
bool foundContradiction
Definition: ezminisat.h:48
bool solverTimoutStatus
Definition: ezsat.h:81
static const int CONST_TRUE
Definition: ezsat.h:48
bool isEliminated(Var v) const
Definition: SimpSolver.h:178
virtual bool solver(const std::vector< int > &modelExpressions, std::vector< bool > &modelValues, const std::vector< int > &assumptions)
Definition: ezminisat.cc:97
std::vector< int > minisatVars
Definition: ezminisat.h:47
#define NULL
virtual void clear()
Definition: ezsat.cc:369
virtual ~ezMiniSAT()
Definition: ezminisat.cc:47
bool mode_non_incremental() const
Definition: ezsat.h:90
virtual void clear()
Definition: ezminisat.cc:53
virtual void freeze(int id)
bool solve(const vec< Lit > &assumps, bool do_simp=true, bool turn_off_simp=false)
Definition: SimpSolver.h:213
static clock_t alarmHandlerTimeout
Definition: ezminisat.h:56
int bind(int id, bool auto_freeze=true)
Definition: ezsat.cc:520