-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuchi_automaton.hpp
199 lines (165 loc) · 4.19 KB
/
buchi_automaton.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#ifndef BUCHI_AUTOMATON_HPP
#define BUCHI_AUTOMATON_HPP
#include <vector>
#include <boost/functional/hash.hpp>
#include <boost/tuple/tuple_comparison.hpp>
template <typename Proposition>
struct buchi_automaton
{
typedef Proposition proposition_type;
struct state
{
std::vector<std::pair<proposition_type, std::size_t> > next;
bool final;
};
bool final(std::size_t state) const
{
return m_states[state].final;
}
std::vector<state> m_states;
};
template <typename Proposition, typename PKS>
class ba_sync_product
{
public:
typedef typename PKS::value_type value_type;
ba_sync_product(buchi_automaton<Proposition> const & ba, PKS const & pks)
: m_ba(ba), m_pks(pks)
{
}
struct vertex_descriptor
{
typename PKS::vertex_descriptor vertex;
std::size_t state;
bool fair_left;
bool fair_right;
bool empty() const
{
return vertex.empty();
}
friend std::ostream & operator<<(std::ostream & out, vertex_descriptor const & rhs)
{
return out << "(" << rhs.vertex << ", " << rhs.state << ", " << "0LRB"[rhs.fair_right * 2 + rhs.fair_left] << ")";
}
friend bool operator==(vertex_descriptor const & lhs, vertex_descriptor const & rhs)
{
return lhs.state == rhs.state && lhs.vertex == rhs.vertex && lhs.fair_left == rhs.fair_left && lhs.fair_right == rhs.fair_right;
}
bool operator<(vertex_descriptor const & rhs) const
{
return boost::tie(state, vertex, fair_left, fair_right) < boost::tie(rhs.state, rhs.vertex, rhs.fair_left, rhs.fair_right);
}
friend std::size_t hash_value(vertex_descriptor const & v)
{
std::size_t res = hash_value(v.vertex);
boost::hash_combine(res, v.state);
boost::hash_combine(res, v.fair_left);
boost::hash_combine(res, v.fair_right);
return res;
}
};
bool final(vertex_descriptor const & v) const
{
return v.fair_left && v.fair_right;
}
class init_enumerator
{
public:
explicit init_enumerator(ba_sync_product const & g)
: m_g(g), m_pks_init(m_g.m_pks)
{
}
bool valid() const
{
return m_pks_init.valid();
}
void next()
{
m_pks_init.next();
}
vertex_descriptor get() const
{
typename PKS::vertex_descriptor const & pksv = m_pks_init.get();
vertex_descriptor v = { pksv, 0, m_g.m_pks.final(pksv), m_g.m_ba.final(0) };
return v;
}
private:
ba_sync_product const & m_g;
typename PKS::init_enumerator m_pks_init;
};
class out_edge_enumerator
{
public:
out_edge_enumerator(ba_sync_product const & g, vertex_descriptor const & source)
: m_g(g), m_out_edges(g.m_pks, source.vertex), m_source(source)
{
this->reset();
}
vertex_descriptor const & source() const
{
return m_source;
}
vertex_descriptor target() const
{
vertex_descriptor res = { m_out_edges.target(), m_g.m_ba.m_states[m_source.state].next[m_state_index].second, m_source.fair_left, m_source.fair_right };
if (res.fair_left && res.fair_right)
res.fair_left = res.fair_right = false;
if (!res.fair_left)
res.fair_left = m_g.m_pks.final(res.vertex);
if (!res.fair_right)
res.fair_right = m_g.m_ba.final(res.state);
return res;
}
template <typename Paramset>
void paramset_intersect(Paramset & p) const
{
m_out_edges.paramset_intersect(p);
}
bool valid() const
{
return m_state_index != m_g.m_ba.m_states[m_source.state].next.size();
}
void next()
{
BOOST_ASSERT(m_out_edges.valid());
m_out_edges.next();
if (!m_out_edges.valid())
{
++m_state_index;
this->find_next();
m_out_edges.reset();
}
}
void reset()
{
m_out_edges.reset();
m_state_index = 0;
this->find_next();
}
private:
void find_next()
{
while (m_state_index != m_g.m_ba.m_states[m_source.state].next.size()
&& !m_g.m_pks.valid(m_g.m_ba.m_states[m_source.state].next[m_state_index].first, m_source.vertex))
{
++m_state_index;
}
}
ba_sync_product const & m_g;
typename PKS::out_edge_enumerator m_out_edges;
vertex_descriptor m_source;
std::size_t m_state_index;
};
template <typename Paramset>
void self_loop(vertex_descriptor const & v, Paramset & p) const
{
if (!m_ba.final(v.state))
p.clear();
else
m_pks.self_loop(v.vertex, p);
}
private:
buchi_automaton<Proposition> const & m_ba;
PKS const & m_pks;
};
#endif