21#include <spot/misc/common.hh>
22#include <spot/misc/_config.h>
23#include <spot/misc/permute.hh>
32#ifdef SPOT_ENABLE_PTHREAD
43 template <
typename State_Data,
typename Edge_Data>
44 class SPOT_API digraph;
49 template <
typename Of,
typename ...Args>
50 struct first_is_base_of
52 static const bool value =
false;
55 template <
typename Of,
typename Arg1,
typename ...Args>
56 struct first_is_base_of<Of, Arg1, Args...>
58 static const bool value =
59 std::is_base_of<Of, typename std::decay<Arg1>::type>::value;
69 template <typename Data, bool boxed = !std::is_class<Data>::value>
70 struct SPOT_API boxed_label
76 template <
typename... Args,
77 typename =
typename std::enable_if<
78 !first_is_base_of<boxed_label, Args...>::value>::type>
79 boxed_label(Args&&... args)
80 noexcept(std::is_nothrow_constructible<Data, Args...>::value)
81 : label{std::forward<Args>(args)...}
88 explicit boxed_label()
89 noexcept(std::is_nothrow_constructible<Data>::value)
98 const Data& data()
const
103 bool operator<(
const boxed_label& other)
const
105 return label < other.label;
110 struct SPOT_API boxed_label<void, true>:
public std::tuple<>
112 typedef std::tuple<> data_t;
118 const std::tuple<>& data()
const
125 template <
typename Data>
126 struct SPOT_API boxed_label<Data, false>:
public Data
131 template <
typename... Args,
132 typename =
typename std::enable_if<
133 !first_is_base_of<boxed_label, Args...>::value>::type>
134 boxed_label(Args&&... args)
135 noexcept(std::is_nothrow_constructible<Data, Args...>::value)
136 : Data{std::forward<Args>(args)...}
143 explicit boxed_label()
144 noexcept(std::is_nothrow_constructible<Data>::value)
153 const Data& data()
const
166 template <
typename Edge,
typename State_Data>
167 struct SPOT_API distate_storage
final:
public State_Data
173 template <
typename... Args,
174 typename =
typename std::enable_if<
175 !first_is_base_of<distate_storage, Args...>::value>::type>
176 distate_storage(Args&&... args)
177 noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
178 : State_Data{std::forward<Args>(args)...}
190 template <
typename StateIn,
191 typename StateOut,
typename Edge,
typename Edge_Data>
192 struct SPOT_API edge_storage final:
public Edge_Data
201 explicit edge_storage()
202 noexcept(std::is_nothrow_constructible<Edge_Data>::value)
208 template <
typename... Args>
209 edge_storage(StateOut dst, Edge next_succ,
210 StateIn src, Args&&... args)
211 noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
212 && std::is_nothrow_constructible<StateOut, StateOut>::value
213 && std::is_nothrow_constructible<Edge, Edge>::value)
214 : Edge_Data{std::forward<Args>(args)...},
215 dst(dst), next_succ(next_succ), src(src)
220 bool operator<(
const edge_storage& other)
const
231 return this->data() < other.data();
234 bool operator==(
const edge_storage& other)
const
236 return src == other.src &&
238 this->data() == other.data();
250 template <
typename Graph>
251 class SPOT_API edge_iterator
254 typedef typename std::conditional<std::is_const<Graph>::value,
255 const typename Graph::edge_storage_t,
256 typename Graph::edge_storage_t>::type
258 typedef value_type& reference;
259 typedef value_type* pointer;
260 typedef std::ptrdiff_t difference_type;
261 typedef std::forward_iterator_tag iterator_category;
263 typedef typename Graph::edge edge;
265 edge_iterator() noexcept
270 edge_iterator(Graph* g, edge t) noexcept
275 bool operator==(edge_iterator o)
const
280 bool operator!=(edge_iterator o)
const
285 reference operator*()
const
287 return g_->edge_storage(t_);
290 pointer operator->()
const
292 return &g_->edge_storage(t_);
295 edge_iterator operator++()
297 t_ = operator*().next_succ;
301 edge_iterator operator++(
int)
303 edge_iterator ti = *
this;
304 t_ = operator*().next_succ;
308 operator bool()
const
323 template <
typename Graph>
324 class SPOT_API killer_edge_iterator:
public edge_iterator<Graph>
326 typedef edge_iterator<Graph> super;
328 typedef typename Graph::state_storage_t state_storage_t;
329 typedef typename Graph::edge edge;
331 killer_edge_iterator(Graph* g, edge t, state_storage_t& src) noexcept
332 : super(g, t), src_(src), prev_(0)
336 killer_edge_iterator operator++()
339 this->t_ = this->operator*().next_succ;
343 killer_edge_iterator operator++(
int)
345 killer_edge_iterator ti = *
this;
353 edge next = this->operator*().next_succ;
358 this->g_->edge_storage(prev_).next_succ = next;
362 if (src_.succ == this->t_)
365 if (src_.succ_tail == this->t_)
367 src_.succ_tail = prev_;
368 SPOT_ASSERT(next == 0);
372 this->operator*().next_succ = this->t_;
377 ++this->g_->killed_edge_;
381 state_storage_t& src_;
392 template <
typename Graph>
393 class SPOT_API state_out
396 typedef typename Graph::edge edge;
397 state_out(Graph* g, edge t) noexcept
402 edge_iterator<Graph> begin()
const
407 edge_iterator<Graph> end()
const
426 template <
typename Graph>
427 class SPOT_API all_edge_iterator
430 typedef typename std::conditional<std::is_const<Graph>::value,
431 const typename Graph::edge_storage_t,
432 typename Graph::edge_storage_t>::type
434 typedef value_type& reference;
435 typedef value_type* pointer;
436 typedef std::ptrdiff_t difference_type;
437 typedef std::forward_iterator_tag iterator_category;
440 typedef typename std::conditional<std::is_const<Graph>::value,
441 const typename Graph::edge_vector_t,
442 typename Graph::edge_vector_t>::type
450 unsigned s = tv_.size();
453 while (t_ < s && tv_[t_].next_succ == t_);
457 all_edge_iterator(
unsigned pos, tv_t& tv) noexcept
463 all_edge_iterator(tv_t& tv) noexcept
464 : t_(tv.size()), tv_(tv)
468 all_edge_iterator& operator++()
474 all_edge_iterator operator++(
int)
476 all_edge_iterator old = *
this;
481 bool operator==(all_edge_iterator o)
const
486 bool operator!=(all_edge_iterator o)
const
491 reference operator*()
const
496 pointer operator->()
const
503 template <
typename Graph>
504 class SPOT_API all_trans
507 typedef typename std::conditional<std::is_const<Graph>::value,
508 const typename Graph::edge_vector_t,
509 typename Graph::edge_vector_t>::type
511 typedef all_edge_iterator<Graph> iter_t;
516 all_trans(tv_t& tv) noexcept
532 class SPOT_API const_universal_dests
535 const unsigned* begin_;
536 const unsigned* end_;
539 const_universal_dests(
const unsigned* begin,
const unsigned* end) noexcept
540 : begin_(begin), end_(end)
544 const_universal_dests(
unsigned state) noexcept
545 : begin_(&tmp_), end_(&tmp_ + 1), tmp_(state)
549 const unsigned* begin()
const
554 const unsigned* end()
const
561 class univ_dest_mapper
563 std::map<std::vector<unsigned>,
unsigned> uniq_;
567 univ_dest_mapper(
G& graph)
573 unsigned new_univ_dests(I begin, I end)
575 std::vector<unsigned> tmp(begin, end);
576 std::sort(tmp.begin(), tmp.end());
577 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
578 auto p = uniq_.emplace(tmp, 0);
580 p.first->second = g_.new_univ_dests(tmp.begin(), tmp.end());
581 return p.first->second;
584 unsigned new_univ_dests(std::vector<unsigned>&& tmp)
586 std::sort(tmp.begin(), tmp.end());
587 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
588 auto p = uniq_.emplace(tmp, 0);
590 p.first->second = g_.new_univ_dests(tmp.begin(), tmp.end());
591 return p.first->second;
603 template <
typename State_Data,
typename Edge_Data>
606 friend class internal::edge_iterator<
digraph>;
607 friend class internal::edge_iterator<const
digraph>;
608 friend class internal::killer_edge_iterator<
digraph>;
611 typedef internal::edge_iterator<digraph> iterator;
612 typedef internal::edge_iterator<const digraph> const_iterator;
615 typedef State_Data state_data_t;
616 typedef Edge_Data edge_data_t;
620 typedef unsigned state;
621 typedef unsigned edge;
623 typedef internal::distate_storage<edge,
624 internal::boxed_label<State_Data>>
626 typedef internal::edge_storage<state, state, edge,
627 internal::boxed_label<Edge_Data>>
629 typedef std::vector<state_storage_t> state_vector;
630 typedef std::vector<edge_storage_t> edge_vector_t;
634 typedef std::vector<unsigned> dests_vector_t;
637 state_vector states_;
638 edge_vector_t edges_;
639 dests_vector_t dests_;
641 unsigned killed_edge_;
649 digraph(
unsigned max_states = 10,
unsigned max_trans = 0)
652 states_.reserve(max_states);
654 max_trans = max_states * 2;
655 edges_.reserve(max_trans + 1);
660 edges_[0].next_succ = 0;
666 return states_.size();
674 return edges_.size() - killed_edge_ - 1;
680 return dests_.empty();
688 template <
typename... Args>
691 state s = states_.size();
692 states_.emplace_back(std::forward<Args>(args)...);
702 template <
typename... Args>
705 state s = states_.size();
706 states_.reserve(s + n);
708 states_.emplace_back(std::forward<Args>(args)...);
723 const state_storage_t&
735 typename state_storage_t::data_t&
738 return states_[s].data();
741 const typename state_storage_t::data_t&
744 return states_[s].data();
759 const edge_storage_t&
771 typename edge_storage_t::data_t&
774 return edges_[s].data();
777 const typename edge_storage_t::data_t&
780 return edges_[s].data();
789 template <
typename... Args>
793 edge t = edges_.size();
794 edges_.emplace_back(dst, 0, src, std::forward<Args>(args)...);
796 edge st = states_[src].succ_tail;
797 SPOT_ASSERT(st < t || !st);
799 states_[src].succ = t;
801 edges_[st].next_succ = t;
802 states_[src].succ_tail = t;
813 template <
typename I>
817 unsigned sz = std::distance(dst_begin, dst_end);
821 unsigned d = dests_.size();
823 && &*dst_begin >= &dests_.front()
824 && &*dst_begin <= &dests_.back()
825 && (dests_.capacity() - dests_.size()) < (sz + 1))
830 std::vector<unsigned> tmp(dst_begin, dst_end);
831 dests_.emplace_back(sz);
832 dests_.insert(dests_.end(), tmp.begin(), tmp.end());
836 dests_.emplace_back(sz);
837 dests_.insert(dests_.end(), dst_begin, dst_end);
848 template <
typename I,
typename... Args>
853 std::forward<Args>(args)...);
861 template <
typename... Args>
867 std::forward<Args>(args)...);
870 internal::const_universal_dests univ_dests(
state src)
const
875 const unsigned* d = dests_.data();
878 return { d + 1, d + num + 1 };
886 internal::const_universal_dests univ_dests(
const edge_storage_t& e)
const
888 return univ_dests(e.dst);
894 SPOT_ASSERT(!states_.empty());
895 return &ss - &states_.front();
901 SPOT_ASSERT(!edges_.empty());
902 return &
tt - &edges_.front();
907 internal::state_out<digraph>
910 return {
this, states_[src].succ};
913 internal::state_out<digraph>
919 internal::state_out<const digraph>
922 return {
this, states_[src].succ};
925 internal::state_out<const digraph>
926 out(state_storage_t& src)
const
936 internal::killer_edge_iterator<digraph>
939 return {
this, src.succ, src};
942 internal::killer_edge_iterator<digraph>
967 internal::all_trans<const digraph>
edges()
const
972 internal::all_trans<digraph>
edges()
1007 return (t < edges_.size() &&
1008 edges_[t].next_succ != t);
1017 return edges_[t].next_succ == t;
1045 unsigned tend = edges_.size();
1046 for (
unsigned t = 1; t < tend; ++t)
1048 o <<
't' << t <<
": (s"
1049 << edges_[t].src <<
", ";
1050 int d = edges_[t].dst;
1055 o <<
") t" << edges_[t].next_succ <<
'\n';
1057 unsigned send = states_.size();
1058 for (
unsigned s = 0; s < send; ++s)
1060 o <<
's' << s <<
": t"
1061 << states_[s].succ <<
" t"
1062 << states_[s].succ_tail <<
'\n';
1064 unsigned dend = dests_.size();
1066 for (
unsigned s = 0; s < dend; ++s)
1068 o <<
'd' << s <<
": ";
1079 o << dests_[s] <<
'\n';
1083 enum dump_storage_items {
1084 DSI_GraphHeader = 1,
1085 DSI_GraphFooter = 2,
1086 DSI_StatesHeader = 4,
1088 DSI_StatesFooter = 16,
1089 DSI_States = DSI_StatesHeader | DSI_StatesBody | DSI_StatesFooter,
1090 DSI_EdgesHeader = 32,
1092 DSI_EdgesFooter = 128,
1093 DSI_Edges = DSI_EdgesHeader | DSI_EdgesBody | DSI_EdgesFooter,
1094 DSI_DestsHeader = 256,
1095 DSI_DestsBody = 512,
1096 DSI_DestsFooter = 1024,
1097 DSI_Dests = DSI_DestsHeader | DSI_DestsBody | DSI_DestsFooter,
1099 DSI_GraphHeader | DSI_States | DSI_Edges | DSI_Dests | DSI_GraphFooter,
1105 if (dsi & DSI_GraphHeader)
1106 o <<
"digraph g { \nnode [shape=plaintext]\n";
1107 unsigned send = states_.size();
1108 if (dsi & DSI_StatesHeader)
1110 o << (
"states [label=<\n"
1111 "<table border='0' cellborder='1' cellspacing='0'>\n"
1112 "<tr><td sides='b' bgcolor='yellow' port='s'>states</td>\n");
1113 for (
unsigned s = 0; s < send; ++s)
1114 o <<
"<td sides='b' bgcolor='yellow' port='s" << s <<
"'>"
1118 if (dsi & DSI_StatesBody)
1120 o <<
"<tr><td port='ss'>succ</td>\n";
1121 for (
unsigned s = 0; s < send; ++s)
1123 o <<
"<td port='ss" << s;
1124 if (states_[s].succ)
1125 o <<
"' bgcolor='cyan";
1126 o <<
"'>" << states_[s].succ <<
"</td>\n";
1128 o <<
"</tr><tr><td port='st'>succ_tail</td>\n";
1129 for (
unsigned s = 0; s < send; ++s)
1131 o <<
"<td port='st" << s;
1132 if (states_[s].succ_tail)
1133 o <<
"' bgcolor='cyan";
1134 o <<
"'>" << states_[s].succ_tail <<
"</td>\n";
1138 if (dsi & DSI_StatesFooter)
1139 o <<
"</table>>]\n";
1140 unsigned eend = edges_.size();
1141 if (dsi & DSI_EdgesHeader)
1143 o << (
"edges [label=<\n"
1144 "<table border='0' cellborder='1' cellspacing='0'>\n"
1145 "<tr><td sides='b' bgcolor='cyan' port='e'>edges</td>\n");
1146 for (
unsigned e = 1; e < eend; ++e)
1148 o <<
"<td sides='b' bgcolor='"
1149 << (e != edges_[e].next_succ ?
"cyan" :
"gray")
1150 <<
"' port='e" << e <<
"'>" << e <<
"</td>\n";
1154 if (dsi & DSI_EdgesBody)
1156 o <<
"<tr><td port='ed'>dst</td>\n";
1157 for (
unsigned e = 1; e < eend; ++e)
1159 o <<
"<td port='ed" << e;
1160 int d = edges_[e].dst;
1162 o <<
"' bgcolor='pink'>~" << ~d;
1164 o <<
"' bgcolor='yellow'>" << d;
1167 o <<
"</tr><tr><td port='en'>next_succ</td>\n";
1168 for (
unsigned e = 1; e < eend; ++e)
1170 o <<
"<td port='en" << e;
1171 if (edges_[e].next_succ)
1173 if (edges_[e].next_succ != e)
1174 o <<
"' bgcolor='cyan";
1176 o <<
"' bgcolor='gray";
1178 o <<
"'>" << edges_[e].next_succ <<
"</td>\n";
1180 o <<
"</tr><tr><td port='es'>src</td>\n";
1181 for (
unsigned e = 1; e < eend; ++e)
1182 o <<
"<td port='es" << e <<
"' bgcolor='yellow'>"
1183 << edges_[e].src <<
"</td>\n";
1186 if (dsi & DSI_EdgesFooter)
1187 o <<
"</table>>]\n";
1188 if (!dests_.empty())
1190 unsigned dend = dests_.size();
1191 if (dsi & DSI_DestsHeader)
1193 o << (
"dests [label=<\n"
1194 "<table border='0' cellborder='1' cellspacing='0'>\n"
1195 "<tr><td sides='b' bgcolor='pink' port='d'>dests</td>\n");
1199 o <<
"<td sides='b' bgcolor='pink' port='d"
1200 << d <<
"'>~" << d <<
"</td>\n";
1201 unsigned cnt = dests_[d];
1204 o <<
"<td sides='b'></td>\n";
1208 if (dsi & DSI_DestsBody)
1210 o <<
"<tr><td port='dd'>#cnt/dst</td>\n";
1214 unsigned cnt = dests_[d];
1215 o <<
"<td port='d'>#" << cnt <<
"</td>\n";
1219 o <<
"<td bgcolor='yellow' port='dd"
1220 << d <<
"'>" << dests_[d] <<
"</td>\n";
1226 if (dsi & DSI_DestsFooter)
1227 o <<
"</table>>]\n";
1229 if (dsi & DSI_GraphFooter)
1240 if (killed_edge_ == 0)
1242 auto i = std::remove_if(edges_.begin() + 1, edges_.end(),
1243 [
this](
const edge_storage_t& t) {
1244 return this->is_dead_edge(t);
1246 edges_.erase(i, edges_.end());
1255 template<
class Predicate = std::less<edge_storage_t>>
1260 std::stable_sort(edges_.begin() + 1, edges_.end(), p);
1272 template<
class Predicate = std::less<edge_storage_t>>
1276 SPOT_ASSERT(!edges_.empty());
1278 std::vector<unsigned> idx_list(ns+1);
1279 edge_vector_t new_edges;
1280 new_edges.reserve(edges_.size());
1281 new_edges.resize(1);
1283 new_edges[0].next_succ = 0;
1285 for (
unsigned s = 0; s < ns; ++s)
1287 idx_list[s] = new_edges.size();
1288 for (
const auto& e :
out(s))
1289 new_edges.push_back(e);
1291 idx_list[ns] = new_edges.size();
1295 auto bne = new_edges.begin();
1296#ifndef SPOT_ENABLE_PTHREAD
1299 unsigned nthreads = ppolicy.nthreads();
1303 for (
unsigned s = 0u; s < ns; ++s)
1304 std::stable_sort(bne + idx_list[s],
1305 bne + idx_list[s+1], p);
1307#ifdef SPOT_ENABLE_PTHREAD
1310 static std::vector<std::thread> tv;
1311 SPOT_ASSERT(tv.empty());
1312 tv.resize(nthreads);
1317 for (
unsigned id = 0;
id < nthreads; ++id)
1318 tv[
id] = std::thread(
1319 [bne,
id, ns, &idx_list, p, nthreads]()
1321 for (
unsigned s =
id; s < ns; s += nthreads)
1322 std::stable_sort(bne + idx_list[s],
1323 bne + idx_list[s+1], p);
1331 std::swap(edges_, new_edges);
1342 template<
bool Stable = false,
class Predicate = std::less<edge_storage_t>>
1344 const std::vector<bool>* to_sort_ptr =
nullptr)
1346 SPOT_ASSERT((to_sort_ptr ==
nullptr)
1350 auto pi = [&](
unsigned t1,
unsigned t2)
1351 {
return p(edges_[t1], edges_[t2]); };
1355 std::vector<unsigned> sort_idx_;
1357 for (
unsigned i = 0; i < ns; ++i)
1359 if (to_sort_ptr && !(*to_sort_ptr)[i])
1361 unsigned t = states_[i].succ;
1367 sort_idx_.push_back(t);
1368 t = edges_[t].next_succ;
1370 if constexpr (Stable)
1371 std::stable_sort(sort_idx_.begin(), sort_idx_.end(), pi);
1373 std::sort(sort_idx_.begin(), sort_idx_.end(), pi);
1375 states_[i].succ = sort_idx_.front();
1376 states_[i].succ_tail = sort_idx_.back();
1377 const unsigned n_outs_n1 = sort_idx_.size() - 1;
1378 for (
unsigned k = 0; k < n_outs_n1; ++k)
1379 edges_[sort_idx_[k]].next_succ = sort_idx_[k+1];
1380 edges_[sort_idx_.back()].next_succ = 0;
1391 state last_src = -1U;
1392 edge tend = edges_.size();
1393 for (edge t = 1; t < tend; ++t)
1395 state src = edges_[t].src;
1396 if (src != last_src)
1398 states_[src].succ = t;
1399 if (last_src != -1U)
1401 states_[last_src].succ_tail = t - 1;
1402 edges_[t - 1].next_succ = 0;
1404 while (++last_src != src)
1406 states_[last_src].succ = 0;
1407 states_[last_src].succ_tail = 0;
1412 edges_[t - 1].next_succ = t;
1415 if (last_src != -1U)
1417 states_[last_src].succ_tail = tend - 1;
1418 edges_[tend - 1].next_succ = 0;
1420 unsigned send = states_.size();
1421 while (++last_src != send)
1423 states_[last_src].succ = 0;
1424 states_[last_src].succ_tail = 0;
1437 SPOT_ASSERT(newst.size() == states_.size());
1438 unsigned tend = edges_.size();
1439 for (
unsigned t = 1; t < tend; t++)
1441 edges_[t].dst = newst[edges_[t].dst];
1442 edges_[t].src = newst[edges_[t].src];
1464 SPOT_ASSERT(newst.size() >= states_.size());
1465 SPOT_ASSERT(used_states > 0);
1472 permute_vector(states_, newst);
1473 unsigned send = states_.size();
1474 for (state s = used_states; s < send; ++s)
1479 auto t = states_[s].succ;
1481 std::swap(t, edges_[t].next_succ);
1483 states_.resize(used_states);
1493 unsigned tend = edges_.size();
1494 std::vector<edge> newidx(tend);
1496 for (edge t = 1; t < tend; ++t)
1501 edges_[dest] = std::move(edges_[t]);
1505 edges_.resize(dest);
1509 for (edge t = 1; t < dest; ++t)
1511 auto& tr = edges_[t];
1512 tr.src = newst[tr.src];
1513 tr.dst = newst[tr.dst];
1514 tr.next_succ = newidx[tr.next_succ];
1518 for (
auto& s: states_)
1520 s.succ = newidx[s.succ];
1521 s.succ_tail = newidx[s.succ_tail];
1529 SPOT_DEPRECATED(
"use reference version of this method")
A directed graph.
Definition graph.hh:605
unsigned num_states() const
The number of states in the automaton.
Definition graph.hh:664
const dests_vector_t & dests_vector() const
The vector used to store universal destinations.
Definition graph.hh:1031
void dump_storage_as_dot(std::ostream &o, int dsi=DSI_All) const
Dump the state and edge storage for debugging.
Definition graph.hh:1103
bool is_dead_edge(const edge_storage_t &t) const
Tests whether an edge has been erased.
Definition graph.hh:1020
void dump_storage(std::ostream &o) const
Dump the state and edge storage for debugging.
Definition graph.hh:1043
internal::state_out< digraph > out(state_storage_t &src)
Return a fake container with all edges leaving src.
Definition graph.hh:914
internal::all_trans< digraph > edges()
Return a fake container with all edges (excluding erased edges)
Definition graph.hh:972
dests_vector_t & dests_vector()
The vector used to store universal destinations.
Definition graph.hh:1036
void sort_edges_of_(Predicate p=Predicate(), const std::vector< bool > *to_sort_ptr=nullptr)
Sort edges of the given states.
Definition graph.hh:1343
state new_states(unsigned n, Args &&... args)
Create n new states.
Definition graph.hh:703
state new_state(Args &&... args)
Create a new states.
Definition graph.hh:689
edge index_of_edge(const edge_storage_t &tt) const
Convert a storage reference into an edge number.
Definition graph.hh:899
const edge_vector_t & edge_vector() const
Return the vector of all edges.
Definition graph.hh:986
internal::killer_edge_iterator< digraph > out_iteraser(state src)
Return a fake container with all edges leaving src, allowing erasure.
Definition graph.hh:943
bool is_valid_edge(edge t) const
Test whether the given edge is valid.
Definition graph.hh:1003
internal::state_out< digraph > out(state src)
Return a fake container with all edges leaving src.
Definition graph.hh:908
internal::state_out< const digraph > out(state_storage_t &src) const
Return a fake container with all edges leaving src.
Definition graph.hh:926
void sort_edges_srcfirst_(Predicate p=Predicate(), parallel_policy ppolicy=parallel_policy())
Sort all edges by src first, then, within edges of the same source use the predicate.
Definition graph.hh:1273
edge new_univ_edge(state src, const std::initializer_list< state > &dsts, Args &&... args)
Create a new universal edge.
Definition graph.hh:863
bool is_existential() const
Whether the automaton uses only existential branching.
Definition graph.hh:678
edge_vector_t & edge_vector()
Return the vector of all edges.
Definition graph.hh:991
const state_storage_t::data_t & state_data(state s) const
return the State_Data associated to a state
Definition graph.hh:742
internal::state_out< const digraph > out(state src) const
Return a fake container with all edges leaving src.
Definition graph.hh:920
state_storage_t::data_t & state_data(state s)
return the State_Data associated to a state
Definition graph.hh:736
void remove_dead_edges_()
Remove all dead edges.
Definition graph.hh:1238
digraph(unsigned max_states=10, unsigned max_trans=0)
Construct an empty graph.
Definition graph.hh:649
state new_univ_dests(I dst_begin, I dst_end)
Create a new universal destination group.
Definition graph.hh:815
const edge_storage_t::data_t & edge_data(edge s) const
return the Edge_Data of an edge.
Definition graph.hh:778
edge_storage_t & edge_storage(edge s)
return a reference to the storage of an edge
Definition graph.hh:754
void rename_states_(const std::vector< unsigned > &newst)
Rename all the states in the edge vector.
Definition graph.hh:1435
void defrag_states(const std::vector< unsigned > &newst, unsigned used_states)
Rename and remove states.
Definition graph.hh:1462
internal::killer_edge_iterator< digraph > out_iteraser(state_storage_t &src)
Return a fake container with all edges leaving src, allowing erasure.
Definition graph.hh:937
const state_vector & states() const
Return the vector of states.
Definition graph.hh:952
internal::all_trans< const digraph > edges() const
Return a fake container with all edges (excluding erased edges)
Definition graph.hh:967
unsigned num_edges() const
The number of edges in the automaton.
Definition graph.hh:672
edge_storage_t::data_t & edge_data(edge s)
return the Edge_Data of an edge.
Definition graph.hh:772
state_storage_t & state_storage(state s)
return a reference to the storage of a state
Definition graph.hh:718
state index_of_state(const state_storage_t &ss) const
Convert a storage reference into a state number.
Definition graph.hh:892
void sort_edges_(Predicate p=Predicate())
Sort all edges according to a predicate.
Definition graph.hh:1256
bool is_dead_edge(unsigned t) const
Tests whether an edge has been erased.
Definition graph.hh:1015
edge new_univ_edge(state src, I dst_begin, I dst_end, Args &&... args)
Create a new universal edge.
Definition graph.hh:850
void chain_edges_()
Reconstruct the chain of outgoing edges.
Definition graph.hh:1389
const edge_storage_t & edge_storage(edge s) const
return a reference to the storage of an edge
Definition graph.hh:760
edge new_edge(state src, state dst, Args &&... args)
Create a new edge.
Definition graph.hh:791
state_vector & states()
Return the vector of states.
Definition graph.hh:957
const state_storage_t & state_storage(state s) const
return a reference to the storage of a state
Definition graph.hh:724
This class is used to tell parallel algorithms what resources they may use.
Definition common.hh:155
Abstract class for states.
Definition twa.hh:47
Definition automata.hh:26