CBMC
qbf_skizzo_core.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: CM Wintersteiger
6 
7 \*******************************************************************/
8 
9 #include <fstream>
10 
11 #include <util/invariant.h>
12 
13 #include <util/string2int.h>
14 
15 #include <cuddObj.hh> // CUDD Library
16 
18 // FIX FOR THE CUDD LIBRARY
19 
20 inline DdNode *DD::getNode() const
21 {
22  return node;
23 } // DD::getNode
26 #include <dddmp.h>
27 
28 #include "qbf_skizzo_core.h"
29 
32 {
33  // skizzo crashes on broken lines
34  break_lines=false;
35  qbf_tmp_file="sKizzo.qdimacs";
36 }
37 
39 {
40 }
41 
42 std::string qbf_skizzo_coret::solver_text() const
43 {
44  return "Skizzo/Core";
45 }
46 
48 {
49  // sKizzo crashes on empty instances
50  if(no_clauses()==0)
51  return P_SATISFIABLE;
52 
53  {
54  std::string msg=
55  "Skizzo: "+
56  std::to_string(no_variables())+" variables, "+
57  std::to_string(no_clauses())+" clauses";
58  messaget::status() << msg << messaget::eom;
59  }
60 
61  std::string result_tmp_file="sKizzo.out";
62 
63  {
64  std::ofstream out(qbf_tmp_file.c_str());
65 
66  // write it
67  break_lines=false;
68  write_qdimacs_cnf(out);
69  }
70 
71  std::string options;
72 
73  // solve it
74  system((
75  "sKizzo -log "+qbf_tmp_file+options+" > "+result_tmp_file).c_str());
76 
77  bool result=false;
78 
79  // read result
80  {
81  std::ifstream in(result_tmp_file.c_str());
82 
83  bool result_found=false;
84  while(in)
85  {
86  std::string line;
87 
88  std::getline(in, line);
89 
90  if(!line.empty() && line[line.size() - 1] == '\r')
91  line.resize(line.size()-1);
92 
93  if(line=="The instance evaluates to TRUE.")
94  {
95  result=true;
96  result_found=true;
97  break;
98  }
99  else if(line=="The instance evaluates to FALSE.")
100  {
101  result=false;
102  result_found=true;
103  break;
104  }
105  }
106 
107  if(!result_found)
108  {
109  messaget::error() << "Skizzo failed: unknown result" << messaget::eom;
110  return P_ERROR;
111  }
112  }
113 
114  remove(result_tmp_file.c_str());
115  remove(qbf_tmp_file.c_str());
116 
117  if(result)
118  {
119  messaget::status() << "Skizzo: TRUE" << messaget::eom;
120 
121  if(get_certificate())
122  return P_ERROR;
123 
124  return P_SATISFIABLE;
125  }
126  else
127  {
128  messaget::status() << "Skizzo: FALSE" << messaget::eom;
129  return P_UNSATISFIABLE;
130  }
131 }
132 
134 {
136 }
137 
139 {
141 }
142 
144 {
145  std::string result_tmp_file="ozziKs.out";
146  std::string options="-dump qbm=bdd";
147  std::string log_file=qbf_tmp_file+".sKizzo.log";
148 
149  system((
150  "ozziKs "+options+" "+log_file+" > "+result_tmp_file).c_str());
151 
152  // read result
153  bool result=false;
154  {
155  std::ifstream in(result_tmp_file.c_str());
156  std::string key=" [OK, VALID,";
157 
158  while(in)
159  {
160  std::string line;
161 
162  std::getline(in, line);
163 
164  if(!line.empty() && line[line.size() - 1] == '\r')
165  line.resize(line.size()-1);
166 
167  if(line.compare(0, key.size(), key)==0)
168  {
169  result=true;
170  break;
171  }
172  }
173  }
174 
175  if(!result)
176  {
177  messaget::error() << "Skizzo failed: unknown result" << messaget::eom;
178  return true;
179  }
180 
181  remove(result_tmp_file.c_str());
182  remove(log_file.c_str());
183 
184  // certificate reconstruction done, now let's load it from the .qbm file
185 
186  int n_e;
187  std::vector<int> e_list;
188  int e_max=0;
189 
190  // check header
191  result=false;
192  {
193  std::ifstream in((qbf_tmp_file+".qbm").c_str());
194  std::string key="# existentials[";
195 
196  std::string line;
197  std::getline(in, line);
198 
200  line == "# QBM file, 1.3",
201  "QBM file has to start with this exact string: ",
202  "# QBM file, 1.3");
203 
204  while(in)
205  {
206  std::getline(in, line);
207 
208  if(!line.empty() && line[line.size() - 1] == '\r')
209  line.resize(line.size()-1);
210 
211  if(line.compare(0, key.size(), key)==0)
212  {
213  result=true;
214  break;
215  }
216  }
217 
218  size_t ob=line.find('[');
219  std::string n_es=line.substr(ob+1, line.find(']')-ob-1);
220  n_e=unsafe_string2int(n_es);
221  INVARIANT(n_e != 0, "there has to be at least one existential variable");
222 
223  e_list.resize(n_e);
224  std::string e_lists=line.substr(line.find(':')+2);
225 
226  for(int i=0; i<n_e; i++)
227  {
228  size_t space=e_lists.find(' ');
229 
230  int cur=unsafe_string2int(e_lists.substr(0, space));
231  INVARIANT(cur != 0, "variable numbering starts with 1");
232 
233  e_list[i]=cur;
234  if(cur>e_max)
235  e_max=cur;
236 
237  e_lists=e_lists.substr(space+1);
238  }
239 
240  INVARIANT(result, "existential mapping from sKizzo missing");
241 
242  in.close();
243 
244  // workaround for long comments
245  system((
246  "sed -e \"s/^#.*$/# no comment/\" -i "+qbf_tmp_file+".qbm").c_str());
247  }
248 
249 
250  {
251  DdNode **bdds;
252  std::string bdd_file=qbf_tmp_file+".qbm";
253 
254  // dddmp insists on a non-const string here...
255  // The linter insists on compile time constant for arrays
256  char filename[bdd_file.size()+1]; // NOLINT(*)
257  snprintf(filename, bdd_file.size()+1, bdd_file.c_str());
258 
259  bdd_manager->AutodynEnable(CUDD_REORDER_SIFT);
260 
261  int nroots=
262  Dddmp_cuddBddArrayLoad(
263  bdd_manager->getManager(),
264  DDDMP_ROOT_MATCHLIST,
265  NULL,
266  DDDMP_VAR_MATCHIDS,
267  NULL,
268  NULL,
269  NULL,
270  DDDMP_MODE_DEFAULT,
271  filename,
272  NULL,
273  &bdds);
274 
275  INVARIANT(
276  nroots == 2 * n_e,
277  "valid QBM certificate should have twice as much roots as the "
278  "existential variables");
279 
280  model_bdds.resize(e_max+1, NULL);
281 
282  for(unsigned i=0; i<e_list.size(); i++)
283  {
284  int cur=e_list[i];
285  DdNode *posNode=bdds[2*i];
286  DdNode *negNode=bdds[2*i+1];
287 
288  if(Cudd_DagSize(posNode)<=Cudd_DagSize(negNode))
289  model_bdds[cur]=new BDD(*bdd_manager, posNode);
290  else
291  model_bdds[cur]=new BDD(*bdd_manager, Cudd_Not(negNode));
292  }
293 
294  // tell CUDD that we don't need those BDDs anymore.
295  for(int i=0; i<nroots; i++)
296  Cudd_Deref(bdds[i]);
297 
298  free(bdds);
299  bdds=NULL;
300  remove(bdd_file.c_str());
301  remove((qbf_tmp_file+".qbm").c_str());
302  }
303 
304 
305  return false;
306 }
size_t no_clauses() const override
virtual size_t no_variables() const override
Definition: cnf.h:42
bool break_lines
Definition: dimacs_cnf.h:42
mstreamt & error() const
Definition: message.h:399
mstreamt & status() const
Definition: message.h:414
static eomt eom
Definition: message.h:297
resultt
Definition: prop.h:101
model_bddst model_bdds
Definition: qbf_bdd_core.h:27
bool get_certificate(void)
std::string qbf_tmp_file
resultt prop_solve() override
std::string solver_text() const override
bool is_in_core(literalt l) const override
modeltypet m_get(literalt a) const override
~qbf_skizzo_coret() override
virtual void write_qdimacs_cnf(std::ostream &out)
Definition: qdimacs_cnf.cpp:15
#define UNIMPLEMENTED
Definition: invariant.h:558
#define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Same as invariant, with one or more diagnostics attached Diagnostics can be of any type that has a sp...
Definition: invariant.h:437
int snprintf(char *str, size_t size, const char *fmt,...)
Definition: stdio.c:1712
void free(void *ptr)
Definition: stdlib.c:317
int unsafe_string2int(const std::string &str, int base)
Definition: string2int.cpp:30
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.