Vcsn  2.5
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 }
context_t_of< Aut > context_t
The context of the result.
auto tuple_context(Ctx &&... ctx) -> context< tupleset< labelset_t_of< Ctx >... >, join_t< weightset_t_of< Ctx >... >>
Definition: tuple.hh:16
base_t< tuple_element_t< I, automata_t > > input_automaton_t
The type of the Ith input automaton, unqualified.
value_impl< detail::label_tag > label
Definition: fwd.hh:32
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:55
auto tuple(const Auts &... as)
Build the (accessible part of the) tuple.
Definition: a-star.hh:8
auto static_if(std::true_type, Then &&then, Else &&)
Execute the then-clause.
Definition: static-if.hh:13
std::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
return res
Definition: multiply.hh:398
weightset_t_of< context_t > weightset_t
automaton tuple(const std::vector< automaton > &as)
Bridge.
state_t state(Args &&... args)
Conversion from state name to state number.
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.
void tuple()
Compute the (accessible part of the) tuple.
std::tuple< Auts... > automata_t
The type of input automata.
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
typename weightset_t::value_t weight_t
void add_tape_transitions_(const state_t src, const state_name_t &psrc, state_name_t dst, label_t label, weight_t weight)
typename tuple_automaton_impl::state_t state_t
value_impl< detail::weight_tag > weight
Definition: fwd.hh:34
typename labelset_t::value_t label_t
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
labelset_t_of< context_t > labelset_t
typename tuple_automaton_impl::state_name_t state_name_t
const weightset_t & ws_
The resulting weightset.
typename super_t::template seq< I... > seq
typename super_t::state_t state_t
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
void add_tuple_transitions_(const state_t src, const state_name_t &psrc, seq< I... >)
Decorator implementing the laziness for an algorithm.
typename super_t::state_name_t state_name_t
#define Automaton
Definition: automaton.hh:23
std::remove_cv_t< std::remove_reference_t< T > > base_t
T without reference or const/volatile qualifiers.
Definition: traits.hh:13
Aut automaton_t
The type of the resulting automaton.
tuple_automata_impl(Aut aut, const Auts &... auts)
Build a tuple automaton.
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
automaton_t aut_
The wrapped automaton, possibly const.
Build the (accessible part of the) Cartesian product of automata.
A dyn automaton.
Definition: automaton.hh:17
automaton tuple_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Bridge helper.
bool all(Bool &&... values)
Whether all the values evaluate as true.
Definition: tuple.hh:446
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61