Vcsn  2.8
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 of `special` is
110  // tempting, but `one` is not always available.
111  // FIXME: it will be available in Vcsn 3.
112  auto label = ls.special();
113  auto weight = ws.one();
114  auto dst = psrc;
115  add_tape_transitions_<0>(src, psrc, dst, label, weight);
116  }
117  }
118 
127  template <std::size_t I>
128  void add_tape_transitions_(const state_t src, const state_name_t& srcn,
129  state_name_t dstn,
130  label_t label, const weight_t& weight)
131  {
132  const auto& ls = *aut_->labelset();
133  const auto& ws = *aut_->weightset();
134  const auto& aut = std::get<I>(aut_->auts_);
135  // Add an outgoing transition from `src` to `dst` with
136  // `<weight>label`.
137  auto add =
138  static_if<I + 1 == sizeof...(Auts)>
139  ([this](auto src, const auto&, const auto& dstn,
140  const auto& label, const auto& weight)
141  {
142  if (state(dstn) == aut_->post())
143  // The label is actually a tuple of \e (instead of a
144  // tuple of special), don't use it.
145  aut_->set_final(src, weight);
146  else
147  aut_->new_transition(src, state(dstn), label, weight);
148  },
149  [this](auto src, const auto& srcn, const auto& dstn,
150  const auto& label, const auto& weight)
151  {
152  add_tape_transitions_<I + 1>(src, srcn, dstn, label, weight);
153  });
154 
155  if (std::get<I>(srcn) == aut->post())
156  {
157  std::get<I>(label) = label_one(ls.template set<I>());
158  add(src, srcn, dstn, label, weight);
159  }
160  else
161  for (auto t: aut->all_out(std::get<I>(srcn)))
162  {
163  std::get<I>(label)
164  = aut->dst_of(t) == aut->post()
165  ? label_one(ls.template set<I>())
166  : aut->label_of(t);
167  std::get<I>(dstn) = aut->dst_of(t);
168  add(src, srcn, dstn, label, ws.mul(weight, aut->weight_of(t)));
169  }
170  }
171  };
172 
173 
174  /*-----------------------.
175  | tuple(automaton...). |
176  `-----------------------*/
177 
179  template <Automaton... Auts>
180  auto
181  tuple(const Auts&... as)
182  {
183  auto ctx = tuple_context(as->context()...);
184  auto aut = make_mutable_automaton(ctx);
185  auto res = tuple_automata_impl<decltype(aut), Auts...>(aut, as...);
186  res.tuple();
187  return res.strip();
188  }
189  }
190 
191  using detail::tuple;
192 
193  namespace dyn
194  {
195  namespace detail
196  {
198  template <typename Auts, size_t... I>
199  automaton
200  tuple_(const std::vector<automaton>& as,
202  {
203  return tuple(as[I]->as<tuple_element_t<I, Auts>>()...);
204  }
205 
207  template <typename Auts>
208  automaton
209  tuple(const std::vector<automaton>& as)
210  {
211  auto indices
213  return tuple_<Auts>(as, indices);
214  }
215  }
216  }
217 }
A dyn automaton.
Definition: automaton.hh:17
base_t< tuple_element_t< I, automata_t > > input_automaton_t
The type of the Ith input automaton, unqualified.
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:54
void add_tape_transitions_(const state_t src, const state_name_t &srcn, state_name_t dstn, label_t label, const weight_t &weight)
Add outgoing transitions from src computed by looking at tape I and beyond.
automaton tuple(const std::vector< automaton > &as)
Bridge.
typename tuple_automaton_impl::state_name_t state_name_t
tuple_automata_impl(Aut aut, const Auts &... auts)
Build a tuple automaton.
Decorator implementing the laziness for an algorithm.
typename super_t::state_t state_t
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.
auto tuple_context(Ctx &&... ctx) -> context< tupleset< labelset_t_of< Ctx >... >, join_t< weightset_t_of< Ctx >... >>
Definition: tuple.hh:16
void add_tuple_transitions_(const state_t src, const state_name_t &psrc, seq< I... >)
state_t state(Args &&... args)
Conversion from state name to state number.
automaton_t aut_
The wrapped automaton, possibly const.
auto tuple(const Auts &... as)
Build the (accessible part of the) tuple.
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
typename weightset_t::value_t weight_t
typename labelset_t::value_t label_t
typename super_t::state_name_t state_name_t
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
Build the static sequence of size_t [0, N[.
Definition: tuple.hh:56
std::remove_cv_t< std::remove_reference_t< T > > base_t
T without reference or const/volatile qualifiers.
Definition: traits.hh:13
Definition: a-star.hh:8
automaton tuple_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Bridge helper.
Aut automaton_t
The type of the resulting automaton.
context_t_of< Aut > context_t
The context of the result.
void tuple()
Compute the (accessible part of the) tuple.
A static list of size_t.
Definition: tuple.hh:32
typename tuple_automaton_impl::state_t state_t
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
typename super_t::template seq< I... > seq
std::tuple< Auts... > automata_t
The type of input automata.
value_impl< detail::label_tag > label
Definition: fwd.hh:32
std::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
auto static_if(Then &&then, Else &&else_)
Execute the then- or the else-clause depending on cond.
Definition: static-if.hh:27
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
#define Automaton
Definition: automaton.hh:23
Build the (accessible part of the) Cartesian product of automata.
weightset_t_of< context_t > weightset_t
labelset_t_of< context_t > labelset_t
const weightset_t & ws_
The resulting weightset.
value_impl< detail::weight_tag > weight
Definition: fwd.hh:34
return res
Definition: multiply.hh:399
bool all(Bool &&... values)
Whether all the values evaluate as true.
Definition: tuple.hh:492