16
16
17
17
#include " bmc.h"
18
18
19
- bool has_low_completeness_threshold (const exprt &expr)
19
+ // counting number of transitions
20
+ std::optional<mp_integer> completeness_threshold (const exprt &expr)
20
21
{
21
22
if (!has_temporal_operator (expr))
22
23
{
23
- return true ; // state predicate only
24
+ return 0 ; // state predicate only
24
25
}
25
26
else if (expr.id () == ID_X)
26
27
{
27
28
// X p
28
- return !has_temporal_operator (to_X_expr (expr).op ());
29
+ if (has_temporal_operator (to_X_expr (expr).op ()))
30
+ return {};
31
+ else
32
+ return 1 ;
29
33
}
30
34
else if (
31
35
expr.id () == ID_sva_nexttime || expr.id () == ID_sva_s_nexttime ||
@@ -41,11 +45,12 @@ bool has_low_completeness_threshold(const exprt &expr)
41
45
return false ;
42
46
else if (always_expr.upper ().is_constant ())
43
47
{
44
- auto lower_int = numeric_cast_v<mp_integer>(always_expr.lower ());
45
48
auto upper_int =
46
49
numeric_cast_v<mp_integer>(to_constant_expr (always_expr.upper ()));
47
- return lower_int >= 0 && lower_int <= 1 && upper_int >= 0 &&
48
- upper_int <= 1 ;
50
+ if (upper_int < 0 )
51
+ return {};
52
+ else
53
+ return upper_int;
49
54
}
50
55
else
51
56
return false ;
@@ -57,29 +62,38 @@ bool has_low_completeness_threshold(const exprt &expr)
57
62
return false ;
58
63
else
59
64
{
60
- auto lower_int = numeric_cast_v<mp_integer>(s_always_expr.lower ());
61
65
auto upper_int = numeric_cast_v<mp_integer>(s_always_expr.upper ());
62
- return lower_int >= 0 && lower_int <= 1 && upper_int >= 0 &&
63
- upper_int <= 1 ;
66
+ if (upper_int < 0 )
67
+ return {};
68
+ else
69
+ return upper_int;
64
70
}
65
71
}
66
72
else if (
67
73
expr.id () == ID_sva_strong || expr.id () == ID_sva_weak ||
68
74
expr.id () == ID_sva_implicit_strong || expr.id () == ID_sva_implicit_weak)
69
75
{
70
76
auto &sequence = to_sva_sequence_property_expr_base (expr).sequence ();
71
- return has_low_completeness_threshold (sequence);
77
+ return completeness_threshold (sequence);
72
78
}
73
79
else if (expr.id () == ID_sva_boolean)
74
80
{
75
- return true ;
81
+ return 0 ; // state predicate only
76
82
}
77
83
else if (expr.id () == ID_sva_or || expr.id () == ID_sva_and)
78
84
{
85
+ mp_integer max_ct = 0 ;
86
+
79
87
for (auto &op : expr.operands ())
80
- if (!has_low_completeness_threshold (op))
81
- return false ;
82
- return true ;
88
+ {
89
+ auto ct_op = completeness_threshold (op);
90
+ if (ct_op.has_value ())
91
+ max_ct = std::max (*ct_op, max_ct);
92
+ else
93
+ return {}; // no CT
94
+ }
95
+
96
+ return max_ct;
83
97
}
84
98
else if (expr.id () == ID_sva_sequence_property)
85
99
{
@@ -89,17 +103,23 @@ bool has_low_completeness_threshold(const exprt &expr)
89
103
return false ;
90
104
}
91
105
92
- bool has_low_completeness_threshold (const ebmc_propertiest::propertyt &property)
106
+ std::optional<mp_integer> completeness_threshold (const ebmc_propertiest::propertyt &property)
93
107
{
94
- return has_low_completeness_threshold (property.normalized_expr );
108
+ return completeness_threshold (property.normalized_expr );
95
109
}
96
110
97
- bool have_low_completeness_threshold (const ebmc_propertiest &properties)
111
+ std::optional<mp_integer> completeness_threshold (const ebmc_propertiest &properties)
98
112
{
113
+ std::optional<mp_integer> max_ct;
114
+
99
115
for (auto &property : properties.properties )
100
- if (has_low_completeness_threshold (property))
101
- return true ;
102
- return false ;
116
+ {
117
+ auto ct_opt = completeness_threshold (property);
118
+ if (ct_opt.has_value ())
119
+ max_ct = std::max (max_ct.value_or (0 ), *ct_opt);
120
+ }
121
+
122
+ return max_ct;
103
123
}
104
124
105
125
property_checker_resultt completeness_threshold (
@@ -110,13 +130,15 @@ property_checker_resultt completeness_threshold(
110
130
message_handlert &message_handler)
111
131
{
112
132
// Do we have an eligibile property?
113
- if (!have_low_completeness_threshold (properties))
133
+ auto ct_opt = completeness_threshold (properties);
134
+
135
+ if (!ct_opt.has_value ())
114
136
return property_checker_resultt{properties}; // give up
115
137
116
138
// Do BMC with two timeframes
117
139
auto result = bmc (
118
- 1 , // bound
119
- false , // convert_only
140
+ numeric_cast_v<std:: size_t >(*ct_opt), // bound
141
+ false , // convert_only
120
142
cmdline.isset (" bmc-with-assumptions" ),
121
143
transition_system,
122
144
properties,
@@ -128,7 +150,7 @@ property_checker_resultt completeness_threshold(
128
150
if (property.is_proved_with_bound ())
129
151
{
130
152
// Turn "PROVED up to bound k" into "PROVED" if k>=CT
131
- if (has_low_completeness_threshold (property) && property. bound >= 1 )
153
+ if (completeness_threshold (property). has_value () )
132
154
property.proved ();
133
155
else
134
156
property.unknown ();
0 commit comments