Vcsn  2.2a
Be Rational
multiply.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <unordered_map>
4 
5 #include <vcsn/algos/copy.hh>
7 #include <vcsn/algos/standard.hh>
8 #include <vcsn/algos/star.hh>
9 #include <vcsn/algos/sum.hh>
10 #include <vcsn/algos/tags.hh>
11 #include <vcsn/core/automaton.hh>
12 #include <vcsn/core/join.hh>
14 #include <vcsn/dyn/automaton.hh> // dyn::make_automaton
15 #include <vcsn/dyn/label.hh>
16 #include <vcsn/dyn/polynomial.hh>
17 #include <vcsn/dyn/weight.hh>
18 #include <vcsn/misc/raise.hh> // require
19 #include <vcsn/misc/vector.hh> // make_vector
20 
21 namespace vcsn
22 {
23  /*----------------------------------.
24  | multiply(automaton, automaton). |
25  `----------------------------------*/
26 
32  template <Automaton Aut1, Automaton Aut2>
33  Aut1&
34  multiply_here(Aut1& res, const Aut2& b, deterministic_tag)
35  {
36  static_assert(labelset_t_of<Aut1>::is_free(),
37  "multiply_here: requires free labelset");
38  multiply_here(res, b, standard_tag{});
39  res = determinize(res)->strip();
40  return res;
41  }
42 
46  template <Automaton Aut1, Automaton Aut2>
47  Aut1&
48  multiply_here(Aut1& res, const Aut2& b, general_tag)
49  {
50  const auto& ls = *res->labelset();
51  const auto& ws = *res->weightset();
52  const auto& bws = *b->weightset();
53 
54  // The set of the current (left-hand side) final transitions.
55  // Store these transitions by copy.
56  auto ftr = detail::make_vector(final_transitions(res));
57 
58  // The set of the current (right-hand side) initial transitions.
59  // Store these transitions by copy.
60  auto init_ts = detail::make_vector(initial_transitions(b));
61 
62  auto copy = make_copier(b, res);
63  copy([](state_t_of<Aut2>) { return true; },
64  // Import all the B transitions, except the initial ones.
65  [b] (transition_t_of<Aut2> t) { return b->src_of(t) != b->pre(); });
66  const auto& map = copy.state_map();
67 
68  // Branch all the final transitions of res to the initial ones in b.
69  for (auto t1: ftr)
70  {
71  auto s1 = res->src_of(t1);
72  auto w1 = res->weight_of(t1);
73  res->del_transition(t1);
74  for (auto t2: init_ts)
75  res->new_transition(s1,
76  map.at(b->dst_of(t2)),
77  ls.one(),
78  ws.mul(w1,
79  ws.conv(bws, b->weight_of(t2))));
80  }
81  return res;
82  }
83 
87  template <Automaton Aut1, Automaton Aut2>
88  Aut1&
89  multiply_here(Aut1& res, const Aut2& b, standard_tag = {})
90  {
91  const auto& ls = *res->labelset();
92  const auto& bls = *b->labelset();
93  const auto& ws = *res->weightset();
94  const auto& bws = *b->weightset();
95 
96  // The set of the current (left-hand side) final transitions.
97  // Store these transitions by copy.
98  auto final_ts = detail::make_vector(final_transitions(res));
99 
100  // The set of the current (right-hand side) initial transitions.
101  // Store these transitions by copy.
102  auto init_ts = detail::make_vector(initial_transitions(b));
103 
104  auto copy = make_copier(b, res);
105  copy(// In order to keep b's transitions unbroken we have to keep its
106  // initial states which have at least one incoming transition.
107  [b](state_t_of<Aut2> s)
108  {
109  return !b->is_initial(s) || !in(b, s).empty();
110  },
111  // Import all the B transitions, except the initial ones (and
112  // those from its (genuine) initial state).
113  [b] (transition_t_of<Aut2> t) { return b->src_of(t) != b->pre(); });
114  const auto& map = copy.state_map();
115 
116  // Branch all the final transitions of res to the successors of
117  // b's initial states.
118  for (auto t1: final_ts)
119  {
120  // Remove the previous final transition first, as we might add
121  // a final transition for the same state later.
122  //
123  // For instance on "<2>a+(<3>\e+<5>a)", the final state s1 of
124  // <2>a will be made final thanks to <3>\e. So if we compute
125  // the new transitions from s1 and then remove t1, we will
126  // have removed the fact that s1 is final thanks to <3>\e.
127  //
128  // Besides, s1 will become final with weight <3>, which might
129  // interfere with <5>a too.
130  auto s1 = res->src_of(t1);
131  auto w1 = res->weight_of(t1);
132  res->del_transition(t1);
133  for (auto t2: init_ts)
134  {
135  auto w2 = b->weight_of(t2);
136  for (auto t3: all_out(b, b->dst_of(t2)))
137  res->set_transition(s1,
138  map.at(b->dst_of(t3)),
139  ls.conv(bls, b->label_of(t3)),
140  ws.mul(w1,
141  ws.conv(bws, w2),
142  ws.conv(bws, b->weight_of(t3))));
143  }
144  }
145  return res;
146  }
147 
149  template <Automaton Aut1, Automaton Aut2, typename Tag = general_tag>
150  auto
151  multiply(const Aut1& lhs, const Aut2& rhs, Tag tag = {})
152  -> decltype(lhs->null_state(), // SFINAE.
153  detail::make_join_automaton(tag, lhs, rhs))
154  {
155  auto res = detail::make_join_automaton(tag, lhs, rhs);
156  ::vcsn::copy_into(lhs, res);
157  multiply_here(res, rhs, tag);
158  return res;
159  }
160 
161  namespace dyn
162  {
163  namespace detail
164  {
166  template <Automaton Lhs, Automaton Rhs, typename String>
167  automaton
168  multiply(const automaton& lhs, const automaton& rhs,
169  const std::string& algo)
170  {
171  const auto& l = lhs->as<Lhs>();
172  const auto& r = rhs->as<Rhs>();
174  (algo == "auto" ? "standard" : algo,
175  [l, r](auto tag)
176  {
177  return make_automaton(::vcsn::multiply(l, r, tag));
178  },
179  l, r);
180  }
181  }
182  }
183 
184  /*---------------------------------.
185  | multiply(automaton, min, max). |
186  `---------------------------------*/
187 
201  template <Automaton Aut, typename Tag = general_tag>
202  auto
203  multiply(const Aut& aut, int min, int max, Tag tag = {})
204  -> decltype(aut->null_state(), // SFINAE.
205  detail::make_join_automaton(tag, aut))
206  {
207  auto res = detail::make_join_automaton(tag, aut);
208  if (min == -1)
209  min = 0;
210  if (max == -1)
211  {
212  res = star(aut, tag);
213  if (min)
214  res = multiply(multiply(aut, min, min, tag), res, tag);
215  }
216  else
217  {
218  require(min <= max,
219  "multiply: invalid exponents: ", min, ", ", max);
220  if (min == 0)
221  {
222  //automatonset::one().
223  auto s = res->new_state();
224  res->set_initial(s);
225  res->set_final(s);
226  }
227  else
228  {
229  auto tag_aut = detail::make_join_automaton(tag, aut);
230  copy_into(aut, res);
231  copy_into(aut, tag_aut);
232  for (int n = 1; n < min; ++n)
233  res = multiply(res, tag_aut, tag);
234  }
235  if (min < max)
236  {
237  // Aut sum = automatonset.one();
238  auto sum = detail::make_join_automaton(tag, aut);
239  {
240  auto s = sum->new_state();
241  sum->set_initial(s);
242  sum->set_final(s);
243  }
244  for (int n = 1; n <= max - min; ++n)
245  sum = vcsn::sum(sum, multiply(aut, n, n, tag), tag);
246  res = vcsn::multiply(res, sum, tag);
247  }
248  }
249  return res;
250  }
251 
252  namespace dyn
253  {
254  namespace detail
255  {
257  template <Automaton Aut, typename Int1, typename Int2, typename String>
258  automaton
259  multiply_repeated(const automaton& a, int min, int max,
260  const std::string& algo)
261  {
262  const auto& aut = a->as<Aut>();
264  [aut, min, max](auto tag)
265  {
266  return make_automaton(::vcsn::multiply(aut, min, max, tag));
267  },
268  aut);
269  }
270  }
271  }
272 
273 
274  /*------------------------------------.
275  | multiply(expression, expression). |
276  `------------------------------------*/
277 
279  template <typename ValueSet>
280  typename ValueSet::value_t
281  multiply(const ValueSet& vs,
282  const typename ValueSet::value_t& lhs,
283  const typename ValueSet::value_t& rhs)
284  {
285  return vs.mul(lhs, rhs);
286  }
287 
288  namespace dyn
289  {
290  namespace detail
291  {
293  template <typename ExpSetLhs, typename ExpSetRhs>
294  expression
295  multiply_expression(const expression& lhs, const expression& rhs)
296  {
297  auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
298  return make_expression(std::get<0>(join_elts),
299  ::vcsn::multiply(std::get<0>(join_elts),
300  std::get<1>(join_elts),
301  std::get<2>(join_elts)));
302  }
303  }
304  }
305 
306  namespace dyn
307  {
308  namespace detail
309  {
311  template <typename ExpSetLhs, typename ExpSetRhs>
312  expression
314  {
315  auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
316  auto res = std::get<0>(join_elts).concat(std::get<1>(join_elts),
317  std::get<2>(join_elts));
318  return make_expression(std::get<0>(join_elts), res);
319  }
320  }
321  }
322 
323 
324  /*----------------------------------.
325  | multiply(expression, min, max). |
326  `----------------------------------*/
327 
328  template <typename ExpSet>
329  typename ExpSet::value_t
330  multiply(const ExpSet& rs, const typename ExpSet::value_t& r,
331  int min, int max)
332  {
333  typename ExpSet::value_t res;
334  if (min == -1)
335  min = 0;
336  if (max == -1)
337  {
338  res = rs.star(r);
339  if (min)
340  res = rs.mul(rs.power(r, min), res);
341  }
342  else
343  {
344  require(min <= max,
345  "multiply: invalid exponents: ", min, ", ", max);
346  res = rs.power(r, min);
347  if (min < max)
348  {
349  typename ExpSet::value_t sum = rs.one();
350  for (int n = 1; n <= max - min; ++n)
351  sum = rs.add(sum, rs.power(r, n));
352  res = rs.mul(res, sum);
353  }
354  }
355  return res;
356  }
357 
358  namespace dyn
359  {
360  namespace detail
361  {
363  template <typename ExpSet, typename Int1, typename Int2>
364  expression
365  multiply_expression_repeated(const expression& re, int min, int max)
366  {
367  const auto& r = re->as<ExpSet>();
368  return make_expression(r.expressionset(),
369  ::vcsn::multiply(r.expressionset(),
370  r.expression(),
371  min, max));
372  }
373  }
374  }
375 
376 
377  /*--------------------------.
378  | multiply(label, label). |
379  `--------------------------*/
380 
381  namespace dyn
382  {
383  namespace detail
384  {
386  template <typename LabelSetLhs, typename LabelSetRhs>
387  label
388  multiply_label(const label& lhs, const label& rhs)
389  {
390  const auto& l = lhs->as<LabelSetLhs>();
391  const auto& r = rhs->as<LabelSetRhs>();
392  auto rs = join(l.labelset(), r.labelset());
393  auto lr = rs.conv(l.labelset(), l.label());
394  auto rr = rs.conv(r.labelset(), r.label());
395  return make_label(rs, multiply(rs, lr, rr));
396  }
397  }
398  }
399 
400 
401  /*------------------------------------.
402  | multiply(polynomial, polynomial). |
403  `------------------------------------*/
404 
405  namespace dyn
406  {
407  namespace detail
408  {
410  template <typename PolynomialSetLhs, typename PolynomialSetRhs>
411  polynomial
412  multiply_polynomial(const polynomial& lhs, const polynomial& rhs)
413  {
414  auto join_elts = join<PolynomialSetLhs, PolynomialSetRhs>(lhs, rhs);
415  return make_polynomial(std::get<0>(join_elts),
416  multiply(std::get<0>(join_elts),
417  std::get<1>(join_elts),
418  std::get<2>(join_elts)));
419  }
420  }
421  }
422 
423  /*----------------------------.
424  | multiply(weight, weight). |
425  `----------------------------*/
426 
427  namespace dyn
428  {
429  namespace detail
430  {
432  template <typename WeightSetLhs, typename WeightSetRhs>
433  weight
434  multiply_weight(const weight& lhs, const weight& rhs)
435  {
436  const auto& l = lhs->as<WeightSetLhs>();
437  const auto& r = rhs->as<WeightSetRhs>();
438  auto ws = join(l.weightset(), r.weightset());
439  auto lw = ws.conv(l.weightset(), l.weight());
440  auto rw = ws.conv(r.weightset(), r.weight());
441  return make_weight(ws, ::vcsn::multiply(ws, lw, rw));
442  }
443 
445  template <typename WeightSet, typename Int1, typename Int2>
446  weight
447  multiply_weight_repeated(const weight& wgt, int min, int max)
448  {
449  const auto& w = wgt->as<WeightSet>();
450  return make_weight(w.weightset(),
451  ::vcsn::multiply(w.weightset(),
452  w.weight(),
453  min, max));
454  }
455  }
456  }
457 }
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
Definition: automaton.hh:137
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
A dyn automaton.
Definition: automaton.hh:19
std::shared_ptr< const detail::polynomial_base > polynomial
Definition: fwd.hh:53
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:57
label make_label(const LabelSet &ls, const typename LabelSet::value_t &l)
Definition: label.hh:80
auto star(const Aut &aut, Tag tag={}) -> decltype(detail::make_join_automaton(tag, aut))
Star of an automaton.
Definition: star.hh:108
auto dispatch_tags(std::string algo, Operation op, Aut &&...auts)
Dispatch an operation between automata depending on their nature.
Definition: tags.hh:32
automaton multiply_repeated(const automaton &a, int min, int max, const std::string &algo)
Bridge (multiply).
Definition: multiply.hh:259
label multiply_label(const label &lhs, const label &rhs)
Bridge (multiply).
Definition: multiply.hh:388
Tag for operations on all automata.
Definition: tags.hh:22
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
Definition: expression.hh:97
context join(const context &c1, const context &c2)
Bridge.
detail::automaton automaton
Definition: automaton.hh:108
auto make_join_automaton(deterministic_tag, Auts &&...auts)
Make an empty automaton which is a supertype of others.
Definition: tags.hh:78
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:37
Tag for operations on standard automata.
Definition: tags.hh:25
weightset_mixin< detail::b_impl > b
Definition: fwd.hh:48
detail::copier< AutIn, AutOut > make_copier(const AutIn &in, AutOut &out, bool safe=true)
Build an automaton copier.
Definition: copy.hh:249
auto copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans) -> decltype(keep_state(input->null_state()), keep_trans(input->null_transition()), make_fresh_automaton< AutIn, AutOut >(input))
A copy of input keeping only its states that are accepted by keep_state, and transitions accepted by ...
Definition: copy.hh:308
auto multiply(const Aut1 &lhs, const Aut2 &rhs, Tag tag={}) -> decltype(lhs->null_state(), detail::make_join_automaton(tag, lhs, rhs))
Concatenate two automata, general case.
Definition: multiply.hh:151
automaton multiply(const automaton &lhs, const automaton &rhs, const std::string &algo)
Bridge.
Definition: multiply.hh:168
auto final_transitions(const Aut &aut) -> decltype(aut->all_in(aut->post()))
Indexes of transitions from (visible) final states.
Definition: automaton.hh:148
auto rs
Definition: lift.hh:151
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
Definition: vector.hh:20
expression multiply_expression(const expression &lhs, const expression &rhs)
Bridge (multiply).
Definition: multiply.hh:295
Aut1 & multiply_here(Aut1 &res, const Aut2 &b, deterministic_tag)
Append automaton b to res.
Definition: multiply.hh:34
auto sum(const Aut1 &lhs, const Aut2 &rhs, Tag tag={}) -> decltype(join_automata(lhs, rhs))
The sum of two automata.
Definition: sum.hh:95
auto map(const std::tuple< Ts... > &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
Definition: tuple.hh:160
void copy_into(const AutIn &in, AutOut &out, KeepState keep_state, KeepTrans keep_trans)
Copy selected states and transitions of an automaton.
Definition: copy.hh:260
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
Definition: automaton.hh:105
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:78
std::shared_ptr< const detail::weight_base > weight
Definition: fwd.hh:71
weight multiply_weight_repeated(const weight &wgt, int min, int max)
Bridge (multiply).
Definition: multiply.hh:447
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
Definition: polynomial.hh:103
weight make_weight(const WeightSet &ws, const typename WeightSet::value_t &w)
Definition: weight.hh:79
expression concatenate_expression(const expression &lhs, const expression &rhs)
Bridge (concatenate).
Definition: multiply.hh:313
ExpSet::value_t multiply(const ExpSet &rs, const typename ExpSet::value_t &r, int min, int max)
Definition: multiply.hh:330
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
std::shared_ptr< const detail::label_base > label
Definition: fwd.hh:44
Tag for operations on deterministic automata.
Definition: tags.hh:19
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:113
auto determinize(const Aut &a, Tag={}, bool_constant< Lazy >={})
Definition: determinize.hh:246
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:56
polynomial multiply_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (multiply).
Definition: multiply.hh:412
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:39
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:55
weight multiply_weight(const weight &lhs, const weight &rhs)
Bridge (multiply).
Definition: multiply.hh:434
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:92
expression multiply_expression_repeated(const expression &re, int min, int max)
Bridge (multiply).
Definition: multiply.hh:365
Definition: a-star.hh:8