Skip to content

Commit c190ae3

Browse files
committed
BMC now checks for use of lasso symbol
Instead of examining the property, the BMC engine now looks for the use of a lasso symbol in the property encoding. This prevents a mismatch between the two methods.
1 parent c588d24 commit c190ae3

File tree

6 files changed

+68
-58
lines changed

6 files changed

+68
-58
lines changed

src/ebmc/bmc.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, dkr@amazon.com
99
#include "bmc.h"
1010

1111
#include <solvers/prop/literal_expr.h>
12+
#include <trans-word-level/lasso.h>
1213
#include <trans-word-level/trans_trace_word_level.h>
1314
#include <trans-word-level/unwind.h>
1415

@@ -191,6 +192,17 @@ void bmc_with_iterative_constraint_strengthening(
191192
}
192193
}
193194

195+
/// Extension of solver.handle(...) from expressions to vectors of expressions
196+
static exprt::operandst
197+
handles(const exprt::operandst &exprs, decision_proceduret &solver)
198+
{
199+
exprt::operandst result;
200+
result.reserve(exprs.size());
201+
for(auto &expr : exprs)
202+
result.push_back(solver.handle(expr));
203+
return result;
204+
}
205+
194206
property_checker_resultt bmc(
195207
std::size_t bound,
196208
bool convert_only,
@@ -211,13 +223,21 @@ property_checker_resultt bmc(
211223

212224
auto solver_wrapper = solver_factory(ns, message_handler);
213225
auto &solver = solver_wrapper.decision_procedure();
226+
auto no_timeframes = bound + 1;
214227

215228
::unwind(
216-
transition_system.trans_expr, message_handler, solver, bound + 1, ns, true);
229+
transition_system.trans_expr,
230+
message_handler,
231+
solver,
232+
no_timeframes,
233+
ns,
234+
true);
217235

218236
// convert the properties
219237
message.status() << "Properties" << messaget::eom;
220238

239+
bool requires_lasso_constraints = false;
240+
221241
for(auto &property : properties.properties)
222242
{
223243
if(property.is_disabled() || property.is_failure())
@@ -230,20 +250,25 @@ property_checker_resultt bmc(
230250
continue;
231251
}
232252

233-
property.timeframe_handles = ::property(
234-
property.normalized_expr, message_handler, solver, bound + 1, ns);
253+
auto obligations =
254+
::property(property.normalized_expr, message_handler, no_timeframes);
255+
256+
if(uses_lasso_symbol(obligations))
257+
requires_lasso_constraints = true;
258+
259+
property.timeframe_handles = handles(obligations, solver);
235260

236261
// If it's an assumption, then add it as constraint.
237262
if(property.is_assumed())
238263
solver.set_to_true(conjunction(property.timeframe_handles));
239264
}
240265

241266
// lasso constraints, if needed
242-
if(properties.requires_lasso_constraints())
267+
if(requires_lasso_constraints)
243268
{
244269
message.status() << "Adding lasso constraints" << messaget::eom;
245270
lasso_constraints(
246-
solver, bound + 1, ns, transition_system.main_symbol->name);
271+
solver, no_timeframes, ns, transition_system.main_symbol->name);
247272
}
248273

249274
if(convert_only)

src/ebmc/ebmc_properties.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,6 @@ class ebmc_propertiest
199199

200200
propertyt() = default;
201201

202-
bool requires_lasso_constraints() const
203-
{
204-
return ::requires_lasso_constraints(normalized_expr);
205-
}
206-
207202
bool is_exists_path() const
208203
{
209204
return ::is_exists_path(original_expr);
@@ -236,15 +231,6 @@ class ebmc_propertiest
236231
return false;
237232
}
238233

239-
bool requires_lasso_constraints() const
240-
{
241-
for(const auto &p : properties)
242-
if(!p.is_disabled() && p.requires_lasso_constraints())
243-
return true;
244-
245-
return false;
246-
}
247-
248234
static ebmc_propertiest from_command_line(
249235
const cmdlinet &,
250236
const transition_systemt &,

src/trans-word-level/lasso.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ Function: lasso_symbol
5959
6060
\*******************************************************************/
6161

62+
#define LASSO_PREFIX "lasso::"
63+
6264
symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i)
6365
{
6466
// True when states i and k are equal.
6567
// We require k<i to avoid the symmetric constraints.
6668
PRECONDITION(k < i);
6769
irep_idt lasso_identifier =
68-
"lasso::" + integer2string(i) + "-back-to-" + integer2string(k);
70+
LASSO_PREFIX + integer2string(i) + "-back-to-" + integer2string(k);
6971
return symbol_exprt(lasso_identifier, bool_typet());
7072
}
7173

