Skip to content

Commit eab8af4

Browse files
authored
Merge pull request #1224 from diffblue/safety-only-Buechi
Buechi: identify special cases where reachability is sufficient
2 parents 5f9a562 + 28e4383 commit eab8af4

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-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/ebmc/instrument_buechi.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,31 @@ void instrument_buechi(
6868
// by the Buechi acceptance condition.
6969
exprt::operandst property_conjuncts;
7070

71+
bool have_liveness = false, have_safety = false;
72+
7173
if(!buechi.liveness_signal.is_false())
7274
{
7375
// Note that we have negated the property,
7476
// so this is the negation of the Buechi acceptance condition.
7577
property_conjuncts.push_back(
7678
F_exprt{G_exprt{not_exprt{buechi.liveness_signal}}});
79+
have_liveness = true;
7780
}
7881

7982
if(!buechi.error_signal.is_true())
8083
{
8184
property_conjuncts.push_back(G_exprt{not_exprt{buechi.error_signal}});
85+
have_safety = true;
8286
}
8387

88+
if(have_liveness && have_safety)
89+
message.debug() << "Buechi automaton has liveness and safety components"
90+
<< messaget::eom;
91+
else if(have_liveness)
92+
message.debug() << "Buechi automaton is liveness only" << messaget::eom;
93+
else if(have_safety)
94+
message.debug() << "Buechi automaton is safety only" << messaget::eom;
95+
8496
property.normalized_expr = conjunction(property_conjuncts);
8597

8698
message.debug() << "New property: " << format(property.normalized_expr)

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)