Vcsn  2.3
Be Rational
tuple-automaton.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vcsn/algos/tuple.hh>
5 #include <vcsn/dyn/automaton.hh>
6 
7 namespace vcsn
8 {
9  namespace detail
10  {
11  /*-------------------------------.
12  | tuple_automata_impl<Aut...>. |
13  `-------------------------------*/
14 
23  template <Automaton Aut, Automaton... Auts>
25  : public lazy_tuple_automaton<tuple_automata_impl<Aut, Auts...>,
26  false, false, Aut, Auts...>
27  {
29  using automaton_t = Aut;
31  using super_t = lazy_tuple_automaton<self_t, false, false, Aut, Auts...>;
32 
33  public:
35  using state_t = typename super_t::state_t;
36 
37  template <size_t... I>
38  using seq = typename super_t::template seq<I...>;
39 
40  using super_t::ws_;
42 
47 
48  using label_t = typename labelset_t::value_t;
49  using weight_t = typename weightset_t::value_t;
50 
52  using automata_t = std::tuple<Auts...>;
53 
55  template <size_t I>
57 
58  using super_t::aut_;
59 
63  tuple_automata_impl(Aut aut, const Auts&... auts)
64  : super_t{aut, auts...}
65  {
66  aut_->todo_.emplace_back(aut_->pre_(), aut_->pre());
67  }
68 
70  void tuple()
71  {
72  try
73  {
74  while (!aut_->todo_.empty())
75  {
76  const auto& p = aut_->todo_.front();
77  add_tuple_transitions(std::get<1>(p), std::get<0>(p));
78  aut_->todo_.pop_front();
79  }
80  }
81  catch (const std::runtime_error& e)
82  {
83  raise(e, " while tupling automata");
84  }
85  }
86 
87  private:
88  using super_t::out_;
89  using super_t::state;
94  void add_tuple_transitions(const state_t src, const state_name_t& psrc)
95  {
96  add_tuple_transitions_(src, psrc, aut_->indices);
97  }
98 
99  template <std::size_t... I>
100  void add_tuple_transitions_(const state_t src, const state_name_t& psrc,
101  seq<I...>)
102  {
103  // If this is post, we are done.
104  if (!all((std::get<I>(psrc) == std::get<I>(aut_->auts_)->post())...))
105  {
106  const auto& ls = *aut_->labelset();
107  const auto& ws = *aut_->weightset();
108  // A blank label: the labels of each tape will be inserted
109  // one after the other. Using `one` instead `special` is
110  // tempting, but `one` is not always available.
111  auto label = ls.special();
112  auto weight = ws.one();
113  auto dst = psrc;
114  add_tape_transitions_<0>(src, psrc, dst, label, weight);
115  }
116  }
117 
118  template <std::size_t I>
119  void add_tape_transitions_(const state_t src, const state_name_t& psrc,
120  state_name_t dst,
122  {
123  const auto& ls = *aut_->labelset();
124  const auto& ws = *aut_->weightset();
125  const auto& aut = std::get<I>(aut_->auts_);
126  // FIXME: too much code duplication between both branches,
127  // something is missing. FIXME: a lot of passing by value on
128  // dst, label and weight. We can probably be more economical.
129  if (std::get<I>(psrc) == aut->post())
130  {
131  std::get<I>(label) = label_one(ls.template set<I>());
132  static_if<I + 1 == sizeof...(Auts)>
133  ([this](auto src, auto, auto dst, auto label, auto weight)
134  {
135  if (state(dst) == aut_->post())
136  // The label is actually a tuple of \e, don't use it.
137  aut_->set_final(src, weight);
138  else
139  aut_->new_transition(src, state(dst), label, weight);
140  },
141  [this](auto src, auto psrc, auto dst, auto label, auto weight)
142  {
143  add_tape_transitions_<I + 1>(src, psrc, dst, label, weight);
144  })
145  (src, psrc, dst, label, weight);
146  }
147  else
148  for (auto t: aut->all_out(std::get<I>(psrc)))
149  {
150  std::get<I>(label)
151  = aut->dst_of(t) == aut->post()
152  ? label_one(ls.template set<I>())
153  : aut->label_of(t);
154  weight = ws.mul(weight, aut->weight_of(t));
155  std::get<I>(dst) = aut->dst_of(t);
156  static_if<I + 1 == sizeof...(Auts)>
157  ([this,&ls,&ws](auto src, auto, auto dst, auto label, auto weight)
158  {
159  if (state(dst) == aut_->post())
160  // The label is actually a tuple of \e, don't use it.
161  aut_->set_final(src, weight);
162  else
163  aut_->new_transition(src, state(dst), label, weight);
164  },
165  [this](auto src, auto psrc, auto dst, auto label, auto weight)
166  {
167  add_tape_transitions_<I + 1>(src, psrc, dst, label, weight);
168  })
169  (src, psrc, dst, label, weight);
170  }
171  }
172  };
173 
174 
175  /*-----------------------.
176  | tuple(automaton...). |
177  `-----------------------*/
178 
180  template <Automaton... Auts>
181  auto
182  tuple(const Auts&... as)
183  {
184  auto ctx = tuple_context(as->context()...);
185  auto aut = make_mutable_automaton(ctx);
186  auto res = tuple_automata_impl<decltype(aut), Auts...>(aut, as...);
187  res.tuple();
188  return res.strip();
189  }
190  }
191 
192  using detail::tuple;
193 
194  namespace dyn
195  {
196  namespace detail
197  {
199  template <typename Auts, size_t... I>
200  automaton
201  tuple_(const std::vector<automaton>& as,
203  {
204  return tuple(as[I]->as<tuple_element_t<I, Auts>>()...);
205  }
206 
208  template <typename Auts>
209  automaton
210  tuple(const std::vector<automaton>& as)
211  {
212  auto indices
214  return tuple_<Auts>(as, indices);
215  }
216  }
217  }
218 }
value_impl< detail::weight_tag > weight
Definition: fwd.hh:28
void tuple()
Compute the (accessible part of the) tuple.
typename super_t::state_t state_t
Aut automaton_t
The type of the resulting automaton.
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
#define Automaton
Definition: automaton.hh:23
std::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
typename labelset_t::value_t label_t
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:53
typename weightset_t::value_t weight_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
typename tuple_automaton_impl::state_name_t state_name_t
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
tuple_automata_impl(Aut aut, const Auts &...auts)
Build a tuple automaton.
labelset_t_of< context_t > labelset_t
return res
Definition: multiply.hh:398
auto tuple(const Auts &...as)
Build the (accessible part of the) tuple.
context_t_of< Aut > context_t
The context of the result.
void add_tuple_transitions_(const state_t src, const state_name_t &psrc, seq< I... >)
void add_tuple_transitions(const state_t src, const state_name_t &psrc)
Add transitions to the result automaton, starting from the given result input state, which must correspond to the given pair of input state automata.
value_impl< detail::label_tag > label
Definition: fwd.hh:26
typename tuple_automaton_impl::state_t state_t
const weightset_t & ws_
The resulting weightset.
typename super_t::template seq< I... > seq
auto static_if(std::true_type, Then &&then, Else &&)
Execute the then-clause.
Definition: static-if.hh:13
Definition: a-star.hh:8
A dyn automaton.
Definition: automaton.hh:17
std::remove_cv_t< std::remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
Definition: traits.hh:13
bool all(Bool &&...values)
Whether all the values evaluate as true.
Definition: tuple.hh:446
automaton tuple_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Bridge helper.
Build the (accessible part of the) Cartesian product of automata.
automaton tuple(const std::vector< automaton > &as)
Bridge.
state_t state(Args &&...args)
Conversion from state name to state number.
void add_tape_transitions_(const state_t src, const state_name_t &psrc, state_name_t dst, label_t label, weight_t weight)
std::tuple< Auts... > automata_t
The type of input automata.
typename super_t::state_name_t state_name_t
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:67
automaton_t aut_
The wrapped automaton, possibly const.
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
Decorator implementing the laziness for an algorithm.
auto tuple_context(Ctx &&...ctx) -> context< tupleset< labelset_t_of< Ctx >... >, join_t< weightset_t_of< Ctx >... >>
Definition: tuple.hh:15
weightset_t_of< context_t > weightset_t
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)