@@ -136,7 +138,7 @@ void lasso_constraints(
136138

137139
/*******************************************************************\
138140
139-
Function: requires_lasso_constraints
141+
Function: uses_lasso_symbol
140142
141143
Inputs:
142144
@@ -146,21 +148,38 @@ Function: requires_lasso_constraints
146148
147149
\*******************************************************************/
148150

149-
bool requires_lasso_constraints(const exprt &expr)
151+
bool uses_lasso_symbol(const exprt &expr)
150152
{
151153
for(auto subexpr_it = expr.depth_cbegin(), subexpr_end = expr.depth_cend();
152154
subexpr_it != subexpr_end;
153155
subexpr_it++)
154156
{
155-
if(
156-
subexpr_it->id() == ID_sva_until || subexpr_it->id() == ID_sva_s_until ||
157-
subexpr_it->id() == ID_sva_eventually ||
158-
subexpr_it->id() == ID_sva_s_eventually || subexpr_it->id() == ID_AF ||
159-
subexpr_it->id() == ID_F || subexpr_it->id() == ID_U)
160-
{
161-
return true;
162-
}
157+
if(subexpr_it->id() == ID_symbol)
158+
if(to_symbol_expr(*subexpr_it).get_identifier().starts_with(LASSO_PREFIX))
159+
{
160+
return true;
161+
}
163162
}
164163

165164
return false;
166165
}
166+
167+
/*******************************************************************\
168+
169+
Function: uses_lasso_symbol
170+
171+
Inputs:
172+
173+
Outputs:
174+
175+
Purpose:
176+
177+
\*******************************************************************/
178+
179+
bool uses_lasso_symbol(const exprt::operandst &exprs)
180+
{
181+
for(auto &expr : exprs)
182+
if(::uses_lasso_symbol(expr))
183+
return true;
184+
return false;
185+
}

src/trans-word-level/lasso.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, dkr@amazon.com
99
#ifndef CPROVER_TRANS_WORD_LEVEL_LASSO_H
1010
#define CPROVER_TRANS_WORD_LEVEL_LASSO_H
1111

12+
#include <util/expr.h>
1213
#include <util/mp_arith.h>
1314
#include <util/namespace.h>
1415

@@ -26,7 +27,7 @@ void lasso_constraints(
2627
/// Precondition: k<i
2728
symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i);
2829

29-
/// Returns true iff the given property requires lasso constraints for BMC.
30-
bool requires_lasso_constraints(const exprt &);
30+
/// Returns true iff the given formula uses a lasso symbol
31+
bool uses_lasso_symbol(const exprt::operandst &);
3132

3233
#endif

src/trans-word-level/property.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com
1212
#include <util/ebmc_util.h>
1313
#include <util/expr_iterator.h>
1414
#include <util/expr_util.h>
15-
#include <util/namespace.h>
1615
#include <util/std_expr.h>
1716
#include <util/symbol_table.h>
1817

@@ -24,6 +23,7 @@ Author: Daniel Kroening, kroening@kroening.com
2423
#include <verilog/sva_expr.h>
2524

2625
#include "instantiate_word_level.h"
26+
#include "lasso.h"
2727
#include "obligations.h"
2828
#include "sequence.h"
2929

@@ -797,9 +797,7 @@ Function: property
797797
exprt::operandst property(
798798
const exprt &property_expr,
799799
message_handlert &message_handler,
800-
decision_proceduret &solver,
801-
std::size_t no_timeframes,
802-
const namespacet &)
800+
std::size_t no_timeframes)
803801
{
804802
// The first element of the pair is the length of the
805803
// counterexample, and the second is the condition that
@@ -815,7 +813,7 @@ exprt::operandst property(
815813
DATA_INVARIANT(
816814
t >= 0 && t < no_timeframes, "obligation must have valid timeframe");
817815
auto t_int = numeric_cast_v<std::size_t>(t);
818-
prop_handles[t_int] = solver.handle(conjunction(obligation_it.second));
816+
prop_handles[t_int] = conjunction(obligation_it.second);
819817
}
820818

821819
return prop_handles;

src/trans-word-level/property.h

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,16 @@ Author: Daniel Kroening, kroening@kroening.com
1212
#include <util/expr.h>
1313
#include <util/message.h>
1414
#include <util/mp_arith.h>
15-
#include <util/namespace.h>
16-
17-
#include <solvers/decision_procedure.h>
1815

16+
/// returns a vector of obligation expressions, one per timeframe
1917
exprt::operandst property(
2018
const exprt &property_expr,
2119
message_handlert &,
22-
decision_proceduret &solver,
23-
std::size_t no_timeframes,
24-
const namespacet &);
20+
std::size_t no_timeframes);
2521

2622
/// Is the given property supported by word-level unwinding?
2723
bool bmc_supports_property(const exprt &);
2824

29-
/// Adds a constraint that can be used to determine whether the
30-
/// given state has already been seen earlier in the trace.
31-
void lasso_constraints(
32-
decision_proceduret &,
33-
const mp_integer &no_timeframes,
34-
const namespacet &,
35-
const irep_idt &module_identifier);
36-
37-
/// Is there a loop from i back to k?
38-
/// Precondition: k<i
39-
symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i);
40-
41-
/// Returns true iff the given property requires lasso constraints for BMC.
42-
bool requires_lasso_constraints(const exprt &);
43-
4425
class obligationst;
4526

4627
obligationst property_obligations(

0 commit comments

Comments
 (0)