Vcsn  2.1
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>
6 #include <vcsn/algos/standard.hh>
7 #include <vcsn/algos/star.hh>
8 #include <vcsn/algos/sum.hh>
10 #include <vcsn/core/join.hh>
12 #include <vcsn/dyn/automaton.hh> // dyn::make_automaton
13 #include <vcsn/dyn/label.hh>
14 #include <vcsn/dyn/polynomial.hh>
15 #include <vcsn/dyn/weight.hh>
16 #include <vcsn/misc/raise.hh> // require
17 #include <vcsn/misc/vector.hh> // make_vector
18 
19 namespace vcsn
20 {
21  /*----------------------------------.
22  | multiply(automaton, automaton). |
23  `----------------------------------*/
24 
29  template <typename A, typename B>
30  A&
31  multiply_here(A& res, const B& b)
32  {
33  require(is_standard(res), __func__, ": lhs must be standard");
34  require(is_standard(b), __func__, ": rhs must be standard");
35 
36  const auto& ls = *res->labelset();
37  const auto& bls = *b->labelset();
38  const auto& ws = *res->weightset();
39  const auto& bws = *b->weightset();
40 
41  // The set of the current (left-hand side) final transitions.
42  // Store these transitions by copy.
43  auto ftr = detail::make_vector(res->final_transitions());
44 
45  state_t_of<B> b_initial = b->dst_of(b->initial_transitions().front());
46 
47  auto copy = make_copier(b, res);
48  copy(// The initial state of b is not copied.
49  [b_initial](state_t_of<B> s) { return s != b_initial; },
50  // Import all the B transitions, except the initial ones (and
51  // those from its (genuine) initial state).
52  [b] (transition_t_of<B> t) { return b->src_of(t) != b->pre(); });
53  const auto& map = copy.state_map();
54 
55  // Branch all the final transitions of res to the successors of
56  // b's initial state.
57  for (auto t1: ftr)
58  {
59  // Remove the previous final transition first, as we might add
60  // a final transition for the same state later.
61  //
62  // For instance on "<2>a+(<3>\e+<5>a)", the final state s1 of
63  // <2>a will be made final thanks to <3>\e. So if we compute
64  // the new transitions from s1 and then remove t1, we will
65  // have removed the fact that s1 is final thanks to <3>\e.
66  //
67  // Besides, s1 will become final with weight <3>, which might
68  // interfere with <5>a too.
69  auto s1 = res->src_of(t1);
70  auto w1 = res->weight_of(t1);
71  res->del_transition(t1);
72  for (auto t2: b->all_out(b_initial))
73  res->set_transition(s1,
74  map.at(b->dst_of(t2)),
75  ls.conv(bls, b->label_of(t2)),
76  ws.mul(w1,
77  ws.conv(bws, b->weight_of(t2))));
78  }
79  return res;
80  }
81 
83  template <typename A, typename B>
84  inline
85  auto
86  multiply(const A& lhs, const B& rhs)
87  -> decltype(join_automata(lhs, rhs))
88  {
89  require(is_standard(lhs), __func__, ": lhs must be standard");
90  require(is_standard(rhs), __func__, ": rhs must be standard");
91  auto res = join_automata(lhs, rhs);
92  ::vcsn::copy_into(lhs, res);
93  multiply_here(res, rhs);
94  return res;
95  }
96 
97  namespace dyn
98  {
99  namespace detail
100  {
102  template <typename Lhs, typename Rhs>
103  automaton
104  multiply(const automaton& lhs, const automaton& rhs)
105  {
106  const auto& l = lhs->as<Lhs>();
107  const auto& r = rhs->as<Rhs>();
108  return make_automaton(::vcsn::multiply(l, r));
109  }
110  }
111  }
112 
113  /*---------------------------------.
114  | multiply(automaton, min, max). |
115  `---------------------------------*/
116 
129  template <typename Aut>
130  auto
131  multiply(const Aut& aut, int min, int max)
132  -> typename Aut::element_type::template fresh_automaton_t<>
133  {
134  auto res = make_fresh_automaton(aut);
135  if (min == -1)
136  min = 0;
137  if (max == -1)
138  {
139  res = star(aut);
140  if (min)
141  res = multiply(multiply(aut, min, min), res);
142  }
143  else
144  {
145  if (min == 0)
146  {
147  // automatonset::one().
148  auto s = res->new_state();
149  res->set_initial(s);
150  res->set_final(s);
151  }
152  else
153  {
154  res = vcsn::copy(aut);
155  for (int n = 1; n < min; ++n)
156  res = multiply(res, aut);
157  }
158  if (min < max)
159  {
160  // Aut sum = automatonset.one();
161  auto sum = make_fresh_automaton(aut);
162  {
163  auto s = sum->new_state();
164  sum->set_initial(s);
165  sum->set_final(s);
166  }
167  for (int n = 1; n <= max - min; ++n)
168  sum = vcsn::sum(sum, multiply(aut, n, n));
169  res = vcsn::multiply(res, sum);
170  }
171  }
172  return res;
173  }
174 
175 
176 
177  namespace dyn
178  {
179  namespace detail
180  {
182  template <typename Aut, typename Int1, typename Int2>
183  automaton
184  multiply_repeated(const automaton& a, int min, int max)
185  {
186  const auto& aut = a->as<Aut>();
187  return make_automaton(::vcsn::multiply(aut, min, max));
188  }
189  }
190  }
191 
192 
193  /*------------------------------------.
194  | multiply(expression, expression). |
195  `------------------------------------*/
196 
198  template <typename ValueSet>
199  inline
200  typename ValueSet::value_t
201  multiply(const ValueSet& vs,
202  const typename ValueSet::value_t& lhs,
203  const typename ValueSet::value_t& rhs)
204  {
205  return vs.mul(lhs, rhs);
206  }
207 
208  namespace dyn
209  {
210  namespace detail
211  {
213  template <typename ExpSetLhs, typename ExpSetRhs>
214  expression
215  multiply_expression(const expression& lhs, const expression& rhs)
216  {
217  const auto& l = lhs->as<ExpSetLhs>();
218  const auto& r = rhs->as<ExpSetRhs>();
219  auto rs = vcsn::join(l.expressionset(), r.expressionset());
220  auto lr = rs.conv(l.expressionset(), l.expression());
221  auto rr = rs.conv(r.expressionset(), r.expression());
222  return make_expression(rs, ::vcsn::multiply(rs, lr, rr));
223  }
224  }
225  }
226 
227  namespace dyn
228  {
229  namespace detail
230  {
232  template <typename ExpSetLhs, typename ExpSetRhs>
233  expression
235  {
236  const auto& l = lhs->as<ExpSetLhs>();
237  const auto& r = rhs->as<ExpSetRhs>();
238  auto rs = vcsn::join(l.expressionset(), r.expressionset());
239  auto lr = rs.conv(l.expressionset(), l.expression());
240  auto rr = rs.conv(r.expressionset(), r.expression());
241  auto res = rs.concat(lr, rr);
242  return make_expression(rs, res);
243  }
244  }
245  }
246 
247 
248  /*----------------------------------.
249  | multiply(expression, min, max). |
250  `----------------------------------*/
251 
252  template <typename ExpSet>
253  typename ExpSet::value_t
254  multiply(const ExpSet& rs, const typename ExpSet::value_t& r,
255  int min, int max)
256  {
257  typename ExpSet::value_t res;
258  if (min == -1)
259  min = 0;
260  if (max == -1)
261  {
262  res = rs.star(r);
263  if (min)
264  res = rs.mul(rs.power(r, min), res);
265  }
266  else
267  {
268  require(min <= max,
269  "multiply: invalid exponent: ", min, ", ", max);
270  res = rs.power(r, min);
271  if (min < max)
272  {
273  typename ExpSet::value_t sum = rs.one();
274  for (int n = 1; n <= max - min; ++n)
275  sum = rs.add(sum, rs.power(r, n));
276  res = rs.mul(res, sum);
277  }
278  }
279  return res;
280  }
281 
282  namespace dyn
283  {
284  namespace detail
285  {
287  template <typename ExpSet, typename Int1, typename Int2>
288  expression
289  multiply_expression_repeated(const expression& re, int min, int max)
290  {
291  const auto& r = re->as<ExpSet>();
292  return make_expression(r.expressionset(),
293  ::vcsn::multiply(r.expressionset(),
294  r.expression(),
295  min, max));
296  }
297  }
298  }
299 
300 
301  /*--------------------------.
302  | multiply(label, label). |
303  `--------------------------*/
304 
305  namespace dyn
306  {
307  namespace detail
308  {
310  template <typename LabelSetLhs, typename LabelSetRhs>
311  label
312  multiply_label(const label& lhs, const label& rhs)
313  {
314  const auto& l = lhs->as<LabelSetLhs>();
315  const auto& r = rhs->as<LabelSetRhs>();
316  auto rs = join(l.labelset(), r.labelset());
317  auto lr = rs.conv(l.labelset(), l.label());
318  auto rr = rs.conv(r.labelset(), r.label());
319  return make_label(rs, multiply(rs, lr, rr));
320  }
321  }
322  }
323 
324 
325  /*------------------------------------.
326  | multiply(polynomial, polynomial). |
327  `------------------------------------*/
328 
329  namespace dyn
330  {
331  namespace detail
332  {
334  template <typename PolynomialSetLhs, typename PolynomialSetRhs>
335  polynomial
336  multiply_polynomial(const polynomial& lhs, const polynomial& rhs)
337  {
338  const auto& l = lhs->as<PolynomialSetLhs>();
339  const auto& r = rhs->as<PolynomialSetRhs>();
340  auto rs = join(l.polynomialset(), r.polynomialset());
341  auto lr = rs.conv(l.polynomialset(), l.polynomial());
342  auto rr = rs.conv(r.polynomialset(), r.polynomial());
343  return make_polynomial(rs, multiply(rs, lr, rr));
344  }
345  }
346  }
347 
348  /*----------------------------.
349  | multiply(weight, weight). |
350  `----------------------------*/
351 
352  namespace dyn
353  {
354  namespace detail
355  {
357  template <typename WeightSetLhs, typename WeightSetRhs>
358  weight
359  multiply_weight(const weight& lhs, const weight& rhs)
360  {
361  const auto& l = lhs->as<WeightSetLhs>();
362  const auto& r = rhs->as<WeightSetRhs>();
363  auto ws = join(l.weightset(), r.weightset());
364  auto lw = ws.conv(l.weightset(), l.weight());
365  auto rw = ws.conv(r.weightset(), r.weight());
366  return make_weight(ws, ::vcsn::multiply(ws, lw, rw));
367  }
368 
370  template <typename WeightSet, typename Int1, typename Int2>
371  weight
372  multiply_weight_repeated(const weight& wgt, int min, int max)
373  {
374  const auto& w = wgt->as<WeightSet>();
375  return make_weight(w.weightset(),
376  ::vcsn::multiply(w.weightset(),
377  w.weight(),
378  min, max));
379  }
380  }
381  }
382 }
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:215
automaton multiply_repeated(const automaton &a, int min, int max)
Bridge (multiply).
Definition: multiply.hh:184
std::shared_ptr< const detail::label_base > label
Definition: fwd.hh:59
weight multiply_weight_repeated(const weight &wgt, int min, int max)
Bridge (multiply).
Definition: multiply.hh:372
detail::copier< AutIn, AutOut > make_copier(const AutIn &in, AutOut &out)
Build an automaton copier.
Definition: copy.hh:116
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
Definition: copy.hh:239
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:48
weightset_mixin< detail::b_impl > b
Definition: fwd.hh:48
A & multiply_here(A &res, const B &b)
Append automaton b to res.
Definition: multiply.hh:31
ExpSet::value_t multiply(const ExpSet &rs, const typename ExpSet::value_t &r, int min, int max)
Definition: multiply.hh:254
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
AutOut copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans)
A copy of input keeping only its states that are accepted by keep_state.
Definition: copy.hh:254
std::shared_ptr< const detail::weight_base > weight
Definition: fwd.hh:86
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
Definition: polynomial.hh:88
bool is_standard(const Aut &a)
Whether a is standard.
Definition: standard.hh:27
expression concatenate_expression(const expression &lhs, const expression &rhs)
Bridge (concatenate).
Definition: multiply.hh:234
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
weight make_weight(const WeightSet &ws, const typename WeightSet::value_t &w)
Definition: weight.hh:79
fresh_automaton_t_of< Aut > star(const Aut &aut)
Star of a standard automaton.
Definition: star.hh:60
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
automaton multiply(const automaton &lhs, const automaton &rhs)
Bridge.
Definition: multiply.hh:104
polynomial multiply_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (multiply).
Definition: multiply.hh:336
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:126
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
weight multiply_weight(const weight &lhs, const weight &rhs)
Bridge (multiply).
Definition: multiply.hh:359
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:49
auto rs
Definition: lift.hh:151
std::shared_ptr< const detail::polynomial_base > polynomial
Definition: fwd.hh:68
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
Definition: expression.hh:83
label multiply_label(const label &lhs, const label &rhs)
Bridge (multiply).
Definition: multiply.hh:312
expression multiply_expression_repeated(const expression &re, int min, int max)
Bridge (multiply).
Definition: multiply.hh:289
auto sum(const A &lhs, const B &rhs) -> decltype(join_automata(lhs, rhs))
Definition: sum.hh:64
auto multiply(const A &lhs, const B &rhs) -> decltype(join_automata(lhs, rhs))
Concatenate two standard automata.
Definition: multiply.hh:86
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
An automaton whose type is the join between those of auts.
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:78
context join(const context &c1, const context &c2)
Bridge.
Definition: make-context.hh:92
label make_label(const LabelSet &ls, const typename LabelSet::value_t &l)
Definition: label.hh:80