22 #include <spot/misc/common.hh>
24 #include <type_traits>
31 #include <type_traits>
35 template <
typename State_Data,
typename Edge_Data>
41 template <
typename Of,
typename ...Args>
44 static const bool value =
false;
47 template <
typename Of,
typename Arg1,
typename ...Args>
50 static const bool value =
51 std::is_base_of<Of, typename std::decay<Arg1>::type>::value;
61 template <typename Data, bool boxed = !std::is_class<Data>::value>
68 template <
typename... Args,
69 typename =
typename std::enable_if<
71 boxed_label(Args&&... args)
72 noexcept(std::is_nothrow_constructible<Data, Args...>::value)
73 : label{std::forward<Args>(args)...}
80 explicit boxed_label()
81 noexcept(std::is_nothrow_constructible<Data>::value)
90 const Data& data()
const
95 bool operator<(
const boxed_label& other)
const
97 return label < other.label;
104 typedef std::tuple<> data_t;
110 const std::tuple<>& data()
const
117 template <
typename Data>
123 template <
typename... Args,
124 typename =
typename std::enable_if<
126 boxed_label(Args&&... args)
127 noexcept(std::is_nothrow_constructible<Data, Args...>::value)
128 : Data{std::forward<Args>(args)...}
135 explicit boxed_label()
136 noexcept(std::is_nothrow_constructible<Data>::value)
145 const Data& data()
const
158 template <
typename Edge,
typename State_Data>
165 template <
typename... Args,
166 typename =
typename std::enable_if<
168 distate_storage(Args&&... args)
169 noexcept(std::is_nothrow_constructible<State_Data, Args...>::value)
170 : State_Data{std::forward<Args>(args)...}
182 template <
typename StateIn,
183 typename StateOut,
typename Edge,
typename Edge_Data>
194 noexcept(std::is_nothrow_constructible<Edge_Data>::value)
200 template <
typename... Args>
202 StateIn src, Args&&... args)
203 noexcept(std::is_nothrow_constructible<Edge_Data, Args...>::value
204 && std::is_nothrow_constructible<StateOut, StateOut>::value
205 && std::is_nothrow_constructible<Edge, Edge>::value)
206 : Edge_Data{std::forward<Args>(args)...},
207 dst(dst), next_succ(next_succ), src(src)
223 return this->data() < other.data();
228 return src == other.src &&
230 this->data() == other.data();
242 template <
typename Graph>
246 typedef typename std::conditional<std::is_const<Graph>::value,
247 const typename Graph::edge_storage_t,
248 typename Graph::edge_storage_t>::type
250 typedef value_type& reference;
251 typedef value_type* pointer;
252 typedef std::ptrdiff_t difference_type;
253 typedef std::forward_iterator_tag iterator_category;
255 typedef typename Graph::edge edge;
277 reference operator*()
const
279 return g_->edge_storage(t_);
282 pointer operator->()
const
284 return &g_->edge_storage(t_);
289 t_ = operator*().next_succ;
296 t_ = operator*().next_succ;
300 operator bool()
const
315 template <
typename Graph>
320 typedef typename Graph::state_storage_t state_storage_t;
321 typedef typename Graph::edge edge;
324 : super(g, t), src_(src), prev_(0)
331 this->t_ = this->operator*().next_succ;
345 edge next = this->operator*().next_succ;
350 this->g_->edge_storage(prev_).next_succ = next;
354 if (src_.succ == this->t_)
357 if (src_.succ_tail == this->t_)
359 src_.succ_tail = prev_;
360 SPOT_ASSERT(next == 0);
364 this->operator*().next_succ = this->t_;
369 ++this->g_->killed_edge_;
373 state_storage_t& src_;
384 template <
typename Graph>
388 typedef typename Graph::edge edge;
418 template <
typename Graph>
422 typedef typename std::conditional<std::is_const<Graph>::value,
423 const typename Graph::edge_storage_t,
424 typename Graph::edge_storage_t>::type
426 typedef value_type& reference;
427 typedef value_type* pointer;
428 typedef std::ptrdiff_t difference_type;
429 typedef std::forward_iterator_tag iterator_category;
432 typedef typename std::conditional<std::is_const<Graph>::value,
433 const typename Graph::edge_vector_t,
434 typename Graph::edge_vector_t>::type
442 unsigned s = tv_.size();
445 while (t_ < s && tv_[t_].next_succ == t_);
456 : t_(tv.size()), tv_(tv)
483 reference operator*()
const
488 pointer operator->()
const
495 template <
typename Graph>
499 typedef typename std::conditional<std::is_const<Graph>::value,
500 const typename Graph::edge_vector_t,
501 typename Graph::edge_vector_t>::type
527 const unsigned* begin_;
528 const unsigned* end_;
532 : begin_(begin), end_(end)
537 : begin_(&tmp_), end_(&tmp_ + 1), tmp_(state)
541 const unsigned* begin()
const
546 const unsigned* end()
const
555 std::map<std::vector<unsigned>,
unsigned> uniq_;
565 unsigned new_univ_dests(I begin, I end)
567 std::vector<unsigned> tmp(begin, end);
568 std::sort(tmp.begin(), tmp.end());
569 tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
570 auto p = uniq_.emplace(tmp, 0);
572 p.first->second = g_.new_univ_dests(tmp.begin(), tmp.end());
573 return p.first->second;
585 template <
typename State_Data,
typename Edge_Data>
597 typedef State_Data state_data_t;
598 typedef Edge_Data edge_data_t;
602 typedef unsigned state;
603 typedef unsigned edge;
611 typedef std::vector<state_storage_t> state_vector;
612 typedef std::vector<edge_storage_t> edge_vector_t;
616 typedef std::vector<unsigned> dests_vector_t;
619 state_vector states_;
620 edge_vector_t edges_;
621 dests_vector_t dests_;
623 unsigned killed_edge_;
631 digraph(
unsigned max_states = 10,
unsigned max_trans = 0)
634 states_.reserve(max_states);
636 max_trans = max_states * 2;
637 edges_.reserve(max_trans + 1);
642 edges_[0].next_succ = 0;
648 return states_.size();
656 return edges_.size() - killed_edge_ - 1;
662 return !dests_.empty();
670 template <
typename... Args>
673 state s = states_.size();
674 states_.emplace_back(std::forward<Args>(args)...);
684 template <
typename... Args>
687 state s = states_.size();
688 states_.reserve(s + n);
690 states_.emplace_back(std::forward<Args>(args)...);
705 const state_storage_t&
717 typename state_storage_t::data_t&
720 return states_[s].data();
723 const typename state_storage_t::data_t&
726 return states_[s].data();
741 const edge_storage_t&
753 typename edge_storage_t::data_t&
756 return edges_[s].data();
759 const typename edge_storage_t::data_t&
762 return edges_[s].data();
771 template <
typename... Args>
775 edge t = edges_.size();
776 edges_.emplace_back(dst, 0, src, std::forward<Args>(args)...);
778 edge st = states_[src].succ_tail;
779 SPOT_ASSERT(st < t || !st);
781 states_[src].succ = t;
783 edges_[st].next_succ = t;
784 states_[src].succ_tail = t;
795 template <
typename I>
799 unsigned sz = std::distance(dst_begin, dst_end);
803 unsigned d = dests_.size();
804 dests_.emplace_back(sz);
805 dests_.insert(dests_.end(), dst_begin, dst_end);
815 template <
typename I,
typename... Args>
819 return new_edge(src, new_univ_dests(dst_begin, dst_end),
820 std::forward<Args>(args)...);
828 template <
typename... Args>
833 return new_univ_edge(src, dsts.begin(), dsts.end(),
834 std::forward<Args>(args)...);
842 const unsigned* d = dests_.data();
845 return { d + 1, d + num + 1 };
853 internal::const_universal_dests univ_dests(
const edge_storage_t& e)
const
855 return univ_dests(e.dst);
861 SPOT_ASSERT(!states_.empty());
862 return &ss - &states_.front();
868 SPOT_ASSERT(!edges_.empty());
869 return &tt - &edges_.front();
877 return {
this, states_[src].succ};
883 return out(index_of_state(src));
889 return {
this, states_[src].succ};
893 out(state_storage_t& src)
const
895 return out(index_of_state(src));
906 return {
this, src.succ, src};
912 return out_iteraser(state_storage(src));
974 return (t < edges_.size() &&
975 edges_[t].next_succ != t);
984 return edges_[t].next_succ == t;
989 return t.next_succ == index_of_edge(t);
1012 unsigned tend = edges_.size();
1013 for (
unsigned t = 1; t < tend; ++t)
1015 o <<
't' << t <<
": (s"
1016 << edges_[t].src <<
", ";
1017 int d = edges_[t].dst;
1022 o <<
") t" << edges_[t].next_succ <<
'\n';
1024 unsigned send = states_.size();
1025 for (
unsigned s = 0; s < send; ++s)
1027 o <<
's' << s <<
": t"
1028 << states_[s].succ <<
" t"
1029 << states_[s].succ_tail <<
'\n';
1031 unsigned dend = dests_.size();
1033 for (
unsigned s = 0; s < dend; ++s)
1035 o <<
'd' << s <<
": ";
1046 o << dests_[s] <<
'\n';
1057 if (killed_edge_ == 0)
1059 auto i = std::remove_if(edges_.begin() + 1, edges_.end(),
1060 [
this](
const edge_storage_t& t) {
1061 return this->is_dead_edge(t);
1063 edges_.erase(i, edges_.end());
1072 template<
class Predicate = std::less<edge_storage_t>>
1077 std::stable_sort(edges_.begin() + 1, edges_.end(), p);
1086 state last_src = -1
U;
1087 edge tend = edges_.size();
1088 for (edge t = 1; t < tend; ++t)
1090 state src = edges_[t].src;
1091 if (src != last_src)
1093 states_[src].succ = t;
1094 if (last_src != -1
U)
1096 states_[last_src].succ_tail = t - 1;
1097 edges_[t - 1].next_succ = 0;
1099 while (++last_src != src)
1101 states_[last_src].succ = 0;
1102 states_[last_src].succ_tail = 0;
1107 edges_[t - 1].next_succ = t;
1110 if (last_src != -1
U)
1112 states_[last_src].succ_tail = tend - 1;
1113 edges_[tend - 1].next_succ = 0;
1115 unsigned send = states_.size();
1116 while (++last_src != send)
1118 states_[last_src].succ = 0;
1119 states_[last_src].succ_tail = 0;
1132 SPOT_ASSERT(newst.size() == states_.size());
1133 unsigned tend = edges_.size();
1134 for (
unsigned t = 1; t < tend; t++)
1136 edges_[t].dst = newst[edges_[t].dst];
1137 edges_[t].src = newst[edges_[t].src];
1148 SPOT_ASSERT(newst.size() >= states_.size());
1149 SPOT_ASSERT(used_states > 0);
1155 unsigned send = states_.size();
1156 for (state s = 0; s < send; ++s)
1158 state dst = newst[s];
1166 auto t = states_[s].succ;
1168 std::swap(t, edges_[t].next_succ);
1171 states_[dst] = std::move(states_[s]);
1173 states_.resize(used_states);
1178 unsigned tend = edges_.size();
1179 std::vector<edge> newidx(tend);
1181 for (edge t = 1; t < tend; ++t)
1183 if (is_dead_edge(t))
1186 edges_[dest] = std::move(edges_[t]);
1190 edges_.resize(dest);
1194 for (edge t = 1; t < dest; ++t)
1196 auto& tr = edges_[t];
1197 tr.src = newst[tr.src];
1198 tr.dst = newst[tr.dst];
1199 tr.next_succ = newidx[tr.next_succ];
1203 for (
auto& s: states_)
1205 s.succ = newidx[s.succ];
1206 s.succ_tail = newidx[s.succ_tail];
internal::killer_edge_iterator< digraph > out_iteraser(state src)
Return a fake container with all edges leaving src, allowing erasure.
Definition: graph.hh:910
state_storage_t & state_storage(state s)
return a reference to the storage of a state
Definition: graph.hh:700
const edge_storage_t & edge_storage(edge s) const
return a reference to the storage of an edge
Definition: graph.hh:742
const state_storage_t & state_storage(state s) const
return a reference to the storage of a state
Definition: graph.hh:706
edge_vector_t & edge_vector()
Return the vector of all edges.
Definition: graph.hh:958
bool is_dead_edge(unsigned t) const
Tests whether an edge has been erased.
Definition: graph.hh:982
internal::state_out< digraph > out(state_storage_t &src)
Return a fake container with all edges leaving src.
Definition: graph.hh:881
state_storage_t::data_t & state_data(state s)
return the State_Data associated to a state
Definition: graph.hh:718
state new_states(unsigned n, Args &&...args)
Create n new states.
Definition: graph.hh:685
state_vector & states()
Return the vector of states.
Definition: graph.hh:924
edge_storage_t & edge_storage(edge s)
return a reference to the storage of an edge
Definition: graph.hh:736
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:904
state new_univ_dests(I dst_begin, I dst_end)
Create a new universal destination group.
Definition: graph.hh:797
Abstract class for states.
Definition: twa.hh:50
unsigned num_edges() const
The number of edges in the automaton.
Definition: graph.hh:654
dests_vector_t & dests_vector()
The vector used to store universal destinations.
Definition: graph.hh:1003
const dests_vector_t & dests_vector() const
The vector used to store universal destinations.
Definition: graph.hh:998
edge new_univ_edge(state src, const std::initializer_list< state > &dsts, Args &&...args)
Create a new universal edge.
Definition: graph.hh:830
const state_vector & states() const
Return the vector of states.
Definition: graph.hh:919
void sort_edges_(Predicate p=Predicate())
Sort all edge according to a predicate.
Definition: graph.hh:1073
internal::state_out< const digraph > out(state_storage_t &src) const
Return a fake container with all edges leaving src.
Definition: graph.hh:893
edge_storage_t::data_t & edge_data(edge s)
return the Edgeg_Data of an edge.
Definition: graph.hh:754
void dump_storage(std::ostream &o) const
Dump the state and edge storage for debugging.
Definition: graph.hh:1010
void remove_dead_edges_()
Remove all dead edges.
Definition: graph.hh:1055
void rename_states_(const std::vector< unsigned > &newst)
Rename all the states in the edge vector.
Definition: graph.hh:1130
internal::state_out< digraph > out(state src)
Return a fake container with all edges leaving src.
Definition: graph.hh:875
internal::state_out< const digraph > out(state src) const
Return a fake container with all edges leaving src.
Definition: graph.hh:887
const edge_vector_t & edge_vector() const
Return the vector of all edges.
Definition: graph.hh:953
edge new_edge(state src, state dst, Args &&...args)
Create a new edge.
Definition: graph.hh:773
const state_storage_t::data_t & state_data(state s) const
return the State_Data associated to a state
Definition: graph.hh:724
void defrag_states(std::vector< unsigned > &&newst, unsigned used_states)
Rename and remove states.
Definition: graph.hh:1146
bool is_valid_edge(edge t) const
Test whether the given edge is valid.
Definition: graph.hh:970
state index_of_state(const state_storage_t &ss) const
Convert a storage reference into a state number.
Definition: graph.hh:859
void chain_edges_()
Reconstruct the chain of outgoing edges.
Definition: graph.hh:1084
internal::all_trans< digraph > edges()
Return a fake container with all edges (exluding erased edges)
Definition: graph.hh:939
const edge_storage_t::data_t & edge_data(edge s) const
return the Edgeg_Data of an edge.
Definition: graph.hh:760
bool is_dead_edge(const edge_storage_t &t) const
Tests whether an edge has been erased.
Definition: graph.hh:987
A directed graph.
Definition: graph.hh:36
edge index_of_edge(const edge_storage_t &tt) const
Conveart a storage reference into an edge number.
Definition: graph.hh:866
digraph(unsigned max_states=10, unsigned max_trans=0)
Construct an empty graph.
Definition: graph.hh:631
edge new_univ_edge(state src, I dst_begin, I dst_end, Args &&...args)
Create a new universal edge.
Definition: graph.hh:817
bool is_alternating() const
Whether the automaton is alternating.
Definition: graph.hh:660
state new_state(Args &&...args)
Create a new states.
Definition: graph.hh:671
unsigned num_states() const
The number of states in the automaton.
Definition: graph.hh:646
internal::all_trans< const digraph > edges() const
Return a fake container with all edges (exluding erased edges)
Definition: graph.hh:934