CBMC
external_sat.cpp
Go to the documentation of this file.
1 
6 #include "external_sat.h"
7 
8 #include "dimacs_cnf.h"
9 
10 #include <util/run.h>
11 #include <util/string_utils.h>
12 #include <util/tempfile.h>
13 
14 #include <algorithm>
15 #include <cstdlib>
16 #include <fstream>
17 #include <string>
18 
19 external_satt::external_satt(message_handlert &message_handler, std::string cmd)
20  : cnf_clause_list_assignmentt(message_handler), solver_cmd(std::move(cmd))
21 {
22 }
23 
24 const std::string external_satt::solver_text()
25 {
26  return "External SAT solver";
27 }
28 
30 {
32 }
33 
35 {
37 }
38 
39 void external_satt::write_cnf_file(std::string cnf_file)
40 {
41  log.status() << "Writing temporary CNF" << messaget::eom;
42  std::ofstream out(cnf_file);
43 
44  // We start counting at 1, thus there is one variable fewer.
45  out << "p cnf " << (no_variables() - 1) << ' '
46  << no_clauses() + assumptions.size() << '\n';
47 
48  // output the problem clauses
49  for(auto &c : clauses)
50  dimacs_cnft::write_dimacs_clause(c, out, false);
51 
52  // output the assumption clauses
53  for(const auto &literal : assumptions)
54  {
55  if(!literal.is_constant())
56  out << literal.dimacs() << " 0\n";
57  }
58 
59  out.close();
60 }
61 
62 std::string external_satt::execute_solver(std::string cnf_file)
63 {
64  log.status() << "Invoking SAT solver" << messaget::eom;
65  std::ostringstream response_ostream;
66  auto cmd_result = run(solver_cmd, {"", cnf_file}, "", response_ostream, "");
67 
68  log.status() << "Solver returned code: " << cmd_result << messaget::eom;
69  return response_ostream.str();
70 }
71 
73 {
74  std::istringstream response_istream(solver_output);
75  std::string line;
77  std::vector<bool> assigned_variables(no_variables(), false);
78  assignment.insert(assignment.begin(), no_variables(), tvt(false));
79 
80  while(getline(response_istream, line))
81  {
82  if(line[0] == 's')
83  {
84  auto parts = split_string(line, ' ');
85  if(parts.size() < 2)
86  {
87  log.error() << "external SAT solver has provided an unexpected "
88  "response in results.\nUnexpected reponse: "
89  << line << messaget::eom;
90  return resultt::P_ERROR;
91  }
92 
93  auto status = parts[1];
94  log.status() << "result:" << status << messaget::eom;
95  if(status == "UNSATISFIABLE")
96  {
98  }
99  if(status == "SATISFIABLE")
100  {
101  result = resultt::P_SATISFIABLE;
102  }
103  if(status == "TIMEOUT")
104  {
105  log.error() << "external SAT solver reports a timeout" << messaget::eom;
106  return resultt::P_ERROR;
107  }
108  }
109 
110  if(line[0] == 'v')
111  {
112  auto assignments = split_string(line, ' ');
113 
114  // remove the first element which should be 'v' identifying
115  // the line as the satisfying assignments
116  assignments.erase(assignments.begin());
117  auto number_of_variables = no_variables();
118  for(auto &assignment_string : assignments)
119  {
120  try
121  {
122  signed long long as_long = std::stol(assignment_string);
123  size_t index = std::labs(as_long);
124 
125  if(index >= number_of_variables)
126  {
127  log.error() << "SAT assignment " << as_long
128  << " out of range of CBMC largest variable of "
129  << (number_of_variables - 1) << messaget::eom;
130  return resultt::P_ERROR;
131  }
132  assignment[index] = tvt(as_long >= 0);
133  assigned_variables[index] = true;
134  }
135  catch(...)
136  {
137  log.error() << "SAT assignment " << assignment_string
138  << " caused an exception while processing"
139  << messaget::eom;
140  return resultt::P_ERROR;
141  }
142  }
143  // Assignments can span multiple lines so returning early isn't an option
144  }
145  }
146 
147  if(result == resultt::P_SATISFIABLE)
148  {
149  // We don't need to check zero
150  for(size_t index = 1; index < no_variables(); index++)
151  {
152  if(!assigned_variables[index])
153  {
154  log.error() << "No assignment was found for literal: " << index
155  << messaget::eom;
156  return resultt::P_ERROR;
157  }
158  }
159  return resultt::P_SATISFIABLE;
160  }
161 
162  log.error() << "external SAT solver has provided an unexpected response"
163  << messaget::eom;
164  return resultt::P_ERROR;
165 }
166 
168 {
169  // are we assuming 'false'?
170  if(
171  std::find(assumptions.begin(), assumptions.end(), const_literal(false)) !=
172  assumptions.end())
173  {
175  }
176 
177  // create a temporary file
178  temporary_filet cnf_file("external-sat", ".cnf");
179  write_cnf_file(cnf_file());
180  auto output = execute_solver(cnf_file());
181  return parse_result(output);
182 }
tempfile.h
UNIMPLEMENTED
#define UNIMPLEMENTED
Definition: invariant.h:525
cnf_clause_listt::clauses
clausest clauses
Definition: cnf_clause_list.h:85
string_utils.h
messaget::status
mstreamt & status() const
Definition: message.h:414
propt::resultt::P_UNSATISFIABLE
@ P_UNSATISFIABLE
cnf_clause_list_assignmentt
Definition: cnf_clause_list.h:91
run
int run(const std::string &what, const std::vector< std::string > &argv)
Definition: run.cpp:48
external_satt::write_cnf_file
void write_cnf_file(std::string)
Definition: external_sat.cpp:39
messaget::eom
static eomt eom
Definition: message.h:297
run.h
dimacs_cnft::write_dimacs_clause
static void write_dimacs_clause(const bvt &, std::ostream &, bool break_lines)
Definition: dimacs_cnf.cpp:53
external_satt::solver_cmd
std::string solver_cmd
Definition: external_sat.h:36
cnf_clause_listt::no_clauses
size_t no_clauses() const override
Definition: cnf_clause_list.h:42
split_string
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
Definition: string_utils.cpp:39
external_satt::do_prop_solve
resultt do_prop_solve() override
Definition: external_sat.cpp:167
messaget::error
mstreamt & error() const
Definition: message.h:399
external_sat.h
propt::resultt::P_ERROR
@ P_ERROR
propt::resultt::P_SATISFIABLE
@ P_SATISFIABLE
external_satt::external_satt
external_satt(message_handlert &message_handler, std::string cmd)
Definition: external_sat.cpp:19
external_satt::is_in_conflict
bool is_in_conflict(literalt) const override
Returns true if an assumption is in the final conflict.
Definition: external_sat.cpp:29
const_literal
literalt const_literal(bool value)
Definition: literal.h:188
external_satt::solver_text
const std::string solver_text() override
Definition: external_sat.cpp:24
message_handlert
Definition: message.h:27
propt::resultt
resultt
Definition: prop.h:97
external_satt::assumptions
bvt assumptions
Definition: external_sat.h:37
tvt
Definition: threeval.h:19
dimacs_cnf.h
literalt
Definition: literal.h:25
propt::log
messaget log
Definition: prop.h:128
cnft::no_variables
virtual size_t no_variables() const override
Definition: cnf.h:42
external_satt::set_assignment
void set_assignment(literalt, bool) override
Definition: external_sat.cpp:34
cnf_clause_list_assignmentt::assignment
assignmentt assignment
Definition: cnf_clause_list.h:126
temporary_filet
Definition: tempfile.h:23
external_satt::execute_solver
std::string execute_solver(std::string)
Definition: external_sat.cpp:62
external_satt::parse_result
resultt parse_result(std::string)
Definition: external_sat.cpp:72