1717#include < chrono>
1818#include < fstream>
1919
20+ void bmc_with_assumptions (
21+ std::size_t bound,
22+ const transition_systemt &transition_system,
23+ ebmc_propertiest &properties,
24+ decision_proceduret &solver,
25+ message_handlert &message_handler)
26+ {
27+ messaget message (message_handler);
28+ const namespacet ns (transition_system.symbol_table );
29+
30+ // Use assumptions to check the properties separately
31+
32+ for (auto &property : properties.properties )
33+ {
34+ if (property.is_disabled () || property.is_failure () || property.is_assumed ())
35+ {
36+ continue ;
37+ }
38+
39+ message.status () << " Checking " << property.name << messaget::eom;
40+
41+ auto assumption = not_exprt{conjunction (property.timeframe_handles )};
42+
43+ decision_proceduret::resultt dec_result = solver (assumption);
44+
45+ switch (dec_result)
46+ {
47+ case decision_proceduret::resultt::D_SATISFIABLE:
48+ if (property.is_exists_path ())
49+ {
50+ property.proved ();
51+ message.result () << " SAT: path found" << messaget::eom;
52+ }
53+ else // universal path property
54+ {
55+ property.refuted ();
56+ message.result () << " SAT: counterexample found" << messaget::eom;
57+ }
58+
59+ property.witness_trace = compute_trans_trace (
60+ property.timeframe_handles ,
61+ solver,
62+ bound + 1 ,
63+ ns,
64+ transition_system.main_symbol ->name );
65+ break ;
66+
67+ case decision_proceduret::resultt::D_UNSATISFIABLE:
68+ if (property.is_exists_path ())
69+ {
70+ message.result () << " UNSAT: No path found within bound"
71+ << messaget::eom;
72+ property.refuted_with_bound (bound);
73+ }
74+ else // universal path property
75+ {
76+ message.result () << " UNSAT: No counterexample found within bound"
77+ << messaget::eom;
78+ property.proved_with_bound (bound);
79+ }
80+ break ;
81+
82+ case decision_proceduret::resultt::D_ERROR:
83+ message.error () << " Error from decision procedure" << messaget::eom;
84+ property.failure ();
85+ break ;
86+
87+ default :
88+ property.failure ();
89+ throw ebmc_errort () << " Unexpected result from decision procedure" ;
90+ }
91+ }
92+ }
93+
94+ void bmc_without_assumptions (
95+ std::size_t bound,
96+ const transition_systemt &transition_system,
97+ ebmc_propertiest &properties,
98+ decision_proceduret &solver,
99+ message_handlert &message_handler)
100+ {
101+ messaget message (message_handler);
102+ const namespacet ns (transition_system.symbol_table );
103+
104+ auto trace_found = [&solver](const ebmc_propertiest::propertyt &property)
105+ {
106+ for (auto &h : property.timeframe_handles )
107+ if (solver.get (h).is_false ())
108+ return true ;
109+ return false ;
110+ };
111+
112+ while (true )
113+ {
114+ // At least one of the remaining properties
115+ // should be falsified.
116+ exprt::operandst disjuncts;
117+
118+ for (auto &property : properties.properties )
119+ {
120+ if (property.is_unknown ())
121+ {
122+ for (auto &h : property.timeframe_handles )
123+ disjuncts.push_back (not_exprt{h});
124+ }
125+ }
126+
127+ solver.set_to_true (disjunction (disjuncts));
128+
129+ decision_proceduret::resultt dec_result = solver ();
130+
131+ switch (dec_result)
132+ {
133+ case decision_proceduret::resultt::D_SATISFIABLE:
134+ // Found a trace for at least one further property with unknown state
135+ message.result () << " SAT: path found" << messaget::eom;
136+
137+ for (auto &property : properties.properties )
138+ {
139+ if (property.is_unknown () && trace_found (property))
140+ {
141+ if (property.is_exists_path ())
142+ property.proved ();
143+ else // universal path property
144+ property.refuted ();
145+
146+ property.witness_trace = compute_trans_trace (
147+ property.timeframe_handles ,
148+ solver,
149+ bound + 1 ,
150+ ns,
151+ transition_system.main_symbol ->name );
152+ }
153+ }
154+ break ; // next iteration of while loop
155+
156+ case decision_proceduret::resultt::D_UNSATISFIABLE:
157+ message.result () << " UNSAT: No path found within bound" << messaget::eom;
158+
159+ for (auto &property : properties.properties )
160+ {
161+ if (property.is_unknown ())
162+ {
163+ if (property.is_exists_path ())
164+ property.refuted_with_bound (bound);
165+ else // universal path property
166+ property.proved_with_bound (bound);
167+ }
168+ }
169+ return ;
170+
171+ case decision_proceduret::resultt::D_ERROR:
172+ for (auto &property : properties.properties )
173+ {
174+ if (property.is_unknown ())
175+ property.failure ();
176+ }
177+ message.error () << " Error from decision procedure" << messaget::eom;
178+ return ;
179+
180+ default :
181+ for (auto &property : properties.properties )
182+ {
183+ if (property.is_unknown ())
184+ property.failure ();
185+ }
186+ throw ebmc_errort () << " Unexpected result from decision procedure" ;
187+ }
188+ }
189+ }
190+
20191void bmc (
21192 std::size_t bound,
22193 bool convert_only,
194+ bool bmc_with_assumptions,
23195 const transition_systemt &transition_system,
24196 ebmc_propertiest &properties,
25197 const ebmc_solver_factoryt &solver_factory,
@@ -78,8 +250,14 @@ void bmc(
78250 {
79251 for (const auto &property : properties.properties )
80252 {
81- if (!property.is_disabled ())
253+ if (property.is_assumed ())
254+ {
255+ solver.set_to_true (conjunction (property.timeframe_handles ));
256+ }
257+ else if (!property.is_disabled ())
258+ {
82259 solver.set_to_false (conjunction (property.timeframe_handles ));
260+ }
83261 }
84262
85263 // Call decision_proceduret::dec_solve to finish the conversion
@@ -93,69 +271,15 @@ void bmc(
93271
94272 auto sat_start_time = std::chrono::steady_clock::now ();
95273
96- // Use assumptions to check the properties separately
97-
98- for (auto &property : properties.properties )
274+ if (bmc_with_assumptions)
99275 {
100- if (
101- property.is_disabled () || property.is_failure () ||
102- property.is_assumed ())
103- {
104- continue ;
105- }
106-
107- message.status () << " Checking " << property.name << messaget::eom;
108-
109- auto assumption = not_exprt{conjunction (property.timeframe_handles )};
110-
111- decision_proceduret::resultt dec_result = solver (assumption);
112-
113- switch (dec_result)
114- {
115- case decision_proceduret::resultt::D_SATISFIABLE:
116- if (property.is_exists_path ())
117- {
118- property.proved ();
119- message.result () << " SAT: path found" << messaget::eom;
120- }
121- else // universal path property
122- {
123- property.refuted ();
124- message.result () << " SAT: counterexample found" << messaget::eom;
125- }
126-
127- property.witness_trace = compute_trans_trace (
128- property.timeframe_handles ,
129- solver,
130- bound + 1 ,
131- ns,
132- transition_system.main_symbol ->name );
133- break ;
134-
135- case decision_proceduret::resultt::D_UNSATISFIABLE:
136- if (property.is_exists_path ())
137- {
138- message.result () << " UNSAT: No path found within bound"
139- << messaget::eom;
140- property.refuted_with_bound (bound);
141- }
142- else // universal path property
143- {
144- message.result () << " UNSAT: No counterexample found within bound"
145- << messaget::eom;
146- property.proved_with_bound (bound);
147- }
148- break ;
149-
150- case decision_proceduret::resultt::D_ERROR:
151- message.error () << " Error from decision procedure" << messaget::eom;
152- property.failure ();
153- break ;
154-
155- default :
156- property.failure ();
157- throw ebmc_errort () << " Unexpected result from decision procedure" ;
158- }
276+ ::bmc_with_assumptions (
277+ bound, transition_system, properties, solver, message_handler);
278+ }
279+ else
280+ {
281+ ::bmc_without_assumptions (
282+ bound, transition_system, properties, solver, message_handler);
159283 }
160284
161285 auto sat_stop_time = std::chrono::steady_clock::now ();
0 commit comments