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