Skip to content

Commit 6cf03c9

Browse files
authored
Merge pull request #450 from diffblue/bmc-Fphi
BMC for F φ
2 parents 9d9dccf + 8147a2a commit 6cf03c9

File tree

9 files changed

+74
-4
lines changed

9 files changed

+74
-4
lines changed

regression/ebmc/smv/bmc_unsupported_property1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ bmc_unsupported_property1.smv
33

44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[main::spec1\] !G main::var::x = FALSE: FAILURE: property not supported by BMC engine$
6+
^\[main::spec1\] EG main::var::x = FALSE: FAILURE: property not supported by BMC engine$
77
^\[main::spec2\] G main::var::x = FALSE: REFUTED$
88
--
99
^warning: ignoring

regression/ebmc/smv/bmc_unsupported_property1.smv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ VAR x : boolean;
44

55
ASSIGN init(x) := 1;
66

7-
LTLSPEC !G x=0
7+
SPEC EG x=0
88
LTLSPEC G x=0

regression/ebmc/smv/bmc_unsupported_property2.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ bmc_unsupported_property2.smv
33

44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[main::spec1\] !G main::var::x = FALSE: FAILURE: property not supported by BMC engine$
6+
^\[main::spec1\] EG main::var::x = FALSE: FAILURE: property not supported by BMC engine$
77
^\[main::spec2\] G main::var::x = TRUE: PROVED up to bound 1$
88
--
99
^warning: ignoring

regression/ebmc/smv/bmc_unsupported_property2.smv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ VAR x : boolean;
55
ASSIGN init(x) := 1;
66
ASSIGN next(x) := x;
77

8-
LTLSPEC !G x=0 -- unsupported
8+
SPEC EG x=0 -- unsupported
99
LTLSPEC G x=1 -- should pass

regression/ebmc/smv/smv_ltlspec4.desc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE broken-smt-backend
2+
smv_ltlspec4.smv
3+
--bound 10 --numbered-trace
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main::spec1\] F main::var::x = 0: REFUTED$
7+
^main::var::x@0 = 1$
8+
^main::var::x@1 = 2$
9+
^main::var::x@2 = 2$
10+
^\[main::spec2\] F main::var::x = 2: PROVED up to bound 10$
11+
--
12+
^warning: ignoring
13+
--

regression/ebmc/smv/smv_ltlspec4.smv

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
MODULE main
2+
3+
VAR x : 0..2;
4+
5+
ASSIGN
6+
init(x) := 1;
7+
next(x) := 2;
8+
9+
LTLSPEC F x=0 -- fails
10+
LTLSPEC F x=2 -- holds

src/temporal-logic/normalize_property.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ exprt normalize_pre_not(not_exprt expr)
3636
{
3737
return to_not_expr(op).op();
3838
}
39+
else if(op.id() == ID_G)
40+
{
41+
// ¬Gφ --> F¬φ
42+
return F_exprt{not_exprt{to_G_expr(op).op()}};
43+
}
44+
else if(op.id() == ID_F)
45+
{
46+
// ¬Fφ --> G¬φ
47+
return G_exprt{not_exprt{to_F_expr(op).op()}};
48+
}
3949

4050
return std::move(expr);
4151
}

src/temporal-logic/normalize_property.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Author: Daniel Kroening, [email protected]
1616
/// ¬(a ∨ b) --> ¬a ∧ ¬b
1717
/// ¬(a ∧ b) --> ¬a ∨ ¬b
1818
/// ¬¬φ --> φ
19+
/// ¬Gφ --> F¬φ
20+
/// ¬Fφ --> G¬φ
1921
exprt normalize_property(exprt);
2022

2123
#endif

src/trans-word-level/property.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ bool bmc_supports_property(const exprt &expr)
5454
return true;
5555
else if(expr.id() == ID_G)
5656
return true;
57+
else if(expr.id() == ID_AF)
58+
return true;
59+
else if(expr.id() == ID_F)
60+
return true;
5761
else if(expr.id() == ID_X)
5862
return bmc_supports_property(to_X_expr(expr).op());
5963
else if(expr.id() == ID_sva_always)
@@ -117,6 +121,37 @@ static void property_obligations_rec(
117121
property_obligations_rec(phi, solver, c, no_timeframes, ns, obligations);
118122
}
119123
}
124+
else if(
125+
property_expr.id() == ID_AF || property_expr.id() == ID_F ||
126+
property_expr.id() == ID_sva_s_eventually)
127+
{
128+
const auto &phi = to_unary_expr(property_expr).op();
129+
130+
// Counterexamples to Fφ must have a loop.
131+
// We consider l-k loops with l<k.
132+
for(mp_integer k = current + 1; k < no_timeframes; ++k)
133+
{
134+
// The following needs to be satisfied for a counterexample
135+
// to Fφ that loops back in timeframe k:
136+
//
137+
// (1) There is a loop from timeframe k back to
138+
// some earlier state l with current<=l<k.
139+
// (2) No state j with current<=j<=k to the end of the
140+
// lasso satisfies 'φ'.
141+
for(mp_integer l = current; l < k; ++l)
142+
{
143+
exprt::operandst disjuncts = {not_exprt(lasso_symbol(l, k))};
144+
145+
for(mp_integer j = current; j <= k; ++j)
146+
{
147+
exprt tmp = instantiate(phi, j, no_timeframes, ns);
148+
disjuncts.push_back(std::move(tmp));
149+
}
150+
151+
obligations[k].push_back(disjunction(disjuncts));
152+
}
153+
}
154+
}
120155
else if(
121156
property_expr.id() == ID_sva_ranged_always ||
122157
property_expr.id() == ID_sva_s_always)

0 commit comments

Comments
 (0)