@@ -9,6 +9,7 @@ Author: Daniel Kroening, dkr@amazon.com
9
9
#include " ltl_to_buechi.h"
10
10
11
11
#include < util/arith_tools.h>
12
+ #include < util/expr_util.h>
12
13
#include < util/format_expr.h>
13
14
#include < util/message.h>
14
15
#include < util/replace_expr.h>
@@ -37,6 +38,7 @@ void buechi_transt::rename_state_symbol(const symbol_exprt &new_state_symbol)
37
38
38
39
replace_expr (replace_map, init);
39
40
replace_expr (replace_map, trans);
41
+ replace_expr (replace_map, error_signal);
40
42
replace_expr (replace_map, liveness_signal);
41
43
42
44
state_symbol = new_state_symbol;
@@ -81,6 +83,23 @@ exprt hoa_label_to_expr(
81
83
}
82
84
}
83
85
86
+ // an accepting state with an unconditional self-loop
87
+ bool is_error_state (const std::pair<hoat::state_namet, hoat::edgest> &state)
88
+ {
89
+ if (!state.first .is_accepting ())
90
+ return false ;
91
+
92
+ for (auto &edge : state.second )
93
+ {
94
+ if (edge.label .id () == " t" )
95
+ for (auto &dest : edge.dest_states )
96
+ if (dest == state.first .number )
97
+ return true ;
98
+ }
99
+
100
+ return false ;
101
+ }
102
+
84
103
buechi_transt
85
104
ltl_to_buechi (const exprt &property, message_handlert &message_handler)
86
105
{
@@ -100,8 +119,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
100
119
101
120
// State-based Buchi acceptance. Should compare with transition-based
102
121
// acceptance.
103
- // Use --complete to be able to have multiple properties in one
104
- // model.
122
+ // The generated automata may have deadend states.
105
123
auto run_result = run (
106
124
" ltl2tgba" ,
107
125
{" ltl2tgba" , " --sba" , " --complete" , " --hoaf=1.1" , string},
@@ -144,7 +162,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
144
162
std::vector<exprt> liveness_disjuncts;
145
163
146
164
for (auto &state : hoa.body )
147
- if (! state.first .acc_sig . empty ())
165
+ if (state.first .is_accepting ())
148
166
{
149
167
liveness_disjuncts.push_back (equal_exprt{
150
168
buechi_state, from_integer (state.first .number , state_type)});
@@ -155,6 +173,37 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
155
173
message.debug () << " Buechi liveness signal: " << format (liveness_signal)
156
174
<< messaget::eom;
157
175
176
+ // construct the error signal -- true when the next automaton state
177
+ // is nonaccepting with an unconditional self-loop.
178
+ std::vector<exprt> error_disjuncts;
179
+
180
+ std::map<mp_integer, std::pair<hoat::state_namet, hoat::edgest>> state_map;
181
+ for (auto &state : hoa.body )
182
+ state_map[state.first .number ] = state;
183
+
184
+ for (auto &state : hoa.body )
185
+ {
186
+ for (auto &edge : state.second )
187
+ {
188
+ if (edge.dest_states .size () != 1 )
189
+ throw ebmc_errort () << " edge must have one destination state" ;
190
+ auto dest_state_it = state_map.find (edge.dest_states .front ());
191
+ CHECK_RETURN (dest_state_it != state_map.end ());
192
+ if (is_error_state (dest_state_it->second ))
193
+ {
194
+ auto pre = equal_exprt{
195
+ buechi_state, from_integer (state.first .number , state_type)};
196
+ auto cond = hoa_label_to_expr (edge.label , ltl_sva_to_string);
197
+ error_disjuncts.push_back (and_exprt{pre, cond});
198
+ }
199
+ }
200
+ }
201
+
202
+ auto error_signal = disjunction (error_disjuncts);
203
+
204
+ message.debug () << " Buechi error signal: " << format (error_signal)
205
+ << messaget::eom;
206
+
158
207
// construct the transition relation
159
208
std::vector<exprt> trans_disjuncts;
160
209
@@ -183,6 +232,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
183
232
buechi_state,
184
233
std::move (init),
185
234
std::move (trans),
235
+ std::move (error_signal),
186
236
std::move (liveness_signal)};
187
237
}
188
238
catch (ltl_sva_to_string_unsupportedt error)
0 commit comments