Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
compose.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_COMPOSE_HH
2 # define VCSN_ALGOS_COMPOSE_HH
3 
4 # include <deque>
5 # include <iostream>
6 # include <map>
7 
8 # include <vcsn/algos/blind.hh>
9 # include <vcsn/algos/insplit.hh>
12 # include <vcsn/ctx/context.hh>
13 # include <vcsn/dyn/automaton.hh> // dyn::make_automaton
14 # include <vcsn/labelset/tupleset.hh>
15 # include <vcsn/misc/vector.hh> // cross_tuple
16 # include <vcsn/misc/raise.hh>
17 # include <vcsn/misc/tuple.hh> // make_index_sequence
18 # include <vcsn/misc/zip-maps.hh> // make_index_sequence
19 
20 namespace vcsn
21 {
22  namespace detail
23  {
24  /*---------------------------------.
25  | composer<automaton, automaton>. |
26  `---------------------------------*/
27 
29  template <typename Lhs, typename Rhs>
30  class composer
31  {
32  static_assert(Lhs::element_type::full_context_t::is_lat,
33  "compose: lhs labelset must be a tupleset");
34  static_assert(Rhs::element_type::full_context_t::is_lat,
35  "compose: rhs labelset must be a tupleset");
36 
38  template <std::size_t... I>
40 
41  public:
42  using clhs_t = Lhs;
43  using crhs_t = Rhs;
44  // clhs_t and crhs_t are permutation automata, yet we need to
45  // read the res_label_t from their wrapped automaton type.
46  using hidden_l_labelset_t = typename clhs_t::element_type::res_labelset_t;
47  using hidden_r_labelset_t = typename crhs_t::element_type::res_labelset_t;
48  using hidden_l_label_t = typename hidden_l_labelset_t::value_t;
49  using hidden_r_label_t = typename hidden_r_labelset_t::value_t;
50 
51  static_assert(std::is_same<labelset_t_of<clhs_t>,
52  labelset_t_of<crhs_t>>::value,
53  "compose: common tape must be of same type");
54 
66 
67  using res_label_t = typename labelset_t::value_t;
69 
72  Lhs, Rhs>;
73 
77  using state_name_t = typename automaton_t::element_type::state_name_t;
78 
79  composer(const Lhs& lhs, const Rhs& rhs)
81  lhs, rhs))
82  , transition_maps_{{lhs, *res_->weightset()},
83  {rhs, *res_->weightset()}}
84  {}
85 
87  const hidden_r_labelset_t& rl)
88  {
89  return make_labelset_(ll, make_index_sequence<hidden_l_labelset_t::size()>{},
90  rl, make_index_sequence<hidden_r_labelset_t::size()>{});
91  }
92 
93  template <std::size_t... I1, std::size_t... I2>
95  seq<I1...>,
96  const hidden_r_labelset_t& rl,
97  seq<I2...>)
98  {
99  return labelset_t{std::get<I1>(ll.sets())...,
100  std::get<I2>(rl.sets())...};
101  }
102 
103  static context_t
104  make_context_(const Lhs& lhs, const Rhs& rhs)
105  {
106  return {make_labelset_(lhs->res_labelset(), rhs->res_labelset()),
107  join(*lhs->weightset(), *rhs->weightset())};
108  }
109 
112  {
114 
115  while (!res_->todo_.empty())
116  {
117  state_name_t psrc = res_->todo_.front();
118  res_->todo_.pop_front();
119  state_t src = res_->pmap_[psrc];
120 
121  add_compose_transitions(src, psrc);
122  }
123  return std::move(res_);
124  }
125 
126  private:
127  using label_t = typename labelset_t::value_t;
128  using weight_t = typename weightset_t::value_t;
129 
132  template <typename A>
134 
138  {
139  res_->todo_.emplace_back(res_->pre_());
140  }
141 
143  {
144  return std::tuple_cat(ll, rl);
145  }
146 
147  template<typename Aut>
148  typename std::enable_if<labelset_t_of<Aut>::has_one(),
149  typename Aut::element_type::res_label_t>::type
150  get_hidden_one(const Aut& aut)
151  {
152  return aut->hidden_one();
153  }
154 
155  template<typename Aut>
156  typename std::enable_if<!labelset_t_of<Aut>::has_one(),
157  typename Aut::element_type::res_label_t>::type
158  get_hidden_one(const Aut&)
159  {
160  raise("should not get here");
161  }
162 
168  const state_name_t& psrc)
169  {
170  auto& lhs = std::get<0>(res_->auts_);
171  auto& rhs = std::get<1>(res_->auts_);
172 
173  // Outgoing transition cache.
174  const auto& ltm = std::get<0>(transition_maps_)[std::get<0>(psrc)];
175  const auto& rtm = std::get<1>(transition_maps_)[std::get<1>(psrc)];
176 
177  bool has_eps_out = false;
178  if (!has_only_ones_in(rhs, std::get<1>(psrc)))
179  {
180  // "Loop" only on the spontaneous transitions. "One" is
181  // guaranteed to be first in the transition maps.
182  if (!ltm.empty()
183  && lhs->labelset()->is_one(ltm.begin()->first))
184  {
185  has_eps_out = true;
186  for (auto t: ltm.begin()->second)
187  res_->new_transition(src,
188  res_->state(t.dst, std::get<1>(psrc)),
189  join_label(lhs->hidden_label_of(t.transition),
190  get_hidden_one(rhs)),
191  t.wgt);
192  }
193  }
194 
195  // If lhs did not issue spontaneous transitions but has
196  // non-spontaneous transitions, issue follow all the rhs
197  // spontaneous-transitions.
198  const bool lhs_has_non_sp_trans =
199  !lhs->labelset()->is_one(ltm.begin()->first)
200  || 2 <= ltm.size();
201 
202  if (!has_eps_out || lhs_has_non_sp_trans)
203  {
204  if (!rtm.empty()
205  && rhs->labelset()->is_one(rtm.begin()->first))
206  {
207  for (auto t: rtm.begin()->second)
208  res_->new_transition(src,
209  res_->state(std::get<0>(psrc), t.dst),
211  rhs->hidden_label_of(t.transition)),
212  t.wgt);
213  }
214  }
215 
216  for (auto t: zip_maps(ltm, rtm))
217  // The type of the common label is that of the visible tape
218  // of either automata.
219  if (!lhs->labelset()->is_one(t.first))
220  // These are always new transitions: first because the
221  // source state is visited for the first time, and second
222  // because the couple (left destination, label) is unique,
223  // and so is (right destination, label).
225  ([&] (const typename transition_map_t<Lhs>::transition& lts,
226  const typename transition_map_t<Rhs>::transition& rts)
227  {
228  res_->new_transition
229  (src,
230  res_->state(lts.dst, rts.dst),
231  join_label(lhs->hidden_label_of(lts.transition),
232  rhs->hidden_label_of(rts.transition)),
233  res_->weightset()->mul(lts.wgt, rts.wgt));
234  },
235  t.second);
236  }
237 
238  template <typename A>
239  typename std::enable_if<labelset_t_of<A>::has_one(),
240  bool>::type
241  is_one(const A& aut, transition_t_of<A> tr) const
242  {
243  return aut->labelset()->is_one(aut->label_of(tr));
244  }
245 
246  template <typename A>
247  constexpr
248  typename std::enable_if<!labelset_t_of<A>::has_one(),
249  bool>::type
251  const
252  {
253  return false;
254  }
255 
256  template <typename Aut>
257  constexpr
258  typename std::enable_if<!labelset_t_of<Aut>::has_one(),
259  bool>::type
261  {
262  return false;
263  }
264 
265  template <typename Aut>
266  typename std::enable_if<labelset_t_of<Aut>::has_one(),
267  bool>::type
268  has_only_ones_in(const Aut& rhs, state_t_of<Aut> rst) const
269  {
270  auto rin = rhs->all_in(rst);
271  auto rtr = rin.begin();
272  return rtr != rin.end() && is_one(rhs, *rtr) && !rhs->is_initial(rst);
273  }
274 
278  std::tuple<transition_map_t<Lhs>, transition_map_t<Rhs>> transition_maps_;
279  };
280  }
281 
282  /*--------------------------------.
283  | compose(automaton, automaton). |
284  `--------------------------------*/
285 
287  template <typename Lhs, typename Rhs>
288  auto
289  compose(Lhs& lhs, Rhs& rhs)
292  {
293  auto l = blind<1>(lhs);
294  auto r = insplit(blind<0>(rhs));
296  return compose.compose();
297  }
298 
299  namespace dyn
300  {
301  namespace detail
302  {
303 
305  template <typename Lhs, typename Rhs>
306  automaton
308  {
309  auto& l = lhs->as<Lhs>();
310  auto& r = rhs->as<Rhs>();
311  return make_automaton(::vcsn::compose(l, r));
312  }
313 
315  (automaton&, automaton&) -> automaton);
316  }
317  }
318 
319 }
320 
321 
322 #endif // !VCSN_ALGOS_COMPOSE_HH
std::size_t static I2 labelset_t make_labelset_(const hidden_l_labelset_t &ll, seq< I1...>, const hidden_r_labelset_t &rl, seq< I2...>)
Definition: compose.hh:94
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
Build the (accessible part of the) composition.
Definition: compose.hh:30
typename labelset_t::value_t res_label_t
Definition: compose.hh:67
decltype(join(std::declval< ValueSets >()...)) join_t
The type of the join of the ValueSets.
Definition: join.hh:61
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:34
std::enable_if< labelset_t_of< Aut >::has_one(), typename Aut::element_type::res_label_t >::type get_hidden_one(const Aut &aut)
Definition: compose.hh:150
automaton_t res_
The computed product.
Definition: compose.hh:276
weight_t wgt
The (converted) weight.
tuple_automaton< mutable_automaton< context_t >, Lhs, Rhs > automaton_t
The type of the resulting automaton.
Definition: compose.hh:72
res_label_t join_label(hidden_l_label_t ll, hidden_r_label_t rl)
Definition: compose.hh:142
state_t_of< automaton_t > state_t
Result state type.
Definition: compose.hh:75
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:77
std::shared_ptr< detail::blind_automaton_impl< Tape, Aut >> blind_automaton
A blind automaton as a shared pointer.
Definition: fwd.hh:24
typename labelset_t::value_t label_t
Definition: compose.hh:127
typename crhs_t::element_type::res_labelset_t hidden_r_labelset_t
Definition: compose.hh:47
std::enable_if< labelset_t_of< A >::has_one(), bool >::type is_one(const A &aut, transition_t_of< A > tr) const
Definition: compose.hh:241
typename automaton_t::element_type::state_name_t state_name_t
Tuple of states of input automata.
Definition: compose.hh:77
typename hidden_r_labelset_t::value_t hidden_r_label_t
Definition: compose.hh:49
typename hidden_l_labelset_t::value_t hidden_l_label_t
Definition: compose.hh:48
std::enable_if< labelset_t_of< Aut >::has_one(), bool >::type has_only_ones_in(const Aut &rhs, state_t_of< Aut > rst) const
Definition: compose.hh:268
#define REGISTER_DECLARE(Name, Signature)
Definition: fwd.hh:104
void add_compose_transitions(const state_t src, const state_name_t &psrc)
Add transitions to the given result automaton, starting from the given result input state...
Definition: compose.hh:167
composer(const Lhs &lhs, const Rhs &rhs)
Definition: compose.hh:79
typename concat_tupleset< hidden_l_labelset_t, hidden_r_labelset_t >::type labelset_t
The type of context of the result.
Definition: compose.hh:63
static context_t make_context_(const Lhs &lhs, const Rhs &rhs)
Definition: compose.hh:104
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:38
Outgoing signature: weight, destination.
void cross_tuple(Fun f, const std::tuple< Ts...> &ts)
Definition: vector.hh:38
std::tuple< transition_map_t< Lhs >, transition_map_t< Rhs > > transition_maps_
Transition caches.
Definition: compose.hh:278
std::enable_if< labelset_t_of< Aut >::has_one(), Aut >::type insplit(Aut &aut)
Definition: insplit.hh:103
constexpr std::enable_if<!labelset_t_of< A >::has_one(), bool >::type is_one(const A &, transition_t_of< A >) const
Definition: compose.hh:250
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:36
auto compose(Lhs &lhs, Rhs &rhs) -> typename detail::composer< blind_automaton< 1, Lhs >, blind_automaton< 0, Rhs >>::automaton_t
Build the (accessible part of the) composition.
Definition: compose.hh:289
typename weightset_t::value_t weight_t
Definition: compose.hh:128
automaton_t compose()
The (accessible part of the) product of lhs_ and rhs_.
Definition: compose.hh:111
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
labelset_t_of< clhs_t > middle_labelset_t
Definition: compose.hh:55
typename clhs_t::element_type::res_labelset_t hidden_l_labelset_t
Definition: compose.hh:46
constexpr std::enable_if<!labelset_t_of< Aut >::has_one(), bool >::type has_only_ones_in(const Aut &, state_t_of< Aut >) const
Definition: compose.hh:260
zipped_maps< Dereference, Maps...> zip_maps(Maps &&...maps)
Definition: zip-maps.hh:257
void initialize_compose()
Fill the worklist with the initial source-state pairs, as needed for the product algorithm.
Definition: compose.hh:137
join_t< weightset_t_of< context_t_of< Lhs >>, weightset_t_of< context_t_of< Rhs >>> weightset_t
Definition: compose.hh:65
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
SharedPtr make_shared_ptr(Args &&...args)
Same as std::make_shared, but parameterized by the shared_ptr type, not the (pointed to) element_type...
Definition: memory.hh:15
std::shared_ptr< detail::tuple_automaton_impl< Auts...>> tuple_automaton
A product automaton as a shared pointer.
std::enable_if<!labelset_t_of< Aut >::has_one(), typename Aut::element_type::res_label_t >::type get_hidden_one(const Aut &)
Definition: compose.hh:158
Cache the outgoing transitions of an automaton as efficient maps label -> vector<(weight, dst)>.