Vcsn  2.4
Be Rational
expansionset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vcsn/algos/project.hh> // project
4 #include <vcsn/algos/split.hh> // expression_polynomialset_t
5 #include <vcsn/misc/map.hh>
6 #include <vcsn/misc/static-if.hh>
7 
8 namespace vcsn
9 {
10 
11  namespace rat
12  {
13 
14  /*---------------.
15  | expansionset. |
16  `---------------*/
17 
18  template <typename ExpSet>
19  struct expansionset
20  {
21  public:
22  using expressionset_t = ExpSet;
27  using expression_t = typename expressionset_t::value_t;
29  using weight_t = typename weightset_t::value_t;
30 
33  using monomial_t = typename polynomialset_t::monomial_t;
34 
35  constexpr static const char* me() { return "expansion"; }
36 
37  // Keep it sorted to ensure determinism, and better looking
38  // results. Anyway, rough benches show no difference between
39  // map and unordered_map here.
40  using polys_t = std::map<label_t, polynomial_t, vcsn::less<labelset_t>>;
41 
43  struct value_t
44  {
47  };
48 
50  : rs_(rs)
51  {}
52 
54  static symbol sname()
55  {
56  static auto res
57  = symbol{"expansionset<" + expressionset_t::sname() + '>'};
58  return res;
59  }
60 
63  {
64  return rs_;
65  }
66 
69  {
70  return ps_;
71  }
72 
74  const context_t& context() const
75  {
76  return rs_.context();
77  }
78 
80  std::ostream& print_set(std::ostream& o, format fmt = {}) const
81  {
82  switch (fmt.kind())
83  {
84  case format::latex:
85  o << "\\mathsf{Expansion}[";
86  rs_.print_set(o, fmt);
87  o << ']';
88  break;
89  case format::sname:
90  o << "expansionset<";
91  rs_.print_set(o, fmt);
92  o << ">";
93  break;
94  case format::text:
95  case format::utf8:
96  o << "Expansion[";
97  rs_.print_set(o, fmt);
98  o << ']';
99  break;
100  case format::raw:
101  assert(0);
102  break;
103  }
104  return o;
105  }
106 
108  std::ostream& print(const value_t& v, std::ostream& o,
109  format fmt = {}) const
110  {
111  bool first = true;
112  if (!ws_.is_zero(v.constant) || v.polynomials.empty())
113  {
114  o << (fmt == format::latex ? "\\left\\langle "
115  : fmt == format::utf8 ? "⟨"
116  : "<");
117  ws_.print(v.constant, o, fmt.for_weights());
118  o << (fmt == format::latex ? "\\right\\rangle "
119  : fmt == format::utf8 ? "⟩"
120  : ">");
121  first = false;
122  }
123  for (const auto& p: v.polynomials)
124  {
125  if (!first)
126  o << (fmt == format::latex ? " \\oplus "
127  : fmt == format::utf8 ? " ⊕ "
128  : " + ");
129  first = false;
130  ls_.print(p.first, o, fmt.for_labels());
131  o << (fmt == format::latex ? " \\odot \\left["
132  : fmt == format::utf8 ? "⊙["
133  : ".[");
134  ps_.print(p.second, o, fmt);
135  o << (fmt == format::latex ? "\\right]"
136  : fmt == format::utf8 ? "]"
137  : "]");
138  }
139  return o;
140  }
141 
144  {
146  return normalize_(res, has_one);
147  }
148 
154  value_t& normalize_(value_t& res, std::true_type) const
155  {
156  auto one = ls_.one();
157  auto i = res.polynomials.find(one);
158  if (i != std::end(res.polynomials))
159  {
160  auto j = i->second.find(rs_.one());
161  if (j != std::end(i->second))
162  {
163  res.constant = ws_.add(res.constant, weight_of(*j));
164  i->second.erase(j);
165  if (i->second.empty())
166  res.polynomials.erase(i);
167  }
168  }
169  return res;
170  }
171 
173  value_t& normalize_(value_t& res, std::false_type) const
174  {
175  return res;
176  }
177 
180  {
182  return denormalize_(res, has_one);
183  }
184 
187  value_t& denormalize_(value_t& res, std::true_type) const
188  {
189  if (!ws_.is_zero(res.constant))
190  {
191  auto one = ls_.one();
192  ps_.add_here(res.polynomials[one],
193  polynomial_t{{rs_.one(), res.constant}});
194  res.constant = ws_.zero();
195  }
196  return res;
197  }
198 
200  value_t& denormalize_(value_t& res, std::false_type) const
201  {
202  return res;
203  }
204 
205  /*--------.
206  | Conv. |
207  `--------*/
208 
210  static value_t
211  conv(self_t, const value_t& v)
212  {
213  return v;
214  }
215 
217  template <typename OtherExpSet>
218  value_t
220  const typename expansionset<OtherExpSet>::value_t& v) const
221  {
222  const auto& other_ws = other.expressionset().weightset();
223  const auto& other_ps = other.polynomialset();
224  return {ws_.conv(other_ws, v.constant),
225  ps_.conv(other_ps, v.polynomials)};
226  }
227 
229  value_t zero() const
230  {
231  return {ws_.zero(), polys_t{}};
232  }
233 
235  value_t one() const
236  {
237  return {ws_.one(), polys_t{}};
238  }
239 
241  value_t atom(const label_t& l) const
242  {
243  return {ws_.zero(), {{l, ps_.one()}}};
244  }
245 
247  void add_here(value_t& lhs, const value_t& rhs) const
248  {
249  lhs.constant = ws_.add(lhs.constant, rhs.constant);
250  for (const auto& p: rhs.polynomials)
251  ps_.add_here(lhs.polynomials[p.first], p.second);
252  }
253 
255  value_t add(const value_t& lhs, const value_t& rhs) const
256  {
257  value_t res = lhs;
258  add_here(res, rhs);
259  return res;
260  }
261 
263  value_t lweight(const weight_t& w, const value_t& rhs) const
264  {
265  value_t res = rhs;
266  lweight_here(w, res);
267  return res;
268  }
269 
271  value_t& lweight_here(const weight_t& w, value_t& res) const
272  {
273  res.constant = ws_.mul(w, res.constant);
274  for (auto& p: res.polynomials)
275  p.second = ps_.lweight(w, p.second);
276  return res;
277  }
278 
280  value_t rweight(const value_t& lhs, const weight_t& w) const
281  {
282  value_t res = {ws_.mul(lhs.constant, w), polys_t{}};
283  for (auto& p: lhs.polynomials)
284  for (const auto& m: p.second)
285  ps_.add_here(res.polynomials[p.first],
286  rs_.rweight(label_of(m), w), weight_of(m));
287  return res;
288  }
289 
291  value_t& rweight_here(value_t& res, const expression_t& rhs) const
292  {
293  for (auto& p: res.polynomials)
294  p.second = ps_.rmul_label(p.second, rhs);
295  return res;
296  }
297 
299  value_t& ldivide_here(const weight_t& w, value_t& res) const
300  {
301  res.constant = ws_.ldivide(w, res.constant);
302  for (auto& p: res.polynomials)
303  for (auto&& m: p.second)
304  weight_set(m, ws_.ldivide(w, weight_of(m)));
305  return normalize(res);
306  }
307 
308  private:
309  template <typename Conjunction>
310  void
312  const value_t&, const value_t&,
313  std::false_type,
314  Conjunction) const
315  {}
316 
317  template <typename Conjunction>
318  void
320  const value_t& l, const value_t& r,
321  std::true_type,
322  Conjunction conjunction) const
323  {
324  // Spontaneous transitions from the lhs.
325  auto one = ls_.one();
326  {
327  auto i = l.polynomials.find(one);
328  if (i != std::end(l.polynomials))
329  for (const auto& rhs: r.polynomials)
330  if (!ls_.is_one(rhs.first))
331  ps_.add_here(res.polynomials[one],
332  conjunction(i->second,
333  ps_.lmul_label(rs_.atom(rhs.first),
334  rhs.second)));
335  }
336  // Spontaneous transitions from the rhs.
337  {
338  auto i = r.polynomials.find(one);
339  if (i != std::end(r.polynomials))
340  for (const auto& lhs: l.polynomials)
341  if (!ls_.is_one(lhs.first))
342  ps_.add_here(res.polynomials[one],
343  conjunction(ps_.lmul_label(rs_.atom(lhs.first),
344  lhs.second),
345  i->second));
346  }
347  }
348 
352  template <typename LabelSet = labelset_t, typename Conjunction>
353  auto conjunction_(value_t l, value_t r,
354  Conjunction conjunction) const
355  -> std::enable_if_t<detail::is_letterized_t<LabelSet>{},
356  value_t>
357  {
358  value_t res = zero();
359  denormalize(l);
360  denormalize(r);
361  res.constant = ws_.mul(l.constant, r.constant);
362  for (const auto& p: zip_maps(l.polynomials, r.polynomials))
363  res.polynomials[p.first]
364  = conjunction(std::get<0>(p.second), std::get<1>(p.second));
365 
367  conjunctions_with_one_(res, l, r, has_one, conjunction);
368  normalize(res);
369  return res;
370  }
371 
375  template <typename LabelSet = labelset_t, typename Conjunction>
376  auto conjunction_(const value_t& lhs, const value_t& rhs,
377  Conjunction conjunction) const
378  -> std::enable_if_t<!detail::is_letterized_t<LabelSet>{},
379  value_t>
380  {
381  value_t res = zero();
382  res.constant = ws_.mul(lhs.constant, rhs.constant);
383  for (const auto& l: lhs.polynomials)
384  for (const auto& r: rhs.polynomials)
385  {
386  // The longest common prefix.
387  auto lcp = ls_.lgcd(l.first, r.first);
388  if (!ls_.is_one(lcp))
389  {
390  auto left = rs_.atom(ls_.ldivide(lcp, l.first));
391  auto right = rs_.atom(ls_.ldivide(lcp, r.first));
392  ps_.add_here(res.polynomials[lcp],
393  conjunction(ps_.lmul_label(left, l.second),
394  ps_.lmul_label(right, r.second)));
395  }
396  }
397  return res;
398  }
399 
401  template <typename Shuffle>
402  value_t& shuffle_(value_t& res,
403  const value_t& lhs_xpn, const expression_t& lhs_xpr,
404  const value_t& rhs_xpn, const expression_t& rhs_xpr,
405  Shuffle shuffle) const
406  {
407  // (i) lhs_xpn:rhs_xpr.
408  for (const auto& p: lhs_xpn.polynomials)
409  for (const auto& m: p.second)
410  ps_.add_here(res.polynomials[p.first],
411  shuffle(label_of(m), rhs_xpr), weight_of(m));
412  // (ii) lhs_xpr:rhs_xpn
413  for (const auto& p: rhs_xpn.polynomials)
414  for (const auto& m: p.second)
415  ps_.add_here(res.polynomials[p.first],
416  shuffle(lhs_xpr, label_of(m)), weight_of(m));
417 
418  return res;
419  }
420 
421  public:
423  value_t conjunction(const value_t& l, const value_t& r) const
424  {
425  return conjunction_(l, r,
426  [this](const polynomial_t& l,
427  const polynomial_t& r)
428  {
429  return ps_.conjunction(l, r);
430  });
431  }
432 
436  value_t shuffle(const value_t& de, const expression_t& e,
437  const value_t& df, const expression_t& f) const
438  {
439  value_t res;
440  res.constant = ws_.mul(de.constant, df.constant);
441  return shuffle_(res,
442  de, e, df, f,
443  [this](const expression_t& l, const expression_t& r)
444  {
445  return rs_.shuffle(l, r);
446  });
447  }
448 
450  value_t infiltrate(const value_t& de, const expression_t& e,
451  const value_t& df, const expression_t& f) const
452  {
453  // Conjunction part: de&:df.
454  value_t res =
455  conjunction_(de, df,
456  [this](const polynomial_t& l, const polynomial_t& r)
457  {
458  return ps_.infiltrate(l, r);
459  });
460 
461  // Shuffle part: de&:f + e&:df.
462  shuffle_(res,
463  de, e, df, f,
464  [this](const expression_t& l, const expression_t& r)
465  {
466  return rs_.infiltrate(l, r);
467  });
468  return res;
469  }
470 
471  /*--------------.
472  | complement. |
473  `--------------*/
474 
476  value_t complement(const value_t& v) const
477  {
478  // We need an expansion whose firsts are letters. However,
479  // requiring a free labelset, i.e., rulling out lan, is too
480  // demanding, since, for instance, to compute {\} requires lan
481  // instead of lal.
482  //
483  // So require a letterized labelset.
484  return complement_<detail::is_letterized_t<labelset_t>{}>(v);
485  }
486 
487  private:
489  template <bool IsLetterized>
490  std::enable_if_t<!IsLetterized, value_t>
491  complement_(const value_t&) const
492  {
493  raise(me(),
494  ": complement: labelset must be letterized: ", ls_);
495  }
496 
498  template <bool IsLetterized>
499  std::enable_if_t<IsLetterized, value_t>
500  complement_(const value_t& v) const
501  {
502  value_t res;
503  res.constant = ws_.is_zero(v.constant) ? ws_.one() : ws_.zero();
504 
505  detail::static_if<labelset_t::has_one()>
506  ([this](const auto& v, const auto& ls)
507  {
508  require(!has(v.polynomials, ls.one()),
509  me(), ": complement: expansion must be normalized: ",
510  to_string(*this, v));
511  })(v, ls_);
512 
513  // Turn the polynomials into expressions, and complement them.
514  // The static-if is made of oneset.
515  detail::static_if<detail::has_generators_mem_fn<labelset_t>{}>
516  ([this, &res](const auto& v, const auto& ls)
517  {
518  for (auto l: ls.generators())
519  {
520  auto i = v.polynomials.find(l);
521  res.polynomials[l] =
522  ps_.complement(i == end(v.polynomials)
523  ? ps_.zero() : i->second);
524  }
525  })(v, ls_);
526  return res;
527  }
528 
529  /*-----------.
530  | ldivide. |
531  `-----------*/
532 
533  public:
535  value_t transpose(const value_t& v) const
536  {
537  value_t res = {ws_.transpose(v.constant), polys_t{}};
538  for (const auto& p: v.polynomials)
539  {
540  VCSN_REQUIRE(ls_.is_one(p.first),
541  *this, ": cannot transpose an expansion "
542  "with proper firsts: ", to_string(*this, v));
543  res.polynomials[p.first] = ps_.transpose(p.second);
544  }
545  return res;
546  }
547 
548  value_t ldivide(value_t lhs, value_t rhs) const
549  {
550  value_t res = zero();
551  denormalize(lhs);
552  denormalize(rhs);
553  auto one = detail::label_one(ls_);
554  auto& res_one = res.polynomials[one];
555 
556  // ε⊙[X_a \ Y_a + ...] for common firsts, included ε.
557  for (const auto& p: zip_maps(lhs.polynomials, rhs.polynomials))
558  ps_.add_ldivide_here(res_one,
559  std::get<0>(p.second),
560  std::get<1>(p.second));
561 
562  // If ε ∈ f(X) then ε⊙[X_ε \ (b Y_b) + ...]
563  if (has(lhs.polynomials, one))
564  for (const auto& rhsp: rhs.polynomials)
565  if (!ls_.is_one(rhsp.first))
566  ps_.add_ldivide_here(res_one,
567  lhs.polynomials[one],
568  ps_.lmul_label(rs_.atom(rhsp.first),
569  rhsp.second));
570 
571  // If ε ∈ f(Y) then ε⊙[(a X_a) \ Y_ε + ...]
572  if (has(rhs.polynomials, one))
573  for (const auto& lhsp: lhs.polynomials)
574  if (!ls_.is_one(lhsp.first))
575  ps_.add_ldivide_here(res_one,
576  ps_.lmul_label(rs_.atom(lhsp.first),
577  lhsp.second),
578  rhs.polynomials[one]);
579 
580  // It was handy to use res_one, but if it's zero, then remove it.
581  if (ps_.is_zero(res_one))
582  res.polynomials.erase(one);
583  normalize(res);
584  return res;
585  }
586 
587  public:
589  value_t
590  determinize(const value_t& v) const
591  {
592  value_t res;
593  res.constant = v.constant;
594  for (const auto& lp: v.polynomials)
595  res.polynomials[lp.first] = {ps_.determinize(lp.second)};
596  return res;
597  }
598 
599  /*---------------.
600  | tuple(v...). |
601  `---------------*/
602 
604  template <unsigned Tape>
605  using project_t
607 
609  template <unsigned Tape>
610  auto project() const
611  -> project_t<Tape>
612  {
613  return {rs_.template project<Tape>()};
614  }
615 
617  template <typename... Expansions>
618  struct tuple_impl
619  {
622  template <size_t Tape>
623  auto denormalize_tape(const typename project_t<Tape>::value_t& e) const
624  -> typename project_t<Tape>::polys_t
625  {
626  auto es = eset_.template project<Tape>();
627  auto res = e;
628  es.denormalize(res);
629  VCSN_REQUIRE(es.expressionset().weightset()->is_zero(res.constant),
630  es, ": to-expansion: cannot denormalize ",
631  to_string(es, res),
632  ", need support for label one (the empty label)");
633  return res.polynomials;
634  }
635 
637  template <size_t... Tape>
638  auto denormalize(std::tuple<const Expansions&...>& es,
640  -> std::tuple<typename project_t<Tape>::polys_t...>
641  {
642  using res_t = std::tuple<typename project_t<Tape>::polys_t...>;
643  return res_t{denormalize_tape<Tape>(std::get<Tape>(es))...};
644  }
645 
647  auto denormalize(const Expansions&... es) const
648  {
649  auto t = std::tuple<const Expansions&...>{es...};
650  constexpr auto indices
651  = detail::make_index_sequence<sizeof...(Expansions)>{};
652  return denormalize(t, indices);
653  }
654 
655  auto
656  tuple(Expansions&&... es) const
657  -> value_t
658  {
659  auto res = eset_.zero();
660  auto polys = denormalize(std::forward<Expansions>(es)...);
662  ([&res, this](const auto&... ps)
663  {
664  auto l = label_t{ps.first...};
665  eset_.ps_.add_here(res.polynomials[l],
666  eset_.ps_.tuple(ps.second...));
667  },
668  polys);
669  eset_.normalize(res);
670  return res;
671  }
672 
674  };
675 
730  template <typename... Expansions>
731  auto
732  tuple(Expansions&&... es) const
733  -> value_t
734  {
735  auto t = tuple_impl<Expansions...>{*this};
736  return t.tuple(std::forward<Expansions>(es)...);
737  }
738 
740  template <size_t Tape>
741  auto project(const value_t& v) const
742  {
743  auto xs = project<Tape>();
744  const auto& ps = xs.polynomialset();
745  using res_t = typename decltype(xs)::value_t;
746  auto res = res_t{};
747  res.constant = v.constant;
748  for (const auto& p: v.polynomials)
749  ps.add_here(res.polynomials[ls_.template project<Tape>(p.first)],
750  ps_.template project<Tape>(p.second));
751  // We might generate denormalized expansions, e.g., when
752  // projecting the expansion of `\e|a`, `\e` is a label.
753  xs.normalize(res);
754  return res;
755  }
756 
757  void
759  const value_t&, const value_t&,
760  std::false_type) const
761  {}
762 
763  void
764  compose_with_one_(value_t& res,
765  const value_t& l, const value_t& r,
766  std::true_type) const
767  {
768  // Handle lhs labels with one on the second tape.
769  {
770  for (const auto& lhs: l.polynomials)
771  if (ls_.template set<1>().is_one(std::get<1>(lhs.first)))
772  for (const auto& rhs: r.polynomials)
773  if (!ls_.template set<0>().is_one(std::get<0>(rhs.first)))
774  // a|\e . [P1] @ b|c . [P2] becomes a|\e . [P1 @ (b|c)P2]
775  ps_.add_here(res.polynomials[lhs.first],
776  ps_.compose(lhs.second,
777  ps_.lmul_label(rs_.atom(rhs.first),
778  rhs.second)));
779  }
780  // Handle rhs labels with one on the first tape.
781  {
782  for (const auto& rhs: r.polynomials)
783  if (ls_.template set<0>().is_one(std::get<0>(rhs.first)))
784  for (const auto& lhs: l.polynomials)
785  if (!ls_.template set<1>().is_one(std::get<1>(lhs.first)))
786  // a|b . [P1] @ \e|c . [P2] becomes \e|c . [(a|b)P1 @ P2]
787  ps_.add_here(res.polynomials[rhs.first],
788  ps_.compose(ps_.lmul_label(rs_.atom(lhs.first),
789  lhs.second),
790  rhs.second));
791  }
792  }
793 
795  template <typename Ctx = context_t>
796  auto compose(value_t l, value_t r) const
797  -> std::enable_if_t<are_composable<Ctx, Ctx>{}, value_t>
798  {
799  value_t res = zero();
800  denormalize(l);
801  denormalize(r);
802  res.constant = ws_.mul(l.constant, r.constant);
803  for (const auto& lm: l.polynomials)
804  for (const auto& rm: r.polynomials)
805  if (ls_.template set<0>().equal(std::get<1>(label_of(lm)),
806  std::get<0>(label_of(rm))))
807  {
808  auto l = ls_.tuple(std::get<0>(label_of(lm)),
809  std::get<1>(label_of(rm)));
810  ps_.add_here(res.polynomials[l],
811  ps_.compose(lm.second, rm.second));
812  }
813  auto has_one = bool_constant<context_t::has_one()>();
814  compose_with_one_(res, l, r, has_one);
815  normalize(res);
816  return res;
817  }
818 
819 
820  private:
824  const labelset_t& ls_ = *rs_.labelset();
826  const weightset_t& ws_ = *rs_.weightset();
829  };
830  }
831 
832  template <typename Context>
835  {
836  return {es};
837  }
838 
839  namespace detail
840  {
842  template <typename Ctx1, typename Ctx2>
845  {
847 
849  const expansionset<expressionset<Ctx2>>& rhs)
850  {
851  return type(vcsn::join(lhs.expressionset(), rhs.expressionset()));
852  }
853  };
854  }
855 }
value_t & ldivide_here(const weight_t &w, value_t &res) const
Inplace left-division by w of res.
constant< type_t::one, Context > one
Definition: fwd.hh:113
polynomialset_t ps_
The polynomialset for the polynomials.
STL namespace.
value_t add(const value_t &lhs, const value_t &rhs) const
Addition.
value_t conjunction(const value_t &l, const value_t &r) const
The conjunction of l and r.
auto tuple(Expansions &&...es) const -> value_t
The tuplization of single-tape expansions into a multitape expansion.
Print as is. For instance, don't try to escape labels.
Definition: format.hh:24
constant< type_t::zero, Context > zero
Definition: fwd.hh:110
Print as a parsable type string.
Definition: format.hh:26
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:173
value_t lweight(const weight_t &w, const value_t &rhs) const
Left-multiplication by w of rhs.
value_t & normalize_(value_t &res, std::false_type) const
Normalize when there is no label one: identity.
value_t rweight(const value_t &lhs, const weight_t &w) const
Right-multiplication of lhs by w.
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
Definition: split.hh:31
value_t ldivide(value_t lhs, value_t rhs) const
auto rs
Definition: lift.hh:152
return res
Definition: multiply.hh:398
void conjunctions_with_one_(value_t &, const value_t &, const value_t &, std::false_type, Conjunction) const
typename polynomialset_t::value_t polynomial_t
Definition: expansionset.hh:32
std::ostream & print(const value_t &v, std::ostream &o, format fmt={}) const
Print this expansion.
Print for LaTeX.
Definition: format.hh:22
expansionset< expressionset< Context > > make_expansionset(const expressionset< Context > &es)
variadic< type_t::conjunction, Context > conjunction
Definition: fwd.hh:142
Aut & lweight_here(const weight_t_of< Aut > &w, Aut &res, Tag tag={})
In place left-multiplication of an automaton by a weight.
Definition: weight.hh:118
auto compose(value_t l, value_t r) const -> std::enable_if_t< are_composable< Ctx, Ctx >
The composition of l and r.
value_t atom(const label_t &l) const
A single label.
const polynomialset_t & polynomialset() const
The polynomialset.
Definition: expansionset.hh:68
Aut1 & add_here(Aut1 &res, const Aut2 &b, standard_tag)
Merge transitions of b into those of res.
Definition: add.hh:28
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
An input/output format for valuesets.
Definition: format.hh:13
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
Definition: tuple.hh:301
value_t & denormalize_(value_t &res, std::true_type) const
Denormalize res move the constant to the polynomial associated to one.
weightset_t_of< expressionset_t > weightset_t
Definition: expansionset.hh:28
value_t infiltrate(const value_t &de, const expression_t &e, const value_t &df, const expression_t &f) const
The infiltration product of l and r.
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto conjunction_(const value_t &lhs, const value_t &rhs, Conjunction conjunction) const -> std::enable_if_t<!detail::is_letterized_t< LabelSet >
The conjunction of l and r.
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:62
std::map< label_t, polynomial_t, vcsn::less< labelset_t >> polys_t
Definition: expansionset.hh:40
typename polynomialset_t::monomial_t monomial_t
Definition: expansionset.hh:33
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
auto conjunction_(value_t l, value_t r, Conjunction conjunction) const -> std::enable_if_t< detail::is_letterized_t< LabelSet >
The conjunction of l and r.
value_t & denormalize(value_t &res) const
Move the constant to the polynomial associated to one.
value_t & lweight_here(const weight_t &w, value_t &res) const
Inplace left-multiplication by w of res.
static value_t conv(self_t, const value_t &v)
Conversion from (this and) other weightsets.
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
Definition: conjunction.hh:652
auto tuple(Expansions &&...es) const -> value_t
value_t complement(const value_t &v) const
The complement of v.
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:239
void compose_with_one_(value_t &res, const value_t &l, const value_t &r, std::true_type) const
value_t & denormalize_(value_t &res, std::false_type) const
Denormalize when there is no label one: identity.
Definition: a-star.hh:8
auto normalize(const Aut &a) -> decltype(copy(a))
Normalize a automaton.
Definition: normalize.hh:20
zipped_maps< Dereference, Maps... > zip_maps(Maps &&...maps)
Definition: zip-maps.hh:250
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
Definition: raise.hh:111
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
A structure that implements the computation of join(V1, V2).
Definition: join.hh:18
value_t & shuffle_(value_t &res, const value_t &lhs_xpn, const expression_t &lhs_xpr, const value_t &rhs_xpn, const expression_t &rhs_xpr, Shuffle shuffle) const
The shuffle product of l and r.
typename expressionset_t::value_t expression_t
Definition: expansionset.hh:27
auto denormalize_tape(const typename project_t< Tape >::value_t &e) const -> typename project_t< Tape >::polys_t
Denormalize on this tape: from expansion to pure polynomial.
std::enable_if_t<!IsLetterized, value_t > complement_(const value_t &) const
Complement on an invalid labelset.
Print as plain (ASCII) text, escaped.
Definition: format.hh:28
auto project() const -> project_t< Tape >
The expansionset for tape Tape.
value_t & normalize_(value_t &res, std::true_type) const
Normalize res.
labelset_t_of< context_t > labelset_t
Definition: expansionset.hh:25
auto denormalize(std::tuple< const Expansions &... > &es, detail::index_sequence< Tape... >) const -> std::tuple< typename project_t< Tape >::polys_t... >
Denormalize on all these tapes.
value_t zero() const
The zero.
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:55
auto project(const value_t &v) const
Project a multitape expansion.
const expressionset_t & expressionset() const
The expressionset.
Definition: expansionset.hh:62
std::integral_constant< bool, B > bool_constant
Definition: type_traits.hh:12
value_t transpose(const value_t &v) const
Transpose an expansion. The firsts must be reduced to one.
static type join(const expansionset< expressionset< Ctx1 >> &lhs, const expansionset< expressionset< Ctx2 >> &rhs)
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print this valueset.
Definition: expansionset.hh:80
An inner node with multiple children.
Definition: expression.hh:118
const labelset_t & ls_
Shorthand to the labelset.
return v
Definition: multiply.hh:361
expressionset_t rs_
The expressionset used for the expressions.
value_t & rweight_here(value_t &res, const expression_t &rhs) const
In place right multiplication by an expression.
value_t conv(const expansionset< OtherExpSet > &other, const typename expansionset< OtherExpSet >::value_t &v) const
Convert from another expansionset to self.
symbol sname()
Definition: name.hh:65
context_t_of< expressionset_t > context_t
Definition: expansionset.hh:24
void add_here(value_t &lhs, const value_t &rhs) const
In place addition.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:67
std::enable_if_t< IsLetterized, value_t > complement_(const value_t &v) const
Complement on a letterized labelset.
value_t shuffle(const value_t &de, const expression_t &e, const value_t &df, const expression_t &f) const
The shuffle product of de and df.
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
ATTRIBUTE_PURE bool has(const boost::container::flat_set< Key, Compare, Allocator > &s, const Key &e)
Whether e is member of s.
Definition: setalpha.hh:25
value_t & normalize(value_t &res) const
Normalize: move the constant term to the label one.
expansionset(const expressionset_t &rs)
Definition: expansionset.hh:49
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:802
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
const context_t & context() const
The context.
Definition: expansionset.hh:74
static constexpr const char * me()
Definition: expansionset.hh:35
typename weightset_t::value_t weight_t
Definition: expansionset.hh:29
void compose_with_one_(value_t &, const value_t &, const value_t &, std::false_type) const
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
Denormalize a pack of one-tape expansions.
auto denormalize(const Expansions &...es) const
Entry point: Denormalize all these expansions.
value_t one() const
The one.
const weightset_t & ws_
Shorthand to the weightset.
std::string to_string(identities i)
Wrapper around operator<<.
Definition: identities.cc:42
static symbol sname()
The static name.
Definition: expansionset.hh:54
value_t determinize(const value_t &v) const
Turn the polynomials into (normalized) monomials.
void conjunctions_with_one_(value_t &res, const value_t &l, const value_t &r, std::true_type, Conjunction conjunction) const
void weight_set(welement< Label, Weight > &m, const Weight &w)
Set the weight of a welement.
Definition: wet.hh:162