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 ||
@@ -38,66 +44,103 @@ bool has_low_completeness_threshold(const exprt &expr)
38
44
{
39
45
auto &always_expr = to_sva_ranged_always_expr (expr);
40
46
if (has_temporal_operator (always_expr.op ()))
41
- return false ;
42
- else if (always_expr.to ().is_constant ())
47
+ return {};
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 = numeric_cast_v<mp_integer>(s_always_expr.to ());
69
+
70
+ if (to_int < 0 )
71
+ return {};
72
+
73
+ // increases the CT by to_int
74
+ auto ct_op = completeness_threshold (s_always_expr.op ());
75
+ if (ct_op.has_value ())
76
+ return *ct_op + to_int;
57
77
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
- }
78
+ return {};
63
79
}
64
80
else if (
65
81
expr.id () == ID_sva_strong || expr.id () == ID_sva_weak ||
66
82
expr.id () == ID_sva_implicit_strong || expr.id () == ID_sva_implicit_weak)
67
83
{
68
84
auto &sequence = to_sva_sequence_property_expr_base (expr).sequence ();
69
- return has_low_completeness_threshold (sequence);
85
+ return completeness_threshold (sequence);
70
86
}
71
87
else if (expr.id () == ID_sva_boolean)
72
88
{
73
- return true ;
89
+ return 0 ; // state predicate only
74
90
}
75
- else if (expr.id () == ID_sva_or || expr. id () == ID_sva_and )
91
+ else if (expr.id () == ID_sva_cycle_delay )
76
92
{
77
- for (auto &op : expr.operands ())
78
- if (!has_low_completeness_threshold (op))
79
- return false ;
80
- return true ;
93
+ auto &cycle_delay = to_sva_cycle_delay_expr (expr);
94
+ mp_integer ct_lhs = 0 ;
95
+
96
+ if (cycle_delay.lhs ().is_not_nil ())
97
+ {
98
+ auto ct_lhs_opt = completeness_threshold (cycle_delay.lhs ());
99
+ if (ct_lhs_opt.has_value ())
100
+ ct_lhs = ct_lhs_opt.value ();
101
+ else
102
+ return {};
103
+ }
104
+
105
+ if (cycle_delay.is_range ())
106
+ return {};
107
+ else // singleton
108
+ {
109
+ auto ct_rhs = completeness_threshold (cycle_delay.rhs ());
110
+ if (ct_rhs.has_value ())
111
+ return ct_lhs + numeric_cast_v<mp_integer>(cycle_delay.from ()) +
112
+ *ct_rhs;
113
+ else
114
+ return {};
115
+ }
81
116
}
82
117
else if (expr.id () == ID_sva_sequence_property)
83
118
{
84
119
PRECONDITION (false ); // should have been turned into implicit weak/strong
85
120
}
86
121
else
87
- return false ;
122
+ return {} ;
88
123
}
89
124
90
- bool has_low_completeness_threshold (const ebmc_propertiest::propertyt &property)
125
+ std::optional<mp_integer>
126
+ completeness_threshold (const ebmc_propertiest::propertyt &property)
91
127
{
92
- return has_low_completeness_threshold (property.normalized_expr );
128
+ return completeness_threshold (property.normalized_expr );
93
129
}
94
130
95
- bool have_low_completeness_threshold (const ebmc_propertiest &properties)
131
+ std::optional<mp_integer>
132
+ completeness_threshold (const ebmc_propertiest &properties)
96
133
{
134
+ std::optional<mp_integer> max_ct;
135
+
97
136
for (auto &property : properties.properties )
98
- if (has_low_completeness_threshold (property))
99
- return true ;
100
- return false ;
137
+ {
138
+ auto ct_opt = completeness_threshold (property);
139
+ if (ct_opt.has_value ())
140
+ max_ct = std::max (max_ct.value_or (0 ), *ct_opt);
141
+ }
142
+
143
+ return max_ct;
101
144
}
102
145
103
146
property_checker_resultt completeness_threshold (
@@ -107,14 +150,16 @@ property_checker_resultt completeness_threshold(
107
150
const ebmc_solver_factoryt &solver_factory,
108
151
message_handlert &message_handler)
109
152
{
110
- // Do we have an eligibile property?
111
- if (!have_low_completeness_threshold (properties))
153
+ // Do we have an eligible property?
154
+ auto ct_opt = completeness_threshold (properties);
155
+
156
+ if (!ct_opt.has_value ())
112
157
return property_checker_resultt{properties}; // give up
113
158
114
- // Do BMC with two timeframes
159
+ // Do BMC, using the CT as the bound
115
160
auto result = bmc (
116
- 1 , // bound
117
- false , // convert_only
161
+ numeric_cast_v<std:: size_t >(*ct_opt), // bound
162
+ false , // convert_only
118
163
cmdline.isset (" bmc-with-assumptions" ),
119
164
transition_system,
120
165
properties,
@@ -126,8 +171,9 @@ property_checker_resultt completeness_threshold(
126
171
if (property.is_proved_with_bound ())
127
172
{
128
173
// 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" );
174
+ auto property_ct_opt = completeness_threshold (property);
175
+ if (property_ct_opt.has_value ())
176
+ property.proved (" CT=" + integer2string (*property_ct_opt));
131
177
else
132
178
property.unknown ();
133
179
}
0 commit comments