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
+ // Increases the CT by one.
30
+ auto ct_p = completeness_threshold (to_X_expr (expr).op ());
31
+ if (ct_p.has_value ())
32
+ return *ct_p + 1 ;
33
+ else
34
+ return {};
29
35
}
30
36
else if (
31
37
expr.id () == ID_sva_nexttime || expr.id () == ID_sva_s_nexttime ||
@@ -37,69 +43,92 @@ bool has_low_completeness_threshold(const exprt &expr)
37
43
else if (expr.id () == ID_sva_ranged_always)
38
44
{
39
45
auto &always_expr = to_sva_ranged_always_expr (expr);
40
- if (has_temporal_operator (always_expr.op ()))
41
- return false ;
42
- else if (always_expr.upper ().is_constant ())
46
+ 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
+
51
+ if (upper_int < 0 )
52
+ return {};
53
+
54
+ // increases the CT by upper_int
55
+ auto ct_op = completeness_threshold (always_expr.op ());
56
+ if (ct_op.has_value ())
57
+ return *ct_op + upper_int;
58
+ else
59
+ return {};
49
60
}
50
61
else
51
- return false ;
62
+ return {} ;
52
63
}
53
64
else if (expr.id () == ID_sva_s_always)
54
65
{
55
66
auto &s_always_expr = to_sva_s_always_expr (expr);
56
- if (has_temporal_operator (s_always_expr.op ()))
57
- return false ;
67
+
68
+ auto upper_int =
69
+ numeric_cast_v<mp_integer>(to_constant_expr (s_always_expr.upper ()));
70
+
71
+ if (upper_int < 0 )
72
+ return {};
73
+
74
+ // increases the CT by upper_int
75
+ auto ct_op = completeness_threshold (s_always_expr.op ());
76
+ if (ct_op.has_value ())
77
+ return *ct_op + upper_int;
58
78
else
59
- {
60
- auto lower_int = numeric_cast_v<mp_integer>(s_always_expr.lower ());
61
- 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 ;
64
- }
79
+ return {};
65
80
}
66
81
else if (
67
82
expr.id () == ID_sva_strong || expr.id () == ID_sva_weak ||
68
83
expr.id () == ID_sva_implicit_strong || expr.id () == ID_sva_implicit_weak)
69
84
{
70
85
auto &sequence = to_sva_sequence_property_expr_base (expr).sequence ();
71
- return has_low_completeness_threshold (sequence);
86
+ return completeness_threshold (sequence);
72
87
}
73
88
else if (expr.id () == ID_sva_boolean)
74
89
{
75
- return true ;
90
+ return 0 ; // state predicate only
76
91
}
77
92
else if (expr.id () == ID_sva_or || expr.id () == ID_sva_and)
78
93
{
94
+ mp_integer max_ct = 0 ;
95
+
79
96
for (auto &op : expr.operands ())
80
- if (!has_low_completeness_threshold (op))
81
- return false ;
82
- return true ;
97
+ {
98
+ auto ct_op = completeness_threshold (op);
99
+ if (ct_op.has_value ())
100
+ max_ct = std::max (*ct_op, max_ct);
101
+ else
102
+ return {}; // no CT
103
+ }
104
+
105
+ return max_ct;
83
106
}
84
107
else if (expr.id () == ID_sva_sequence_property)
85
108
{
86
109
PRECONDITION (false ); // should have been turned into implicit weak/strong
87
110
}
88
111
else
89
- return false ;
112
+ return {} ;
90
113
}
91
114
92
- bool has_low_completeness_threshold (const ebmc_propertiest::propertyt &property)
115
+ std::optional<mp_integer> completeness_threshold (const ebmc_propertiest::propertyt &property)
93
116
{
94
- return has_low_completeness_threshold (property.normalized_expr );
117
+ return completeness_threshold (property.normalized_expr );
95
118
}
96
119
97
- bool have_low_completeness_threshold (const ebmc_propertiest &properties)
120
+ std::optional<mp_integer> completeness_threshold (const ebmc_propertiest &properties)
98
121
{
122
+ std::optional<mp_integer> max_ct;
123
+
99
124
for (auto &property : properties.properties )
100
- if (has_low_completeness_threshold (property))
101
- return true ;
102
- return false ;
125
+ {
126
+ auto ct_opt = completeness_threshold (property);
127
+ if (ct_opt.has_value ())
128
+ max_ct = std::max (max_ct.value_or (0 ), *ct_opt);
129
+ }
130
+
131
+ return max_ct;
103
132
}
104
133
105
134
property_checker_resultt completeness_threshold (
@@ -110,13 +139,15 @@ property_checker_resultt completeness_threshold(
110
139
message_handlert &message_handler)
111
140
{
112
141
// Do we have an eligibile property?
113
- if (!have_low_completeness_threshold (properties))
142
+ auto ct_opt = completeness_threshold (properties);
143
+
144
+ if (!ct_opt.has_value ())
114
145
return property_checker_resultt{properties}; // give up
115
146
116
147
// Do BMC with two timeframes
117
148
auto result = bmc (
118
- 1 , // bound
119
- false , // convert_only
149
+ numeric_cast_v<std:: size_t >(*ct_opt), // bound
150
+ false , // convert_only
120
151
cmdline.isset (" bmc-with-assumptions" ),
121
152
transition_system,
122
153
properties,
@@ -128,7 +159,7 @@ property_checker_resultt completeness_threshold(
128
159
if (property.is_proved_with_bound ())
129
160
{
130
161
// Turn "PROVED up to bound k" into "PROVED" if k>=CT
131
- if (has_low_completeness_threshold (property) && property. bound >= 1 )
162
+ if (completeness_threshold (property). has_value () )
132
163
property.proved ();
133
164
else
134
165
property.unknown ();
0 commit comments