Skip to content

Commit 8250fc5

Browse files
committed
Buechi: identify special cases where reachability is sufficient
This adds treatment for the special case where all nonaccepting states of the Buechi automaton have an unconditional self-loop. In this case, when these nonaccepting states is reached, the trace cannot be extended to an accepting trace, and will hence be rejected. Hence, in this case, the Buechi acceptance condition is unnecessary, and a simple reachability property is sufficient. Among the 74 tests in regression/ebmc-spot/sva-buechi, only 3 require the Büchi acceptance condition with this change applied.
1 parent 5f9a562 commit 8250fc5

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

regression/ebmc-spot/sva-buechi/initial2.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
../../verilog/SVA/initial2.sv
33
--buechi --module main
4-
^\[main\.assert\.1\] main\.counter == 1: PROVED up to bound \d+$
5-
^\[main\.assert\.2\] main\.counter == 2: PROVED up to bound \d+$
4+
^\[main\.assert\.1\] main\.counter == 1: PROVED \(1-induction\)$
5+
^\[main\.assert\.2\] main\.counter == 2: PROVED \(1-induction\)$
66
^EXIT=0$
77
^SIGNAL=0$
88
--

regression/ebmc-spot/sva-buechi/static_final1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
../../verilog/SVA/static_final1.sv
33
--buechi
4-
^\[full_adder\.p0\] always \{ full_adder\.carry, full_adder\.sum \} == \{ 1'b0, full_adder\.a \} \+ full_adder\.b \+ full_adder\.c: PROVED up to bound \d+$
4+
^\[full_adder\.p0\] always \{ full_adder\.carry, full_adder\.sum \} == \{ 1'b0, full_adder\.a \} \+ full_adder\.b \+ full_adder\.c: PROVED \(1-induction\)$
55
^EXIT=0$
66
^SIGNAL=0$
77
--

src/temporal-logic/ltl_to_buechi.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ bool is_error_state(const std::pair<hoat::state_namet, hoat::edgest> &state)
100100
return false;
101101
}
102102

103+
/// Returns true iff all accepting states of the automaton have
104+
/// unconditional self loops
105+
bool is_safety_only(const hoat &hoa)
106+
{
107+
for(auto &state : hoa.body)
108+
if(state.first.is_accepting() && !is_error_state(state))
109+
return false;
110+
111+
return true;
112+
}
113+
103114
buechi_transt
104115
ltl_to_buechi(const exprt &property, message_handlert &message_handler)
105116
{
@@ -162,20 +173,32 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
162173
message.debug() << "Buechi initial state: " << format(init)
163174
<< messaget::eom;
164175

165-
// construct the liveness signal
166-
std::vector<exprt> liveness_disjuncts;
176+
exprt liveness_signal;
167177

168-
for(auto &state : hoa.body)
169-
if(state.first.is_accepting())
170-
{
171-
liveness_disjuncts.push_back(equal_exprt{
172-
buechi_state, from_integer(state.first.number, state_type)});
173-
}
178+
// Is safety sufficient?
179+
if(is_safety_only(hoa))
180+
{
181+
liveness_signal = false_exprt{};
174182

175-
auto liveness_signal = disjunction(liveness_disjuncts);
183+
message.debug() << "Buechi liveness signal not required" << messaget::eom;
184+
}
185+
else
186+
{
187+
// construct the liveness signal
188+
std::vector<exprt> liveness_disjuncts;
176189

177-
message.debug() << "Buechi liveness signal: " << format(liveness_signal)
178-
<< messaget::eom;
190+
for(auto &state : hoa.body)
191+
if(state.first.is_accepting())
192+
{
193+
liveness_disjuncts.push_back(equal_exprt{
194+
buechi_state, from_integer(state.first.number, state_type)});
195+
}
196+
197+
liveness_signal = disjunction(liveness_disjuncts);
198+
199+
message.debug() << "Buechi liveness signal: " << format(liveness_signal)
200+
<< messaget::eom;
201+
}
179202

180203
// construct the error signal -- true when the next automaton state
181204
// is nonaccepting with an unconditional self-loop.

0 commit comments

Comments
 (0)