Skip to content

Commit 3125442

Browse files
committed
SVA-to-LTL: refactoring to use vector
This refactors the SVA-to-LTL sequence translation to return a vector instead of an expression. This makes it easier to implement the sequence repetition operators.
1 parent c6dfec8 commit 3125442

File tree

1 file changed

+83
-33
lines changed

1 file changed

+83
-33
lines changed

src/temporal-logic/sva_to_ltl.cpp

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,79 @@ static exprt n_Xes(mp_integer n, exprt op)
2525
// Returns a set of match conditions (given as LTL formula)
2626
struct ltl_sequence_matcht
2727
{
28-
ltl_sequence_matcht(exprt __cond, mp_integer __length)
29-
: cond(std::move(__cond)), length(std::move(__length))
28+
// the empty match
29+
ltl_sequence_matcht()
3030
{
31-
PRECONDITION(length >= 0);
3231
}
3332

34-
exprt cond; // LTL
35-
mp_integer length; // match_end - match_start + 1
33+
// a match of length 1
34+
explicit ltl_sequence_matcht(exprt __cond)
35+
{
36+
cond_vector.push_back(std::move(__cond));
37+
}
38+
39+
std::vector<exprt> cond_vector;
40+
41+
std::size_t length()
42+
{
43+
return cond_vector.size();
44+
}
45+
46+
bool empty_match() const
47+
{
48+
return cond_vector.empty();
49+
}
3650

37-
bool empty() const
51+
// c0 ∧ X c1 ∧ XX c2 ....
52+
exprt cond_expr() const
3853
{
39-
return length == 0;
54+
exprt::operandst conjuncts;
55+
conjuncts.reserve(cond_vector.size());
56+
for(std::size_t i = 0; i < cond_vector.size(); i++)
57+
{
58+
auto &c = cond_vector[i];
59+
if(!c.is_true())
60+
conjuncts.push_back(n_Xes(i, cond_vector[i]));
61+
}
62+
return conjunction(conjuncts);
63+
}
64+
65+
// generate true ##1 ... ##1 true with length n
66+
static ltl_sequence_matcht true_match(const mp_integer &n)
67+
{
68+
ltl_sequence_matcht result;
69+
for(mp_integer i; i < n; ++i)
70+
result.cond_vector.push_back(true_exprt{});
71+
return result;
4072
}
4173
};
4274

75+
// nonoverlapping concatenation
76+
ltl_sequence_matcht concat(ltl_sequence_matcht a, const ltl_sequence_matcht &b)
77+
{
78+
a.cond_vector.insert(
79+
a.cond_vector.end(), b.cond_vector.begin(), b.cond_vector.end());
80+
return a;
81+
}
82+
83+
// overlapping concatenation
84+
ltl_sequence_matcht
85+
overlapping_concat(ltl_sequence_matcht a, ltl_sequence_matcht b)
86+
{
87+
PRECONDITION(!a.empty_match());
88+
PRECONDITION(!b.empty_match());
89+
auto a_last = a.cond_vector.back();
90+
a.cond_vector.pop_back();
91+
b.cond_vector.front() = conjunction({a_last, b.cond_vector.front()});
92+
return concat(std::move(a), b);
93+
}
94+
4395
std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
4496
{
4597
if(sequence.id() == ID_sva_boolean)
4698
{
4799
// atomic proposition
48-
return {{to_sva_boolean_expr(sequence).op(), 1}};
100+
return {ltl_sequence_matcht{to_sva_boolean_expr(sequence).op()}};
49101
}
50102
else if(sequence.id() == ID_sva_sequence_concatenation)
51103
{
@@ -57,17 +109,16 @@ std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
57109
return {};
58110

59111
std::vector<ltl_sequence_matcht> result;
112+
60113
// cross product
61114
for(auto &match_lhs : matches_lhs)
62115
for(auto &match_rhs : matches_rhs)
63116
{
64-
// Concatenation is overlapping, hence deduct one from
65-
// the length.
66-
auto delay = match_lhs.length - 1;
67-
auto rhs_delayed = n_Xes(delay, match_rhs.cond);
68-
result.emplace_back(
69-
and_exprt{match_lhs.cond, rhs_delayed},
70-
match_lhs.length + match_rhs.length - 1);
117+
// Sequence concatenation is overlapping
118+
auto new_match = overlapping_concat(match_lhs, match_rhs);
119+
CHECK_RETURN(
120+
new_match.length() == match_lhs.length() + match_rhs.length() - 1);
121+
result.push_back(std::move(new_match));
71122
}
72123
return result;
73124
}
@@ -82,12 +133,12 @@ std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
82133

83134
if(delay.to().is_nil())
84135
{
136+
// delay as instructed
137+
auto delay_sequence = ltl_sequence_matcht::true_match(from_int);
138+
85139
for(auto &match : matches)
86-
{
87-
// delay as instructed
88-
match.length += from_int;
89-
match.cond = n_Xes(from_int, match.cond);
90-
}
140+
match = concat(delay_sequence, match);
141+
91142
return matches;
92143
}
93144
else if(delay.to().id() == ID_infinity)
@@ -101,13 +152,12 @@ std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
101152

102153
for(mp_integer i = from_int; i <= to_int; ++i)
103154
{
155+
// delay as instructed
156+
auto delay_sequence = ltl_sequence_matcht::true_match(i);
157+
104158
for(const auto &match : matches)
105159
{
106-
// delay as instructed
107-
auto new_match = match;
108-
new_match.length += from_int;
109-
new_match.cond = n_Xes(i, match.cond);
110-
new_matches.push_back(std::move(new_match));
160+
new_matches.push_back(concat(delay_sequence, match));
111161
}
112162
}
113163

@@ -239,15 +289,15 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
239289
for(auto &match : matches)
240290
{
241291
const auto overlapped = expr.id() == ID_sva_overlapped_implication;
242-
if(match.empty() && overlapped)
292+
if(match.empty_match() && overlapped)
243293
{
244294
// ignore the empty match
245295
}
246296
else
247297
{
248-
auto delay = match.length + (overlapped ? 0 : 1) - 1;
298+
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
249299
auto delayed_property = n_Xes(delay, property_rec.value());
250-
conjuncts.push_back(implies_exprt{match.cond, delayed_property});
300+
conjuncts.push_back(implies_exprt{match.cond_expr(), delayed_property});
251301
}
252302
}
253303

@@ -275,15 +325,15 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
275325
for(auto &match : matches)
276326
{
277327
const auto overlapped = expr.id() == ID_sva_overlapped_followed_by;
278-
if(match.empty() && overlapped)
328+
if(match.empty_match() && overlapped)
279329
{
280330
// ignore the empty match
281331
}
282332
else
283333
{
284-
auto delay = match.length + (overlapped ? 0 : 1) - 1;
334+
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
285335
auto delayed_property = n_Xes(delay, property_rec.value());
286-
disjuncts.push_back(and_exprt{match.cond, delayed_property});
336+
disjuncts.push_back(and_exprt{match.cond_expr(), delayed_property});
287337
}
288338
}
289339

@@ -310,8 +360,8 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
310360

311361
for(auto &match : matches)
312362
{
313-
if(!match.empty())
314-
disjuncts.push_back(match.cond);
363+
if(!match.empty_match())
364+
disjuncts.push_back(match.cond_expr());
315365
}
316366

317367
return disjunction(disjuncts);

0 commit comments

Comments
 (0)