Skip to content

BMC now checks for use of lasso symbol #1201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/ebmc/bmc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Author: Daniel Kroening, dkr@amazon.com
#include "bmc.h"

#include <solvers/prop/literal_expr.h>
#include <trans-word-level/lasso.h>
#include <trans-word-level/trans_trace_word_level.h>
#include <trans-word-level/unwind.h>

Expand Down Expand Up @@ -191,6 +192,17 @@ void bmc_with_iterative_constraint_strengthening(
}
}

/// Extension of solver.handle(...) from expressions to vectors of expressions
static exprt::operandst
handles(const exprt::operandst &exprs, decision_proceduret &solver)
{
exprt::operandst result;
result.reserve(exprs.size());
for(auto &expr : exprs)
result.push_back(solver.handle(expr));
return result;
}

property_checker_resultt bmc(
std::size_t bound,
bool convert_only,
Expand All @@ -211,13 +223,21 @@ property_checker_resultt bmc(

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

::unwind(
transition_system.trans_expr, message_handler, solver, bound + 1, ns, true);
transition_system.trans_expr,
message_handler,
solver,
no_timeframes,
ns,
true);

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

bool requires_lasso_constraints = false;

for(auto &property : properties.properties)
{
if(property.is_disabled() || property.is_failure())
Expand All @@ -230,20 +250,25 @@ property_checker_resultt bmc(
continue;
}

property.timeframe_handles = ::property(
property.normalized_expr, message_handler, solver, bound + 1, ns);
auto obligations =
::property(property.normalized_expr, message_handler, no_timeframes);

if(uses_lasso_symbol(obligations))
requires_lasso_constraints = true;

property.timeframe_handles = handles(obligations, solver);

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

// lasso constraints, if needed
if(properties.requires_lasso_constraints())
if(requires_lasso_constraints)
{
message.status() << "Adding lasso constraints" << messaget::eom;
lasso_constraints(
solver, bound + 1, ns, transition_system.main_symbol->name);
solver, no_timeframes, ns, transition_system.main_symbol->name);
}

if(convert_only)
Expand Down
14 changes: 0 additions & 14 deletions src/ebmc/ebmc_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,6 @@ class ebmc_propertiest

propertyt() = default;

bool requires_lasso_constraints() const
{
return ::requires_lasso_constraints(normalized_expr);
}

bool is_exists_path() const
{
return ::is_exists_path(original_expr);
Expand Down Expand Up @@ -236,15 +231,6 @@ class ebmc_propertiest
return false;
}

bool requires_lasso_constraints() const
{
for(const auto &p : properties)
if(!p.is_disabled() && p.requires_lasso_constraints())
return true;

return false;
}

static ebmc_propertiest from_command_line(
const cmdlinet &,
const transition_systemt &,
Expand Down
32 changes: 23 additions & 9 deletions src/ebmc/liveness_to_safety.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,29 @@ class liveness_to_safetyt
}
};

/// returns true iff the given property is supported
/// by the liveness-to-safety translation
static bool property_supported(const exprt &expr)
{
return expr.id() == ID_sva_always &&
(to_sva_always_expr(expr).op().id() == ID_sva_eventually ||
to_sva_always_expr(expr).op().id() == ID_sva_s_eventually);
}

static bool have_supported_property(const ebmc_propertiest &properties)
{
for(auto &property : properties.properties)
if(!property.is_disabled())
if(property_supported(property.normalized_expr))
return true;

return false;
}

