Skip to content

Commit dcc7498

Browse files
Merge pull request diffblue#15 from thomasspriggs/tas/no_values_of_quantifiers
Fix errors from issue 5970
2 parents cb665b7 + 2898f43 commit dcc7498

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
lines changed

src/solvers/smt2/smt2_conv.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,15 @@ exprt smt2_convt::get(const exprt &expr) const
319319
}
320320
else if(expr.is_constant())
321321
return expr;
322+
else if(const auto &array = expr_try_dynamic_cast<array_exprt>(expr))
323+
{
324+
exprt array_copy = *array;
325+
for(auto &element : array_copy.operands())
326+
{
327+
element = get(element);
328+
}
329+
return array_copy;
330+
}
322331

323332
return nil_exprt();
324333
}
@@ -745,6 +754,14 @@ literalt smt2_convt::convert(const exprt &expr)
745754
no_boolean_variables++;
746755

747756
out << "; convert\n";
757+
out << "; Converting var_no " << l.var_no() << " with expr ID of "
758+
<< expr.id_string() << "\n";
759+
// We're converting the expression, so store it in the defined_expressions
760+
// store and in future we use the literal instead of the whole expression
761+
// Note that here we are always converting, so we do not need to consider
762+
// other literal kinds, only "|B###|"
763+
defined_expressions[expr] =
764+
std::string{"|B"} + std::to_string(l.var_no()) + "|";
748765
out << "(define-fun ";
749766
convert_literal(l);
750767
out << " () Bool ";
@@ -4314,18 +4331,27 @@ void smt2_convt::set_to(const exprt &expr, bool value)
43144331

43154332
out << "; set_to " << (value?"true":"false") << "\n"
43164333
<< "(assert ";
4317-
43184334
if(!value)
43194335
{
43204336
out << "(not ";
4321-
convert_expr(prepared_expr);
4322-
out << ")";
4337+
}
4338+
const auto found_literal = defined_expressions.find(expr);
4339+
if(!(found_literal == defined_expressions.end()))
4340+
{
4341+
// This is a converted expression, we can just assert the literal name
4342+
// since the expression is already defined
4343+
out << found_literal->second;
4344+
set_values[found_literal->second] = value;
43234345
}
43244346
else
4347+
{
43254348
convert_expr(prepared_expr);
4326-
4327-
out << ")" << "\n"; // assert
4328-
4349+
}
4350+
if(!value)
4351+
{
4352+
out << ")";
4353+
}
4354+
out << ")\n";
43294355
return;
43304356
}
43314357

src/solvers/smt2/smt2_conv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ class smt2_convt : public stack_decision_proceduret
225225

226226
typedef std::map<exprt, irep_idt> defined_expressionst;
227227
defined_expressionst defined_expressions;
228+
/// The values which boolean identifiers have been `smt2_convt::set_to` or
229+
/// in other words those which are asserted as true / false in the output
230+
/// smt2 formula.
231+
std::unordered_map<irep_idt, bool> set_values;
228232

229233
defined_expressionst object_sizes;
230234

src/solvers/smt2/smt2_dec.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ decision_proceduret::resultt smt2_dect::read_result(std::istream &in)
139139
boolean_assignment.resize(no_boolean_variables, false);
140140

141141
typedef std::unordered_map<irep_idt, irept> valuest;
142-
valuest values;
142+
valuest parsed_values;
143143

144144
while(in)
145145
{
@@ -167,37 +167,54 @@ decision_proceduret::resultt smt2_dect::read_result(std::istream &in)
167167
// ( (|some_integer| 0) )
168168
// ( (|some_integer| (- 10)) )
169169

170-
values[s0.id()] = s1;
170+
parsed_values[s0.id()] = s1;
171171
}
172172
else if(
173173
parsed.id().empty() && parsed.get_sub().size() == 2 &&
174174
parsed.get_sub().front().id() == "error")
175175
{
176+
const auto &message = id2string(parsed.get_sub()[1].id());
177+
176178
// We ignore errors after UNSAT because get-value after check-sat
177179
// returns unsat will give an error.
178-
if(res != resultt::D_UNSATISFIABLE)
180+
if(
181+
res != resultt::D_UNSATISFIABLE &&
182+
!(solver == solvert::Z3 &&
183+
message.find("must not contain quantifiers") != std::string::npos))
179184
{
180185
messaget log{message_handler};
181186
log.error() << "SMT2 solver returned error message:\n"
182-
<< "\t\"" << parsed.get_sub()[1].id() << "\""
183-
<< messaget::eom;
187+
<< "\t\"" << message << "\"" << messaget::eom;
184188
return decision_proceduret::resultt::D_ERROR;
185189
}
186190
}
187191
}
188192

193+
if(res != resultt::D_SATISFIABLE)
194+
return res;
195+
189196
for(auto &assignment : identifier_map)
190197
{
191198
std::string conv_id = convert_identifier(assignment.first);
192-
const irept &value = values[conv_id];
199+
const irept &value = parsed_values[conv_id];
193200
assignment.second.value = parse_rec(value, assignment.second.type);
194201
}
195202

196203
// Booleans
197204
for(unsigned v = 0; v < no_boolean_variables; v++)
198205
{
199-
const irept &value = values["B" + std::to_string(v)];
200-
boolean_assignment[v] = (value.id() == ID_true);
206+
const std::string boolean_identifier = "B" + std::to_string(v);
207+
boolean_assignment[v] = [&]() {
208+
const auto found_parsed_value = parsed_values.find(boolean_identifier);
209+
if(found_parsed_value != parsed_values.end())
210+
return found_parsed_value->second.id() == ID_true;
211+
// Work out the value based on what set_to was called with.
212+
const auto found_set_value =
213+
set_values.find('|' + boolean_identifier + '|');
214+
if(found_set_value != set_values.end())
215+
return found_set_value->second;
216+
UNREACHABLE;
217+
}();
201218
}
202219

203220
return res;

0 commit comments

Comments
 (0)