@@ -16,16 +16,22 @@ Author: Daniel Kroening, dkr@amazon.com
1616
1717#include " bmc.h"
1818
19- bool has_low_completeness_threshold (const exprt &expr)
19+ // counting number of transitions
20+ std::optional<mp_integer> completeness_threshold (const exprt &expr)
2021{
2122 if (!has_temporal_operator (expr))
2223 {
23- return true ; // state predicate only
24+ return 0 ; // state predicate only
2425 }
2526 else if (expr.id () == ID_X)
2627 {
2728 // 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 {};
2935 }
3036 else if (
3137 expr.id () == ID_sva_nexttime || expr.id () == ID_sva_s_nexttime ||
@@ -37,69 +43,94 @@ bool has_low_completeness_threshold(const exprt &expr)
3743 else if (expr.id () == ID_sva_ranged_always)
3844 {
3945 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 ())
4347 {
44- auto lower_int = numeric_cast_v<mp_integer>(always_expr.lower ());
4548 auto upper_int =
4649 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 {};
4960 }
5061 else
51- return false ;
62+ return {} ;
5263 }
5364 else if (expr.id () == ID_sva_s_always)
5465 {
5566 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;
5878 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 {};
6580 }
6681 else if (
6782 expr.id () == ID_sva_strong || expr.id () == ID_sva_weak ||
6883 expr.id () == ID_sva_implicit_strong || expr.id () == ID_sva_implicit_weak)
6984 {
7085 auto &sequence = to_sva_sequence_property_expr_base (expr).sequence ();
71- return has_low_completeness_threshold (sequence);
86+ return completeness_threshold (sequence);
7287 }
7388 else if (expr.id () == ID_sva_boolean)
7489 {
75- return true ;
90+ return 0 ; // state predicate only
7691 }
7792 else if (expr.id () == ID_sva_or || expr.id () == ID_sva_and)
7893 {
94+ mp_integer max_ct = 0 ;
95+
7996 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;
83106 }
84107 else if (expr.id () == ID_sva_sequence_property)
85108 {
86109 PRECONDITION (false ); // should have been turned into implicit weak/strong
87110 }
88111 else
89- return false ;
112+ return {} ;
90113}
91114
92- bool has_low_completeness_threshold (const ebmc_propertiest::propertyt &property)
115+ std::optional<mp_integer>
116+ completeness_threshold (const ebmc_propertiest::propertyt &property)
93117{
94- return has_low_completeness_threshold (property.normalized_expr );
118+ return completeness_threshold (property.normalized_expr );
95119}
96120
97- bool have_low_completeness_threshold (const ebmc_propertiest &properties)
121+ std::optional<mp_integer>
122+ completeness_threshold (const ebmc_propertiest &properties)
98123{
124+ std::optional<mp_integer> max_ct;
125+
99126 for (auto &property : properties.properties )
100- if (has_low_completeness_threshold (property))
101- return true ;
102- 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;
103134}
104135
105136property_checker_resultt completeness_threshold (
@@ -110,13 +141,15 @@ property_checker_resultt completeness_threshold(
110141 message_handlert &message_handler)
111142{
112143 // Do we have an eligibile property?
113- if (!have_low_completeness_threshold (properties))
144+ auto ct_opt = completeness_threshold (properties);
145+
146+ if (!ct_opt.has_value ())
114147 return property_checker_resultt{properties}; // give up
115148
116149 // Do BMC with two timeframes
117150 auto result = bmc (
118- 1 , // bound
119- false , // convert_only
151+ numeric_cast_v<std:: size_t >(*ct_opt), // bound
152+ false , // convert_only
120153 cmdline.isset (" bmc-with-assumptions" ),
121154 transition_system,
122155 properties,
@@ -128,8 +161,9 @@ property_checker_resultt completeness_threshold(
128161 if (property.is_proved_with_bound ())
129162 {
130163 // Turn "PROVED up to bound k" into "PROVED" if k>=CT
131- if (has_low_completeness_threshold (property) && property.bound >= 1 )
132- 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));
133167 else
134168 property.unknown ();
135169 }
0 commit comments