Vcsn  2.1
Be Rational
tuple-automaton.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <deque>
4 #include <iostream>
5 #include <map>
6 #include <utility>
7 
9 #include <vcsn/ctx/context.hh>
10 #include <vcsn/ctx/traits.hh>
11 #include <vcsn/misc/map.hh> // has
12 #include <vcsn/misc/tuple.hh>
13 
14 namespace vcsn
15 {
16  namespace detail
17  {
18  /*-------------------------------------.
19  | tuple_automaton_impl<Aut, Auts...>. |
20  `-------------------------------------*/
21 
28  template <typename Aut, typename... Auts>
30  : public automaton_decorator<Aut>
31  {
33  using automaton_t = Aut;
35 
36  public:
37  static symbol sname()
38  {
39  static symbol res("tuple_automaton" + sname_());
40  return res;
41  }
42 
43  std::ostream& print_set(std::ostream& o, format fmt = {}) const
44  {
45  o << "tuple_automaton";
46  print_set_(o, fmt);
47  return o;
48  }
49 
59 
60  using label_t = typename labelset_t::value_t;
61  using weight_t = typename weightset_t::value_t;
62 
63  public:
65  using automata_t = std::tuple<Auts...>;
66 
68  template <size_t I>
70 
72  using super_t::aut_;
73 
74  tuple_automaton_impl(const automaton_t& aut, const Auts&... auts)
75  : super_t(aut)
76  , auts_(auts...)
77  {
78  pmap_[pre_()] = aut_->pre();
79  pmap_[post_()] = aut_->post();
80  }
81 
82  bool state_has_name(typename super_t::state_t s) const
83  {
84  return has(origins(), s);
85  }
86 
87  std::ostream&
88  print_state_name(typename super_t::state_t s, std::ostream& o,
89  format fmt = {}, bool delimit = false)
90  const
91  {
92  if (delimit)
93  o << '(';
94  print_state_name_(s, o, fmt, indices);
95  if (delimit)
96  o << ')';
97  return o;
98  }
99 
103  using state_name_t = std::tuple<state_t_of<Auts>...>;
104 
106  using origins_t = std::map<state_t, state_name_t>;
107 
109  const origins_t& origins() const
110  {
111  origins_.clear();
112  for (const auto& p: pmap_)
113  origins_.emplace(p.second, p.first);
114  return origins_;
115  }
116 
117  // FIXME: protected:
119  template <std::size_t... I>
121 
124  static constexpr indices_t indices{};
125 
127  static std::string sname_()
128  {
129  std::string res = "<" + Aut::element_type::sname() + ", ";
130  const char* sep = "";
131  using swallow = int[];
132  (void) swallow
133  {
134  (res += sep + Auts::element_type::sname(), sep = ", ", 0)...
135  };
136  res += ">";
137  return res;
138  }
139 
141  std::ostream& print_set_(std::ostream& o, format fmt) const
142  {
143  return print_set_(o, fmt, indices);
144  }
145 
146  template <size_t... I>
147  std::ostream& print_set_(std::ostream& o, format fmt,
148  seq<I...>) const
149  {
150  o << '<';
151  aut_->print_set(o, fmt);
152  o << ", ";
153  const char* sep = "";
154  using swallow = int[];
155  (void) swallow
156  {
157  (o << sep,
158  std::get<I>(auts_)->print_set(o, fmt),
159  sep = ", ",
160  0)...
161  };
162  return o << '>';
163  }
164 
166  state_name_t pre_() const
167  {
168  return pre_(indices);
169  }
170 
171  template <size_t... I>
172  state_name_t pre_(seq<I...>) const
173  {
174  // clang 3.4 on top of libstdc++ wants this ctor to be
175  // explicitly called.
176  return state_name_t{(std::get<I>(auts_)->pre())...};
177  }
178 
180  state_name_t post_() const
181  {
182  return post_(indices);
183  }
184 
185  template <size_t... I>
186  state_name_t post_(seq<I...>) const
187  {
188  // clang 3.4 on top of libstdc++ wants this ctor to be
189  // explicitly called.
190  return state_name_t{(std::get<I>(auts_)->post())...};
191  }
192 
199  state_t state(const state_name_t& state)
200  {
201  auto lb = pmap_.lower_bound(state);
202  if (lb == pmap_.end() || pmap_.key_comp()(state, lb->first))
203  {
204  state_t s = aut_->new_state();
205  lb = pmap_.emplace_hint(lb, state, s);
206  todo_.emplace_back(state, s);
207  }
208  return lb->second;
209  }
210 
211  state_t state(state_t_of<Auts>... ss)
212  {
213  return state(std::make_tuple(ss...));
214  }
215 
216  template <size_t... I>
217  std::ostream&
218  print_state_name_(typename super_t::state_t s, std::ostream& o,
219  format fmt,
220  seq<I...>) const
221  {
222  const auto& origs = origins();
223  auto i = origs.find(s);
224  if (i == std::end(origs))
225  this->print_state(s, o);
226  else
227  {
228  const char* sep = "";
229  using swallow = int[];
230  (void) swallow
231  {
232  (o << sep,
233  std::get<I>(auts_)->print_state_name(std::get<I>(i->second),
234  o, fmt, true),
235  sep = ", ",
236  0)...
237  };
238  }
239  return o;
240  }
241 
243  automata_t auts_;
244 
246  using map = std::map<state_name_t, state_t>;
247  map pmap_;
248 
250  std::deque<std::pair<state_name_t, state_t>> todo_;
251 
252  mutable origins_t origins_;
253  };
254  }
255 
257  template <typename... Auts>
258  using tuple_automaton
259  = std::shared_ptr<detail::tuple_automaton_impl<Auts...>>;
260 
261  template <typename... Auts>
262  inline
263  auto
264  make_tuple_automaton(const Auts&... auts)
265  -> tuple_automaton<Auts...>
266  {
267  using res_t = tuple_automaton<Auts...>;
268  return make_shared_ptr<res_t>(auts...);
269  }
270 }
std::ostream & print_state_name(typename super_t::state_t s, std::ostream &o, format fmt={}, bool delimit=false) const
state_t_of< automaton_t > state_t
remove_cv_t< remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
Definition: traits.hh:12
std::ostream & print_set(std::ostream &o, format fmt={}) const
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:45
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
labelset_t_of< context_t > labelset_t
state_t_of< automaton_t > state_t
Result state type.
context_t_of< Aut > context_t
The type of context of the result.
static std::string sname_()
The sname of the sub automata.
std::tuple< state_t_of< Auts >...> state_name_t
State names: Tuple of states of input automata.
std::map< state_t, state_name_t > origins_t
A map from result state to tuple of original states.
Aggregate an automaton, and forward calls to it.
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:28
const origins_t & origins() const
A map from result state to tuple of original states.
state_name_t post_() const
The name of the post of the output automaton.
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
weightset_t_of< context_t > weightset_t
An input/output format.
Definition: format.hh:11
std::ostream & print_set_(std::ostream &o, format fmt) const
The setname of the sub automata.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:47
std::ostream & print_set_(std::ostream &o, format fmt, seq< I...>) const
typename weightset_t::value_t weight_t
Aut automaton_t
The type of the resulting automaton.
tuple_automaton_impl(const automaton_t &aut, const Auts &...auts)
symbol sname()
Definition: name.hh:67
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
automata_t auts_
Input automata, supplied at construction time.
std::tuple< Auts...> automata_t
The type of input automata.
state_name_t pre_() const
The name of the pre of the output automaton.
static constexpr indices_t indices
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
std::ostream & print_state_name_(typename super_t::state_t s, std::ostream &o, format fmt, seq< I...>) const
automaton_t aut_
The wrapped automaton, possibly const.
typename labelset_t::value_t label_t
An automaton whose states are tuples of states of automata.
bool state_has_name(typename super_t::state_t s) const