void liveness_to_safetyt::operator()()
{
// Do we have a liveness property?
if(!properties.requires_lasso_constraints())
// Do we have a supported property?
if(!have_supported_property(properties))
return; // no

// gather the state variables
Expand Down Expand Up @@ -231,15 +250,10 @@ void liveness_to_safetyt::operator()()

for(auto &property : properties.properties)
{
if(!property.is_disabled() && property.requires_lasso_constraints())
if(!property.is_disabled())
{
// We want GFp.
if(
property.normalized_expr.id() == ID_sva_always &&
(to_sva_always_expr(property.normalized_expr).op().id() ==
ID_sva_eventually ||
to_sva_always_expr(property.normalized_expr).op().id() ==
ID_sva_s_eventually))
if(property_supported(property.normalized_expr))
{
translate_GFp(property);
}
Expand Down
41 changes: 30 additions & 11 deletions src/trans-word-level/lasso.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,15 @@ Function: lasso_symbol

\*******************************************************************/

#define LASSO_PREFIX "lasso::"

symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i)
{
// True when states i and k are equal.
// We require k<i to avoid the symmetric constraints.
PRECONDITION(k < i);
irep_idt lasso_identifier =
"lasso::" + integer2string(i) + "-back-to-" + integer2string(k);
LASSO_PREFIX + integer2string(i) + "-back-to-" + integer2string(k);
return symbol_exprt(lasso_identifier, bool_typet());
}

Expand Down Expand Up @@ -136,7 +138,7 @@ void lasso_constraints(

/*******************************************************************\

Function: requires_lasso_constraints
Function: uses_lasso_symbol

Inputs:

Expand All @@ -146,21 +148,38 @@ Function: requires_lasso_constraints

\*******************************************************************/

bool requires_lasso_constraints(const exprt &expr)
bool uses_lasso_symbol(const exprt &expr)
{
for(auto subexpr_it = expr.depth_cbegin(), subexpr_end = expr.depth_cend();
subexpr_it != subexpr_end;
subexpr_it++)
{
if(
subexpr_it->id() == ID_sva_until || subexpr_it->id() == ID_sva_s_until ||
subexpr_it->id() == ID_sva_eventually ||
subexpr_it->id() == ID_sva_s_eventually || subexpr_it->id() == ID_AF ||
subexpr_it->id() == ID_F || subexpr_it->id() == ID_U)
{
return true;
}
if(subexpr_it->id() == ID_symbol)
if(to_symbol_expr(*subexpr_it).get_identifier().starts_with(LASSO_PREFIX))
{
return true;
}
}

return false;
}

/*******************************************************************\

Function: uses_lasso_symbol

Inputs:

Outputs:

Purpose:

\*******************************************************************/

bool uses_lasso_symbol(const exprt::operandst &exprs)
{
for(auto &expr : exprs)
if(::uses_lasso_symbol(expr))
return true;
return false;
}
5 changes: 3 additions & 2 deletions src/trans-word-level/lasso.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Author: Daniel Kroening, dkr@amazon.com
#ifndef CPROVER_TRANS_WORD_LEVEL_LASSO_H
#define CPROVER_TRANS_WORD_LEVEL_LASSO_H

#include <util/expr.h>
#include <util/mp_arith.h>
#include <util/namespace.h>

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

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

#endif
8 changes: 3 additions & 5 deletions src/trans-word-level/property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Author: Daniel Kroening, kroening@kroening.com
#include <util/ebmc_util.h>
#include <util/expr_iterator.h>
#include <util/expr_util.h>
#include <util/namespace.h>
#include <util/std_expr.h>
#include <util/symbol_table.h>

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

#include "instantiate_word_level.h"
#include "lasso.h"
#include "obligations.h"
#include "sequence.h"

Expand Down Expand Up @@ -797,9 +797,7 @@ Function: property
exprt::operandst property(
const exprt &property_expr,
message_handlert &message_handler,
decision_proceduret &solver,
std::size_t no_timeframes,
const namespacet &)
std::size_t no_timeframes)
{
// The first element of the pair is the length of the
// counterexample, and the second is the condition that
Expand All @@ -815,7 +813,7 @@ exprt::operandst property(
DATA_INVARIANT(
t >= 0 && t < no_timeframes, "obligation must have valid timeframe");
auto t_int = numeric_cast_v<std::size_t>(t);
prop_handles[t_int] = solver.handle(conjunction(obligation_it.second));
prop_handles[t_int] = conjunction(obligation_it.second);
}

return prop_handles;
Expand Down
23 changes: 2 additions & 21 deletions src/trans-word-level/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,16 @@ Author: Daniel Kroening, kroening@kroening.com
#include <util/expr.h>
#include <util/message.h>
#include <util/mp_arith.h>
#include <util/namespace.h>

#include <solvers/decision_procedure.h>

/// returns a vector of obligation expressions, one per timeframe
exprt::operandst property(
const exprt &property_expr,
message_handlert &,
decision_proceduret &solver,
std::size_t no_timeframes,
const namespacet &);
std::size_t no_timeframes);

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

/// Adds a constraint that can be used to determine whether the
/// given state has already been seen earlier in the trace.
void lasso_constraints(
decision_proceduret &,
const mp_integer &no_timeframes,
const namespacet &,
const irep_idt &module_identifier);

/// Is there a loop from i back to k?
/// Precondition: k<i
symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i);

/// Returns true iff the given property requires lasso constraints for BMC.
bool requires_lasso_constraints(const exprt &);

class obligationst;

obligationst property_obligations(
Expand Down
Loading