Skip to content

Commit ed453c4

Browse files
authored
Merge pull request #1043 from diffblue/bdd-property-supported
BDD engine: only look for atomic propositions in supported properties
2 parents f98faf5 + 6bc4a23 commit ed453c4

File tree

5 files changed

+127
-18
lines changed

5 files changed

+127
-18
lines changed

src/ebmc/bdd_engine.cpp

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class bdd_enginet
6565
const namespacet ns;
6666
netlistt netlist;
6767

68+
static bool property_supported(const exprt &);
69+
6870
// the Manager must appear before any BDDs
6971
// to do the cleanup in the right order
7072
mini_bdd_mgrt mgr;
@@ -196,10 +198,9 @@ property_checker_resultt bdd_enginet::operator()()
196198
<< ", nodes: " << netlist.number_of_nodes()
197199
<< messaget::eom;
198200

199-
const auto property_map = properties.make_property_map();
200-
201-
for(const auto &[_, expr] : property_map)
202-
get_atomic_propositions(expr);
201+
for(const auto &property : properties.properties)
202+
if(property_supported(property.normalized_expr))
203+
get_atomic_propositions(property.normalized_expr);
203204

204205
message.status() << "Building BDD for netlist" << messaget::eom;
205206

@@ -437,6 +438,54 @@ void bdd_enginet::compute_counterexample(
437438

438439
/*******************************************************************\
439440
441+
Function: bdd_enginet::property_supported
442+
443+
Inputs:
444+
445+
Outputs:
446+
447+
Purpose:
448+
449+
\*******************************************************************/
450+
451+
bool bdd_enginet::property_supported(const exprt &expr)
452+
{
453+
// Our engine knows all of CTL.
454+
if(is_CTL(expr))
455+
return true;
456+
457+
if(is_LTL(expr))
458+
{
459+
// We can map selected path properties to CTL.
460+
return is_Gp(expr) || is_GFp(expr);
461+
}
462+
463+
if(is_SVA(expr))
464+
{
465+
if(
466+
expr.id() == ID_sva_always &&
467+
!has_temporal_operator(to_sva_always_expr(expr).op()))
468+
{
469+
// always p
470+
return true;
471+
}
472+
473+
if(
474+
expr.id() == ID_sva_always &&
475+
to_sva_always_expr(expr).op().id() == ID_sva_s_eventually &&
476+
!has_temporal_operator(
477+
to_sva_s_eventually_expr(to_sva_always_expr(expr).op()).op()))
478+
{
479+
// always s_eventually p
480+
return true;
481+
}
482+
}
483+
484+
return false;
485+
}
486+
487+
/*******************************************************************\
488+
440489
Function: bdd_enginet::check_property
441490
442491
Inputs:
@@ -455,24 +504,26 @@ void bdd_enginet::check_property(propertyt &property)
455504
if(property.is_assumed())
456505
return;
457506

507+
if(!property_supported(property.normalized_expr))
508+
{
509+
property.failure("property not supported by BDD engine");
510+
return;
511+
}
512+
458513
message.status() << "Checking " << property.name << messaget::eom;
459514
property.status=propertyt::statust::UNKNOWN;
460515

461-
// special treatment for AGp
462-
auto is_AGp = [](const exprt &expr) {
463-
return (expr.id() == ID_AG || expr.id() == ID_G ||
464-
expr.id() == ID_sva_always) &&
465-
!has_temporal_operator(to_unary_expr(expr).op());
466-
};
467-
468516
// Our engine knows CTL only.
469517
// We map selected path properties to CTL.
470518

471-
if(
472-
property.normalized_expr.id() == ID_G &&
473-
to_G_expr(property.normalized_expr).op().id() == ID_F &&
474-
!has_temporal_operator(
475-
to_F_expr(to_G_expr(property.normalized_expr).op()).op()))
519+
if(is_Gp(property.normalized_expr))
520+
{
521+
// G p --> AG p
522+
auto p = to_G_expr(property.normalized_expr).op();
523+
property.normalized_expr = AG_exprt{p};
524+
}
525+
526+
if(is_GFp(property.normalized_expr))
476527
{
477528
// G F p --> AG AF p
478529
auto p = to_F_expr(to_G_expr(property.normalized_expr).op()).op();
@@ -494,6 +545,15 @@ void bdd_enginet::check_property(propertyt &property)
494545
property.normalized_expr = AG_exprt{AF_exprt{p}};
495546
}
496547

548+
if(
549+
property.normalized_expr.id() == ID_sva_always &&
550+
!has_temporal_operator(to_sva_always_expr(property.normalized_expr).op()))
551+
{
552+
// always p --> AG p
553+
auto p = to_sva_always_expr(property.normalized_expr).op();
554+
property.normalized_expr = AG_exprt{p};
555+
}
556+
497557
if(is_AGp(property.normalized_expr))
498558
{
499559
check_AGp(property);
@@ -503,7 +563,7 @@ void bdd_enginet::check_property(propertyt &property)
503563
check_CTL(property);
504564
}
505565
else
506-
property.failure("property not supported by BDD engine");
566+
DATA_INVARIANT(false, "unexpected normalized property");
507567
}
508568

509569
/*******************************************************************\

src/temporal-logic/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
SRC = nnf.cpp \
1+
SRC = ctl.cpp \
2+
ltl.cpp \
3+
nnf.cpp \
24
normalize_property.cpp \
35
temporal_logic.cpp \
46
trivial_sva.cpp \

src/temporal-logic/ctl.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*******************************************************************\
2+
3+
Module: CTL
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "ctl.h"
10+
11+
#include "temporal_logic.h"
12+
13+
bool is_AGp(const exprt &expr)
14+
{
15+
return expr.id() == ID_AG && !has_temporal_operator(to_AG_expr(expr).op());
16+
}

src/temporal-logic/ltl.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*******************************************************************\
2+
3+
Module: LTL
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "ltl.h"
10+
11+
#include "temporal_logic.h"
12+
13+
bool is_Gp(const exprt &expr)
14+
{
15+
return expr.id() == ID_G && !has_temporal_operator(to_G_expr(expr).op());
16+
}
17+
18+
bool is_GFp(const exprt &expr)
19+
{
20+
return expr.id() == ID_G && to_G_expr(expr).op().id() == ID_F &&
21+
!has_temporal_operator(to_F_expr(to_G_expr(expr).op()).op());
22+
}

src/temporal-logic/temporal_logic.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ bool is_exists_path(const exprt &);
2525
/// Returns true iff the given expression is a CTL formula
2626
bool is_CTL(const exprt &);
2727

28+
/// Returns true iff the given expression is AGp
29+
bool is_AGp(const exprt &);
30+
2831
/// Returns true iff the given expression has a CTL operator
2932
/// as its root
3033
bool is_CTL_operator(const exprt &);
@@ -42,6 +45,12 @@ bool has_RTCTL_operator(const exprt &);
4245
/// Returns true iff the given expression is an LTL formula
4346
bool is_LTL(const exprt &);
4447

48+
/// Returns true iff the given expression is Gp
49+
bool is_Gp(const exprt &);
50+
51+
/// Returns true iff the given expression is GFp
52+
bool is_GFp(const exprt &);
53+
4554
/// Returns true iff the given expression is an LTL past formula
4655
bool is_LTL_past(const exprt &);
4756

0 commit comments

Comments
 (0)