Vcsn  2.2
Be Rational
polynomialset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <iostream>
5 #include <sstream>
6 #include <type_traits>
7 #include <vector>
8 
9 #include <boost/optional.hpp>
10 #include <boost/range/algorithm/equal.hpp>
11 #include <boost/range/algorithm/find_if.hpp>
12 #include <boost/range/algorithm/lexicographical_compare.hpp>
13 
14 #include <vcsn/ctx/context.hh> // We need context to define join.
16 #include <vcsn/ctx/traits.hh>
17 #include <vcsn/misc/algorithm.hh> // front
18 #include <vcsn/misc/attributes.hh>
19 #include <vcsn/misc/functional.hh>
20 #include <vcsn/misc/math.hh>
21 #include <vcsn/misc/raise.hh>
22 #include <vcsn/misc/star-status.hh>
23 #include <vcsn/misc/stream.hh>
24 #include <vcsn/misc/wet.hh>
25 #include <vcsn/misc/zip-maps.hh>
26 #include <vcsn/weightset/fwd.hh>
27 #include <vcsn/weightset/f2.hh>
28 #include <vcsn/weightset/z.hh>
29 
30 namespace vcsn
31 {
32  // http://llvm.org/bugs/show_bug.cgi?id=18571
33 #if defined __clang__
34 # pragma clang diagnostic push
35 # pragma clang diagnostic ignored "-Wunused-value"
36 #endif
37  template <typename LabelSet>
38  auto label_is_zero(const LabelSet& ls, const typename LabelSet::value_t* l)
39  -> decltype(ls.is_zero(l), bool())
40  {
41  return ls.is_zero(*l);
42  }
43 
44 #if defined __clang__
45 # pragma clang diagnostic pop
46 #endif
47 
48  template <typename LabelSet>
49  bool label_is_zero(const LabelSet&, ...)
50  ATTRIBUTE_CONST;
51 
52  template <typename LabelSet>
53  bool label_is_zero(const LabelSet&, ...)
54  {
55  return false;
56  }
57 
58  namespace detail
59  {
60  template <typename WeightSet>
62  : std::true_type
63  {};
64 
65  template <>
67  : std::false_type
68  {};
69 
70  template <typename Context, wet_kind_t Kind>
71  struct is_division_ring<polynomialset<Context, Kind>>
72  : std::false_type
73  {};
74 
77  template <typename Context, wet_kind_t Kind>
78  class polynomialset_impl
79  {
80  public:
82  using context_t = Context;
85 
86  using labelset_ptr = typename context_t::labelset_ptr;
87  using weightset_ptr = typename context_t::weightset_ptr;
89  using label_t = typename labelset_t::value_t;
91 
94  using monomial_t = typename value_t::value_type;
95 
96  polynomialset_impl() = delete;
97  polynomialset_impl(const polynomialset_impl&) = default;
100  : ctx_{ctx}
101  {}
102 
113  const self_t& self() const { return static_cast<const self_t&>(*this); }
114 
116  static symbol sname()
117  {
118  static auto res = symbol{"polynomialset<" + context_t::sname() + '>'};
119  return res;
120  }
121 
122  const context_t& context() const { return ctx_; }
123  const labelset_ptr& labelset() const { return ctx_.labelset(); }
124  const weightset_ptr& weightset() const { return ctx_.weightset(); }
125 
126  static constexpr bool is_commutative() { return false; }
127  static constexpr bool has_lightening_weights()
128  {
129  return weightset_t::has_lightening_weights();
130  }
131 
133  value_t&
134  del_weight(value_t& v, const label_t& l) const
135  {
136  v.erase(l);
137  return v;
138  }
139 
142  value_t&
143  new_weight(value_t& v, const label_t& l, const weight_t w) const
144  {
145  assert(!weightset()->is_zero(w));
146  v.set(l, w);
147  return v;
148  }
149 
151  value_t&
152  set_weight(value_t& v, const label_t& l, const weight_t w) const
153  {
154  if (weightset()->is_zero(w))
155  return del_weight(v, l);
156  else
157  return new_weight(v, l, w);
158  }
159 
160  const weight_t
161  get_weight(const value_t& v, const label_t& l) const ATTRIBUTE_PURE
162  {
163  auto i = v.find(l);
164  if (i == v.end())
165  return weightset()->zero();
166  else
167  return weight_of(*i);
168  }
169 
170 
171  /*---------.
172  | clear. |
173  `---------*/
174 
176  void clear(value_t& v)
177  {
178  v.clear();
179  }
180 
181 
182  /*-------.
183  | add. |
184  `-------*/
185 
187  value_t&
188  add_here(value_t& v, const label_t& l, const weight_t k) const
189  {
190  if (!label_is_zero(*labelset(), &l))
191  {
192  auto i = v.find(l);
193  if (i == v.end())
194  {
195  set_weight(v, l, k);
196  }
197  else
198  {
199  // Do not use set_weight() because it would lookup l
200  // again and we already have the right iterator.
201  auto w2 = weightset()->add(weight_of(*i), k);
202  if (weightset()->is_zero(w2))
203  v.erase(i);
204  else
205  v.set(i, w2);
206  }
207  }
208  return v;
209  }
210 
212  value_t&
213  add_here(value_t& v, const monomial_t& m) const
214  {
215  return add_here(v, label_of(m), weight_of(m));
216  }
217 
219  template <wet_kind_t WetType, typename WS>
220  auto
221  add_here_impl(value_t& l, const value_t& r) const
222  -> std::enable_if_t<WetType != wet_kind_t::bitset,
223  value_t&>
224  {
225  for (const auto& m: r)
226  add_here(l, m);
227  return l;
228  }
229 
231  template <wet_kind_t WetType, typename WS>
232  auto
233  add_here_impl(value_t& l, const value_t& r) const
234  -> std::enable_if_t<(WetType == wet_kind_t::bitset
235  && std::is_same<WS, b>::value),
236  value_t&>
237  {
238  l.set() |= r.set();
239  return l;
240  }
241 
243  template <wet_kind_t WetType, typename WS>
244  auto
245  add_here_impl(value_t& l, const value_t& r) const
246  -> std::enable_if_t<(WetType == wet_kind_t::bitset
247  && std::is_same<WS, f2>::value),
248  value_t&>
249  {
250  l.set() ^= r.set();
251  return l;
252  }
253 
254  value_t&
255  add_here(value_t& l, const value_t& r) const
256  {
257  return add_here_impl<value_t::kind, weightset_t>(l, r);
258  }
259 
261  value_t add(const value_t& l, const value_t& r) const
262  {
263  value_t res = l;
264  add_here(res, r);
265  return res;
266  }
267 
268 
269  /*-------.
270  | sub. |
271  `-------*/
272 
274  value_t&
275  sub_here(value_t& v, const monomial_t& m) const
276  {
277  if (!label_is_zero(*labelset(), &label_of(m)))
278  {
279  auto i = v.find(label_of(m));
280  if (i == v.end())
281  {
282  raise(sname(), ": sub_here: invalid arguments: ",
283  to_string(*this, v), ", ", to_string(*this, m));
284  }
285  else
286  {
287  // Do not use set_weight() because it would lookup w
288  // again and we already have the right iterator.
289  auto w2 = weightset()->sub(weight_of(*i), weight_of(m));
290  if (weightset()->is_zero(w2))
291  v.erase(i);
292  else
293  weight_set(*i, w2);
294  }
295  }
296  return v;
297  }
298 
300  value_t
301  sub(const value_t& l, const value_t& r) const
302  {
303  value_t res = l;
304  for (const auto& rm: r)
305  sub_here(res, rm);
306  return res;
307  }
308 
309 
310  /*-------.
311  | mul. |
312  `-------*/
313 
315  monomial_t
316  mul(const monomial_t& l, const monomial_t& r) const
317  {
318  return {labelset()->mul(label_of(l), label_of(r)),
319  weightset()->mul(weight_of(l), weight_of(r))};
320  }
321 
324  template <wet_kind_t WetType>
325  auto
326  mul_impl(const value_t& l, const value_t& r) const
327  -> std::enable_if_t<WetType != wet_kind_t::bitset,
328  value_t>
329  {
330  value_t res;
331  for (const auto& lm: l)
332  for (const auto& rm: r)
333  add_here(res,
334  labelset()->mul(label_of(lm), label_of(rm)),
335  weightset()->mul(weight_of(lm), weight_of(rm)));
336  return res;
337  }
338 
341  template <wet_kind_t WetType>
342  auto
343  mul_impl(const value_t& l, const value_t& r) const
344  -> std::enable_if_t<WetType == wet_kind_t::bitset,
345  value_t>
346  {
347  return l.set() & r.set();
348  }
349 
351  auto
352  mul(const value_t& l, const value_t& r) const
353  -> value_t
354  {
355  return mul_impl<value_t::kind>(l, r);
356  }
357 
359  auto
360  mul(const value_t& p, const label_t& l, const weight_t w) const
361  -> value_t
362  {
363  value_t res;
364  for (const auto& m: p)
365  add_here(res,
366  labelset()->mul(label_of(m), l),
367  weightset()->mul(weight_of(m), w));
368  return res;
369  }
370 
371 
372  /*---------------.
373  | conjunction. |
374  `---------------*/
375 
378  template <typename Ctx>
379  std::enable_if_t<Ctx::is_lar, value_t>
380  conjunction_impl(const value_t& l, const value_t& r) const
381  {
382  value_t res;
383  for (const auto& lm: l)
384  for (const auto& rm: r)
385  add_here(res,
386  labelset()->conjunction(label_of(lm), label_of(rm)),
387  weightset()->mul(weight_of(lm), weight_of(rm)));
388  return res;
389  }
390 
393  template <typename Ctx>
394  std::enable_if_t<!Ctx::is_lar, value_t>
395  conjunction_impl(const value_t& l, const value_t& r) const
396  {
397  value_t res;
398  for (const auto& p: zip_maps<vcsn::as_tuple>(l, r))
399  add_here(res,
400  label_of(std::get<0>(p)),
401  weightset()->mul(weight_of(std::get<0>(p)),
402  weight_of(std::get<1>(p))));
403  return res;
404  }
405 
406  value_t
407  conjunction(const value_t& l, const value_t& r) const
408  {
409  return conjunction_impl<context_t>(l, r);
410  }
411 
414  value_t
415  infiltration(const value_t& l, const value_t& r) const
416  {
417  value_t res;
418  for (const auto& lm: l)
419  for (const auto& rm: r)
420  add_here(res,
421  labelset()->infiltration(label_of(lm), label_of(rm)),
422  weightset()->mul(weight_of(lm), weight_of(rm)));
423  return res;
424  }
425 
428  template <wet_kind_t WetType = value_t::kind>
429  auto
430  scalar_product(const value_t& l, const value_t& r) const
431  -> std::enable_if_t<WetType != wet_kind_t::bitset,
432  weight_t>
433  {
434  auto res = weightset()->zero();
435  for (const auto& p: zip_maps<vcsn::as_tuple>(l, r))
436  res = weightset()->add(res,
437  weightset()->mul(weight_of(std::get<0>(p)),
438  weight_of(std::get<1>(p))));
439  return res;
440  }
441 
444  template <wet_kind_t WetType = value_t::kind, typename WS = weightset_t>
445  auto
446  scalar_product(const value_t& l, const value_t& r) const
447  -> std::enable_if_t<(WetType == wet_kind_t::bitset
448  && std::is_same<WS, b>::value),
449  weight_t>
450  {
451  return l.set().intersects(r.set());
452  }
453 
456  template <wet_kind_t WetType = value_t::kind, typename WS = weightset_t>
457  auto
458  scalar_product(const value_t& l, const value_t& r) const
459  -> std::enable_if_t<(WetType == wet_kind_t::bitset
460  && std::is_same<WS, f2>::value),
461  weight_t>
462  {
463  return (l.set() & r.set()).count() % 2;
464  }
465 
467  value_t
468  star(const value_t& v) const
469  {
470  // The only starrable polynomials are scalars (if they are
471  // starrable too).
472  auto s = v.size();
473  if (s == 0)
474  return one();
475  else if (s == 1)
476  {
477  auto i = v.find(labelset()->one());
478  if (i != v.end())
479  return {{i->first, weightset()->star(i->second)}};
480  }
481  raise(sname(), ": star: invalid value: ", to_string(*this, v));
482  }
483 
485  value_t
486  lmul(const weight_t w, const value_t& v) const
487  {
488  value_t res;
489  if (weightset()->is_one(w))
490  res = v;
491  else if (!weightset()->is_zero(w))
492  for (const auto& m: v)
493  add_here(res, label_of(m), weightset()->mul(w, weight_of(m)));
494  return res;
495  }
496 
498  value_t
499  lmul_label(const label_t& lhs, const value_t& v) const
500  {
501  value_t res;
502  for (const auto& m: v)
503  add_here(res,
504  labelset()->mul(lhs, label_of(m)),
505  weight_of(m));
506  return res;
507  }
508 
510  value_t
511  mul(const monomial_t& lhs, const value_t& v) const
512  {
513  value_t res;
514  for (const auto& m: v)
515  add_here(res,
516  labelset()->mul(label_of(lhs), label_of(m)),
517  weightset()->mul(weight_of(lhs), weight_of(m)));
518  return res;
519  }
520 
529  value_t
530  rmul(const value_t& v, const weight_t w) const
531  {
532  value_t res;
533  if (!weightset()->is_zero(w))
534  for (const auto& m: v)
535  add_here(res, labelset()->rmul(label_of(m), w), weight_of(m));
536  return res;
537  }
538 
540  value_t
541  rmul_label(const value_t& v, const label_t& rhs) const
542  {
543  value_t res;
544  for (const auto& lhs: v)
545  add_here(res,
546  labelset()->mul(label_of(lhs), rhs),
547  weight_of(lhs));
548  return res;
549  }
550 
552  value_t
553  mul(const value_t& l, const monomial_t& rhs) const
554  {
555  value_t res;
556  for (const auto& lhs: l)
557  add_here(res,
558  labelset()->mul(label_of(lhs), label_of(rhs)),
559  weightset()->mul(weight_of(lhs), weight_of(rhs)));
560  return res;
561  }
562 
563  value_t
564  rdiv(const value_t& l, const value_t& r) const
565  {
566  raise(sname(), ": rdiv: not implemented (",
567  to_string(*this, l), ", ", to_string(*this, r), ")");
568  }
569 
570  monomial_t
571  ldiv(const monomial_t& l, const monomial_t& r) const
572  {
573  return {labelset()->ldiv(label_of(l), label_of(r)),
574  weightset()->ldiv(weight_of(l), weight_of(r))};
575  }
576 
578  value_t
579  ldiv(const monomial_t& l, const value_t& r) const
580  {
581  value_t res;
582  for (const auto& m: r)
583  add_here(res, ldiv(l, m));
584  return res;
585  }
586 
587  value_t
588  ldiv(const value_t& l, const value_t& r) const
589  {
590  value_t res;
591  if (is_zero(l))
592  raise(sname(), ": ldiv: division by zero");
593  else
594  {
595  value_t remainder = r;
596 #if DEBUG
597  std::cerr << "ldiv(";
598  print(l, std::cerr) << ", ";
599  print(r, std::cerr) << "\n";
600 #endif
601  while (!is_zero(remainder))
602  {
603  auto factor = ldiv(detail::front(l), detail::front(remainder));
604 #if DEBUG
605  std::cerr << "factor = "; print(factor, std::cerr) << "\n";
606 #endif
607  add_here(res, factor);
608 #if DEBUG
609  std::cerr << "res = "; print(res, std::cerr) << "\n";
610  std::cerr << "sub = "; print(mul(l, factor), std::cerr) << "\n";
611 #endif
612  remainder = sub(remainder, mul(l, factor));
613 #if DEBUG
614  std::cerr << "rem = "; print(remainder, std::cerr) << "\n";
615 #endif
616  }
617 #if DEBUG
618  std::cerr << "ldiv(";
619  print(l, std::cerr) << ", ";
620  print(r, std::cerr) << ") = ";
621  print(res, std::cerr) << " rem: ";
622  print(remainder, std::cerr) << "\n";
623 #endif
624  if (!is_zero(remainder))
625  raise(sname(), ": ldiv: not implemented (",
626  to_string(*this, l), ", ", to_string(*this, r), ")");
627  }
628  return res;
629  }
630 
632  value_t&
633  ldiv_here(const weight_t w, value_t& v) const
634  {
635  if (!weightset()->is_one(w))
636  for (auto&& m: v)
637  weight_set(m, weightset()->ldiv(w, weight_of(m)));
638  return v;
639  }
640 
642  value_t&
643  rdiv_here(value_t& v, const weight_t w) const
644  {
645  if (!weightset()->is_one(w))
646  for (auto& m: v)
647  weight_set(m, weightset()->rdiv(weight_of(m), w));
648  return v;
649  }
650 
657  value_t lgcd(const value_t& lhs, const value_t& rhs) const
658  {
659  using std::begin;
660  using std::end;
661  value_t res;
662  // For each monomial, look for the matching GCD of the weight.
663  auto i = begin(lhs), i_end = end(lhs);
664  auto j = begin(rhs), j_end = end(rhs);
665  for (;
666  i != i_end && j != j_end
667  && labelset()->equal(i->first, j->first);
668  ++i, ++j)
669  res.set(i->first, weightset()->lgcd(i->second, j->second));
670  // If the sets of labels are different, the polynomials
671  // cannot be "colinear", and the GCD is just 1.
672  if (i != i_end || j != j_end)
673  res = one();
674  return res;
675  }
676 
677  /*--------.
678  | norm. |
679  `--------*/
680 
682  template <typename WeightSet, typename Dummy = void>
683  struct norm_
684  {
685  typename WeightSet::value_t operator()(const value_t& v) const
686  {
687  return weight_of(front(v));
688  }
689  const WeightSet& ws_;
690  };
691 
693  template <typename Dummy>
694  struct norm_<z, Dummy>
695  {
696  typename z::value_t operator()(const value_t& v) const
697  {
698  int sign = 0 < weight_of(detail::front(v)) ? 1 : -1;
699  auto res = abs(weight_of(detail::front(v)));
700  for (const auto& m: v)
701  res = z_.lgcd(res, abs(weight_of(m)));
702  res *= sign;
703  return res;
704  }
705  const z& z_;
706  };
707 
709  template <typename Ctx, wet_kind_t Knd, typename Dummy>
710  struct norm_<polynomialset<Ctx, Knd>, Dummy>
711  {
713 
714  typename ps_t::value_t operator()(const value_t& v) const
715  {
716  typename ps_t::value_t res = weight_of(detail::front(v));
717  for (const auto& p: v)
718  res = ps_.lgcd(res, weight_of(p));
719  return res;
720  }
721  const ps_t& ps_;
722  };
723 
726  auto norm(const value_t& v) const
727  -> weight_t
728  {
729  if (is_zero(v))
730  return weightset()->zero();
731  else
732  return norm_<weightset_t>{*weightset()}(v);
733  }
734 
735 
736  /*-------------.
737  | normalize. |
738  `-------------*/
739 
743  {
744  // Zero is in normal form, don't try to divide by zero.
745  auto res = norm(v);
746  if (!weightset()->is_zero(res))
747  ldiv_here(res, v);
748  return res;
749  }
750 
753  {
754  normalize_here(res);
755  return res;
756  }
757 
758 
759 
760  /*---------------.
761  | tuple(v...). |
762  `---------------*/
763 
766  template <typename... Polys>
767  auto
768  tuple(Polys&&... vs) const
769  -> value_t
770  {
771  auto res = value_t{};
772  detail::cross([&res, this](auto... ms)
773  {
774  this->add_here(res,
775  this->labelset()->tuple(ms.first...),
776  this->weightset()->mul(ms.second...));
777  },
778  std::forward<Polys>(vs)...);
779  return res;
780  }
781 
783  template <size_t Tape>
784  auto project(const value_t& v) const
785  {
786  auto ps = make_polynomialset(vcsn::detail::project<Tape>(context()));
787  auto res = typename decltype(ps)::value_t{};
788  for (const auto& m: v)
789  ps.add_here(res,
790  std::get<Tape>(label_of(m)),
791  weight_of(m));
792  return res;
793  }
794 
801  label_t to_label(const value_t& v) const
802  {
803  label_t res = labelset()->zero();
804  for (const auto& m: v)
805  res = labelset()->add(res,
806  labelset()->lmul(weight_of(m), label_of(m)));
807  return res;
808  }
809 
814  {
815  weight_t w = normalize_here(v);
816  return {to_label(v), w};
817  }
818 
822  value_t complement(const value_t& v) const
823  {
824  return {{labelset()->complement(to_label(normalize(v))),
825  weightset()->one()}};
826  }
827 
828  /*---------------.
829  | equal(l, r). |
830  `---------------*/
831 
832  ATTRIBUTE_PURE
833  static bool monomial_equal(const monomial_t& lhs,
834  const monomial_t& rhs)
835  {
836  return (labelset_t::equal(label_of(lhs), label_of(rhs))
837  && weightset_t::equal(weight_of(lhs), weight_of(rhs)));
838  }
839 
840  template <wet_kind_t WetType>
841  ATTRIBUTE_PURE
842  static auto
843  equal_impl(const value_t& l, const value_t& r)
844  -> std::enable_if_t<WetType != wet_kind_t::bitset,
845  bool>
846  {
847  return boost::equal(l, r, monomial_equal);
848  }
849 
850  template <wet_kind_t WetType>
851  ATTRIBUTE_PURE
852  static auto
853  equal_impl(const value_t& l, const value_t& r)
854  -> std::enable_if_t<WetType == wet_kind_t::bitset,
855  bool>
856  {
857  return l.set() == r.set();
858  }
859 
860  ATTRIBUTE_PURE
861  static bool
862  equal(const value_t& l, const value_t& r)
863  {
864  return equal_impl<value_t::kind>(l, r);
865  }
866 
868  static const value_t& one()
869  {
870  static value_t res{monomial_one()};
871  return res;
872  }
873 
875  static const monomial_t& monomial_one()
876  {
878  return res;
879  }
880 
882  static bool is_one(const value_t& v) ATTRIBUTE_PURE
883  {
884  if (v.size() != 1)
885  return false;
886  auto i = v.find(labelset_t::one());
887  if (i == v.end())
888  return false;
889  return weightset_t::is_one(i->second);
890  }
891 
892  const value_t&
893  zero() const
894  {
895  static value_t res;
896  return res;
897  }
898 
899  bool
900  is_zero(const value_t& v) const
901  {
902  return v.empty();
903  }
904 
905  static constexpr bool show_one() { return false; }
906  static constexpr star_status_t star_status()
907  {
908  return weightset_t::star_status();
909  }
910 
912  static value_t
913  conv(self_t, const value_t& v)
914  {
915  return v;
916  }
917 
921  template <typename WS>
922  value_t
923  conv(const WS& ws, const typename WS::value_t& v) const
924  {
925  return {{labelset()->one(), weightset()->conv(ws, v)}};
926  }
927 
929  template <typename C, wet_kind_t K>
930  value_t
932  const typename polynomialset<C, K>::value_t& v) const
933  {
934  const typename C::labelset_t& sls = *sps.labelset();
935  const typename C::weightset_t& sws = *sps.weightset();
936  const labelset_t& tls = *labelset();
937  const weightset_t& tws = *weightset();
938  value_t res;
939  for (const auto& m: v)
940  add_here(res, tls.conv(sls, label_of(m)), tws.conv(sws, weight_of(m)));
941  return res;
942  }
943 
944 
945  /*--------------.
946  | less(l, r). |
947  `--------------*/
948 
949  ATTRIBUTE_PURE
950  static bool monomial_less(const monomial_t& lhs, const monomial_t& rhs)
951  {
952  if (labelset_t::less(label_of(lhs), label_of(rhs)))
953  return true;
954  else if (labelset_t::less(label_of(rhs), label_of(lhs)))
955  return false;
956  else
957  return weightset_t::less(weight_of(lhs), weight_of(rhs));
958  }
959 
960  template <wet_kind_t WetType>
961  ATTRIBUTE_PURE
962  static auto
963  less_impl(const value_t& l, const value_t& r)
964  -> std::enable_if_t<WetType != wet_kind_t::bitset,
965  bool>
966  {
967  return boost::range::lexicographical_compare(l, r, monomial_less);
968  }
969 
970  template <wet_kind_t WetType>
971  ATTRIBUTE_PURE
972  static auto
973  less_impl(const value_t& l, const value_t& r)
974  -> std::enable_if_t<WetType == wet_kind_t::bitset,
975  bool>
976  {
977  return l.set() < r.set();
978  }
979 
980  ATTRIBUTE_PURE
981  static bool
982  less(const value_t& l, const value_t& r)
983  {
984  return less_impl<value_t::kind>(l, r);
985  }
986 
987 
988  value_t
989  transpose(const value_t& v) const
990  {
991  value_t res;
992  for (const auto& i: v)
993  res.set(labelset()->transpose(label_of(i)),
994  weightset()->transpose(weight_of(i)));
995  return res;
996  }
997 
998 
999  /*--------.
1000  | hash. |
1001  `--------*/
1002  ATTRIBUTE_PURE
1003  static size_t hash(const monomial_t& m, size_t res = 0)
1004  {
1005  hash_combine(res, labelset_t::hash(label_of(m)));
1006  hash_combine(res, weightset_t::hash(weight_of(m)));
1007  return res;
1008  }
1009 
1010  template <wet_kind_t WetType>
1011  ATTRIBUTE_PURE
1012  static auto
1013  hash_impl(const value_t& p)
1014  -> std::enable_if_t<WetType != wet_kind_t::bitset,
1015  size_t>
1016  {
1017  size_t res = 0;
1018  for (const auto& m: p)
1019  res = hash(m, res);
1020  return res;
1021  }
1022 
1023  template <wet_kind_t WetType>
1024  ATTRIBUTE_PURE
1025  static auto
1026  hash_impl(const value_t& p)
1027  -> std::enable_if_t<WetType == wet_kind_t::bitset,
1028  size_t>
1029  {
1030  return hash_value(p.set());
1031  }
1032 
1033  ATTRIBUTE_PURE
1034  static size_t hash(const value_t& v)
1035  {
1036  return hash_impl<value_t::kind>(v);
1037  }
1038 
1039 
1041  static self_t make(std::istream& is)
1042  {
1043  // name is, for instance, "polynomialset<lal_char(abcd), z>".
1044  eat(is, "polynomialset<");
1045  auto ctx = Context::make(is);
1046  eat(is, '>');
1047  return {ctx};
1048  }
1049 
1050  std::ostream&
1051  print_set(std::ostream& o, format fmt = {}) const
1052  {
1053  switch (fmt.kind())
1054  {
1055  case format::latex:
1056  o << "\\mathsf{Poly}[";
1057  context().print_set(o, fmt);
1058  o << ']';
1059  break;
1060  case format::sname:
1061  o << "polynomialset<";
1062  context().print_set(o, fmt);
1063  o << '>';
1064  break;
1065  case format::text:
1066  case format::utf8:
1067  o << "Poly[";
1068  context().print_set(o, fmt);
1069  o << ']';
1070  break;
1071  case format::raw:
1072  assert(0);
1073  break;
1074  }
1075  return o;
1076  }
1077 
1083  boost::optional<label_t>
1084  conv_label(std::istream& i, bool weighted, const char sep = '+') const
1085  {
1086  int peek = i.peek();
1087  assert(peek != '[');
1088  if (peek == '\\')
1089  {
1090  i.ignore();
1091  if (i.peek() == 'z')
1092  {
1093  i.ignore();
1094  return boost::none;
1095  }
1096  else
1097  i.unget();
1098  }
1099 
1100  // The label is not \z.
1101  // Check if there is a label that comes. Or rather, check if
1102  // there is something else than EOF or the separator, in which
1103  // case it must be a label.
1104  label_t res;
1105  if (peek == EOF || peek == sep || isspace(peek))
1106  {
1107  // There is no label. This counts as '$', the special
1108  // label.
1109  //
1110  // Indeed, that's how we represent the initial and final
1111  // transitions: '$ -> 0 "<2>"'. Using the one label is
1112  // tempting, but it does not exist for lal_char for
1113  // instance. And it would be wrong to have '\e' when we
1114  // can, and '$' otherwise...
1115  //
1116  // However, we must have at least a weight: a completely
1117  // empty mononial ($ -> 0 "<2>,") is invalid.
1118  VCSN_REQUIRE(weighted,
1119  sname(), ": conv: invalid monomial: ",
1120  str_escape(peek),
1121  " (did you mean \\e or \\z?)");
1122  res = labelset()->special();
1123  }
1124  else
1125  {
1126  auto pos = i.tellg();
1127  res = labelset()->conv(i);
1128  // In law_char, when reading the monomial `a|b` (yes, `|` is
1129  // not escaped), we looped for ever: the `a` was read by
1130  // setalpha::get_word, which then returned, and then
1131  // conv_label repeatedly called get_word on `|b`, which
1132  // endlessly returned the empty word, refusing to pass the
1133  // `|`.
1134  //
1135  // Make sure we catch this. Beware that tellg returns -1
1136  // (yes, signed!) on EOF.
1137  require(i.peek() == EOF || pos < i.tellg(),
1138  "invalid implicit empty word before: ", i);
1139  }
1140  return res;
1141  }
1142 
1144  weight_t
1145  conv_weight(std::istream& i) const
1146  {
1147  if (i.peek() == langle)
1148  // FIXME: convert to use conv(std::istream).
1149  //
1150  // The problem is when we have a rational expression as a
1151  // weight: in that case, conv expect to parse up to EOF, not
1152  // up to '>'. We first need to fix the parsing of expression
1153  // to work on a flow, to be able to use weightset()->conv
1154  // here. Which means to get back the stream from a Flex
1155  // scanner. It might not be easy.
1157  else
1158  return weightset()->one();
1159  }
1160 
1167  boost::optional<monomial_t>
1168  conv_monomial(std::istream& i, const char sep = '+') const
1169  {
1170 #define SKIP_SPACES() \
1171  while (isspace(i.peek())) \
1172  i.ignore()
1173 
1174  // Nothing to read: signal EOF as an empty result.
1175  SKIP_SPACES();
1176  if (i.peek() == EOF)
1177  return boost::none;
1178 
1179  // Possibly a weight in braces.
1180  bool weighted = i.peek() == langle;
1181  weight_t w = conv_weight(i);
1182 
1183  // Possibly, a label.
1184  SKIP_SPACES();
1185  auto l = conv_label(i, weighted, sep);
1186  require(l, "\\z is invalid for monomials");
1187  return monomial_t{*l, w};
1188 #undef SKIP_SPACES
1189  }
1190 
1199  value_t
1200  conv(std::istream& i, const char sep = '+') const
1201  {
1202  value_t res;
1203 #define SKIP_SPACES() \
1204  while (isspace(i.peek())) \
1205  i.ignore()
1206 
1207  do
1208  {
1209  // Possibly a weight in braces.
1210  SKIP_SPACES();
1211  bool weighted = i.peek() == langle;
1212  weight_t w = conv_weight(i);
1213 
1214  SKIP_SPACES();
1215  // Possibly, a label.
1216  // Handle label classes.
1217  if (i.peek() == '[')
1218  labelset()->convs(i, [this, &res, &w](const label_t& l)
1219  {
1220  add_here(res, l, w);
1221  });
1222  else if (auto l = conv_label(i, weighted, sep))
1223  {
1224  require(l, "\\z is invalid for monomials");
1225  add_here(res, *l, w);
1226  }
1227 
1228  // sep (e.g., '+'), or stop parsing.
1229  SKIP_SPACES();
1230  if (i.peek() == sep)
1231  i.ignore();
1232  else
1233  break;
1234  }
1235  while (true);
1236 #undef SKIP_SPACES
1237 
1238  return res;
1239  }
1240 
1242  std::ostream&
1243  print(const monomial_t& m, std::ostream& out,
1244  format fmt = {}) const
1245  {
1246  static bool parens = getenv("VCSN_PARENS");
1247  print_weight_(weight_of(m), out, fmt);
1248  if (parens)
1249  out << (fmt == format::latex ? "\\left(" : "(");
1250  labelset()->print(label_of(m), out, fmt.for_labels());
1251  if (parens)
1252  out << (fmt == format::latex ? "\\right)" : ")");
1253  return out;
1254  }
1255 
1262  std::ostream&
1263  print(const value_t& v, std::ostream& out,
1264  format fmt = {},
1265  const std::string& sep = " + ") const
1266  {
1267  if (is_zero(v))
1268  out << (fmt == format::latex ? "\\emptyset"
1269  : fmt == format::utf8 ? "∅"
1270  : "\\z");
1271  else
1272  {
1273  const auto s =
1274  (sep == " + "
1275  ? (fmt == format::latex ? std::string{" \\oplus "}
1276  : fmt == format::utf8 ? std::string{"⊕"}
1277  : sep)
1278  : sep);
1279  print_(v, out, fmt, s);
1280  }
1281  return out;
1282  }
1283 
1284  private:
1286  std::ostream&
1287  print_weight_(const weight_t w, std::ostream& out,
1288  format fmt) const
1289  {
1290  static bool parens = getenv("VCSN_PARENS");
1291  if (parens || weightset()->show_one() || !weightset()->is_one(w))
1292  {
1293  out << (fmt == format::latex ? "\\left\\langle "
1294  : fmt == format::utf8 ? "⟨"
1295  : "<");
1296  weightset()->print(w, out, fmt.for_weights());
1297  out << (fmt == format::latex ? "\\right\\rangle "
1298  : fmt == format::utf8 ? "⟩"
1299  : ">");
1300  }
1301  return out;
1302  }
1303 
1305  std::ostream&
1306  print_without_classes_(const value_t& v, std::ostream& out,
1307  format fmt,
1308  const std::string& sep) const
1309  {
1310  bool first = true;
1311  for (const auto& m: v)
1312  {
1313  if (!first)
1314  out << sep;
1315  first = false;
1316  print(m, out, fmt);
1317  }
1318  return out;
1319  }
1320 
1322  std::ostream&
1323  print_with_classes_(const value_t& v, std::ostream& out,
1324  format fmt,
1325  const std::string& sep) const
1326  {
1327  using std::begin;
1328  using std::end;
1329 
1330  // We can use a vector, as we know that the labels are already
1331  // sorted, and random access iteration will be handy below.
1332  using labels_t = std::vector<label_t>;
1333 
1334  // Cluster the letters per weight.
1335  auto per_weight = std::map<weight_t, labels_t,
1337  // No classes if the weights of the letters aren't all the same.
1338  for (const auto& m: v)
1339  if (!labelset()->is_one(label_of(m)))
1340  per_weight[weight_of(m)].emplace_back(label_of(m));
1341 
1342  // Sort the clusters per label.
1343  auto per_label = std::map<label_t,
1344  std::pair<weight_t, labels_t>,
1346  for (const auto& p: per_weight)
1347  // Split classes which are too small.
1348  if (p.second.size() < 3)
1349  for (auto l: p.second)
1350  per_label[l] = std::make_pair(p.first, labels_t{l});
1351  else
1352  per_label[detail::front(p.second)] = p;
1353 
1354  // Whether we must not issue a separator.
1355  bool first = true;
1356 
1357  // Print with classes. First, the constant-term.
1358  if (labelset()->is_one(label_of(detail::front(v))))
1359  {
1360  print(detail::front(v), out, fmt);
1361  first = false;
1362  }
1363 
1364  for (const auto& p: per_label)
1365  {
1366  if (!first)
1367  out << sep;
1368  first = false;
1369 
1370  // The weight.
1371  print_weight_(p.second.first, out, fmt);
1372 
1373  if (1 < p.second.second.size())
1374  // Print the character class. 'letters' are sorted, since
1375  // polynomials are shortlex-sorted on the labels.
1376  print_label_class(*labelset(), p.second.second,
1377  out, fmt.for_labels());
1378  else
1379  labelset()->print(detail::front(p.second.second),
1380  out, fmt.for_labels());
1381  }
1382  return out;
1383  }
1384 
1386  template <typename Ctx = context_t>
1388  std::ostream&>
1389  print_(const value_t& v, std::ostream& out,
1390  format fmt = {},
1391  const std::string& sep = " + ") const
1392  {
1393  return print_without_classes_(v, out, fmt, sep);
1394  }
1395 
1398  template <typename Ctx = context_t>
1400  std::ostream&>
1401  print_(const value_t& v, std::ostream& out,
1402  format fmt = {},
1403  const std::string& sep = " + ") const
1404  {
1405  // No classes if not at least 3 elements.
1406  if (sep == " + " || v.size() <= 2)
1407  return print_without_classes_(v, out, fmt, sep);
1408  else
1409  return print_with_classes_(v, out, fmt, sep);
1410  }
1411 
1412 
1413  private:
1415 
1417  constexpr static char langle = '<';
1419  constexpr static char rangle = '>';
1420  };
1421 
1422  template <typename Context,
1423  wet_kind_t Kind = detail::wet_kind<labelset_t_of<Context>,
1426  make_polynomialset(const Context& context)
1427  {
1428  return {context};
1429  }
1430 
1431  template <typename Ctx1, wet_kind_t Kind1,
1432  typename Ctx2, wet_kind_t Kind2>
1433  struct join_impl<polynomialset<Ctx1, Kind1>,
1434  polynomialset<Ctx2, Kind2>>
1435  {
1436  // Use the default kind.
1439  const polynomialset<Ctx2, Kind2>& ps2)
1440  {
1441  return {vcsn::join(ps1.context(), ps2.context())};
1442  }
1443  };
1444 
1445  template <typename Ctx1, wet_kind_t Kind1,
1446  typename WS2>
1447  struct join_impl<polynomialset<Ctx1, Kind1>, WS2>
1448  {
1449  using type
1450  = polynomialset<context<typename Ctx1::labelset_t,
1452  static type join(const polynomialset<Ctx1, Kind1>& ps1, const WS2& ws2)
1453  {
1454  return {*ps1.labelset(), vcsn::join(*ps1.weightset(), ws2)};
1455  }
1456  };
1457  }
1458 }
value_t infiltration(const value_t &l, const value_t &r) const
The infiltration of polynomials l and r.
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
static constexpr bool has_lightening_weights()
value_t & set_weight(value_t &v, const label_t &l, const weight_t w) const
Set the monomial of l in v to weight w.
Linear combination of labels: map labels to weights.
Definition: fwd.hh:41
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
Definition: raise.hh:89
value_t conv(const WS &ws, const typename WS::value_t &v) const
FIXME: use enable_if to prevent this from being instantiated when WS is a polynomialset.
value_t rdiv(const value_t &l, const value_t &r) const
value_t sub(const value_t &l, const value_t &r) const
The subtraction of polynomials l and r.
static type join(const polynomialset< Ctx1, Kind1 > &ps1, const polynomialset< Ctx2, Kind2 > &ps2)
std::enable_if_t<!Ctx::is_lar, value_t > conjunction_impl(const value_t &l, const value_t &r) const
The conjunction of polynomials l and r.
value_t normalize(value_t res) const
Normalized v.
value_t conv(std::istream &i, const char sep= '+') const
Read a polynomial from a stream.
const context_t & context() const
decltype(join(std::declval< ValueSets >()...)) join_t
The type of the join of the ValueSets.
Definition: join.hh:79
typename value_t::value_type monomial_t
A pair .
Print as rich UTF-8 text, escaped.
Definition: format.hh:28
auto scalar_product(const value_t &l, const value_t &r) const -> std::enable_if_t<(WetType==wet_kind_t::bitset &&std::is_same< WS, b >::value), weight_t >
The sum of the weights of the common labels.
static constexpr bool is_commutative()
static ATTRIBUTE_PURE auto equal_impl(const value_t &l, const value_t &r) -> std::enable_if_t< WetType==wet_kind_t::bitset, bool >
auto tuple(Polys &&...vs) const -> value_t
Build a tuple of polynomials: (e.E+f.F)|(g.G+h.H) => eg.
weightset_t_of< context_t > weightset_t
void weight_set(welement< Label, Weight > &m, const Weight &w)
Set the weight of a welement.
Definition: wet.hh:162
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:59
auto hash_value(const T &v) -> decltype(std::hash< T >
Following the naming convention of Boost.
Definition: functional.hh:66
value_t complement(const value_t &v) const
Complement this polynomial.
static constexpr bool show_one()
bool is_zero(const value_t &v) const
value_t & sub_here(value_t &v, const monomial_t &m) const
v -= m.
Definition: a-star.hh:8
polynomialset_impl(const context_t &ctx)
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:78
#define SKIP_SPACES()
const value_t & zero() const
std::enable_if_t< labelset_t_of< Ctx >::is_letterized(), std::ostream & > print_(const value_t &v, std::ostream &out, format fmt={}, const std::string &sep=" + ") const
Print a non-null value for a letterized labelset (e.g., letterset or nullableset. ...
auto add_here_impl(value_t &l, const value_t &r) const -> std::enable_if_t<(WetType==wet_kind_t::bitset &&std::is_same< WS, f2 >::value), value_t & >
v += p, F2 and bitsets.
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
static symbol sname()
The static name.
value_t & rdiv_here(value_t &v, const weight_t w) const
Right exterior division.
std::ostream & str_escape(std::ostream &os, const std::string &str, const char *special=nullptr)
Output a string, escaping special characters.
Definition: escape.cc:54
static ATTRIBUTE_PURE bool monomial_less(const monomial_t &lhs, const monomial_t &rhs)
value_t lmul_label(const label_t &lhs, const value_t &v) const
Left product by a label.
Print for LaTeX.
Definition: format.hh:20
typename context_t::labelset_ptr labelset_ptr
auto mul_impl(const value_t &l, const value_t &r) const -> std::enable_if_t< WetType==wet_kind_t::bitset, value_t >
The product of polynomials l and r.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:55
boost::optional< monomial_t > conv_monomial(std::istream &i, const char sep= '+') const
Read a monomial from a stream.
value_t lmul(const weight_t w, const value_t &v) const
Left exterior product.
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
An input/output format for valuesets.
Definition: format.hh:11
value_t & ldiv_here(const weight_t w, value_t &v) const
Left exterior division.
auto factor(const Aut &aut) -> decltype(::vcsn::copy(aut))
Definition: prefix.hh:106
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto scalar_product(const value_t &l, const value_t &r) const -> std::enable_if_t<(WetType==wet_kind_t::bitset &&std::is_same< WS, f2 >::value), weight_t >
The sum of the weights of the common labels.
value_t & add_here(value_t &l, const value_t &r) const
format for_labels() const
A copy of this format, but to print labels.
Definition: format.hh:40
wet< label_t_of< Context >, weight_t_of< Context >, Kind, vcsn::less< labelset_t_of< Context >>, vcsn::hash< labelset_t_of< Context >>, vcsn::equal_to< labelset_t_of< Context >>> wet_of
The corresponding wet for a LabelSet -> WeightSet context.
Definition: wet.hh:859
auto add_here_impl(value_t &l, const value_t &r) const -> std::enable_if_t<(WetType==wet_kind_t::bitset &&std::is_same< WS, b >::value), value_t & >
v += p, B and bitsets.
static ATTRIBUTE_PURE size_t hash(const monomial_t &m, size_t res=0)
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Definition: wet.hh:154
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:58
static ATTRIBUTE_PURE bool monomial_equal(const monomial_t &lhs, const monomial_t &rhs)
value_t ldiv(const value_t &l, const value_t &r) const
void cross(Fun f)
Variadic Cartesian product of containers.
Definition: tuple.hh:207
std::enable_if_t<!labelset_t_of< Ctx >::is_letterized(), std::ostream & > print_(const value_t &v, std::ostream &out, format fmt={}, const std::string &sep=" + ") const
Print a non-null value for a non letterized labelset.
wet_of< context_t, Kind > value_t
auto norm(const value_t &v) const -> weight_t
The norm: the weight with which we should divide a polynomial to normalize it.
std::ostream & print(const monomial_t &m, std::ostream &out, format fmt={}) const
Print a monomial.
static constexpr char langle
Left marker for weight in concrete syntax.
value_t & new_weight(value_t &v, const label_t &l, const weight_t w) const
Set the monomial of l in v to weight k.
static const value_t & one()
The unit polynomial.
static ATTRIBUTE_PURE size_t hash(const value_t &v)
constant< type_t::one, Context > one
Definition: fwd.hh:111
value_t add(const value_t &l, const value_t &r) const
The sum of polynomials l and r.
value_t ldiv(const monomial_t &l, const value_t &r) const
Left division by a monomial.
std::enable_if_t< Ctx::is_lar, value_t > conjunction_impl(const value_t &l, const value_t &r) const
The conjunction of polynomials l and r.
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:56
void hash_combine(std::size_t &seed, const T &v)
Definition: functional.hh:32
A structure that implements the computation of join(V1, V2).
Definition: join.hh:18
static ATTRIBUTE_PURE auto equal_impl(const value_t &l, const value_t &r) -> std::enable_if_t< WetType!=wet_kind_t::bitset, bool >
static self_t make(std::istream &is)
Build from the description in is.
value_t & add_here(value_t &v, const label_t &l, const weight_t k) const
v += l.
static ATTRIBUTE_PURE auto hash_impl(const value_t &p) -> std::enable_if_t< WetType!=wet_kind_t::bitset, size_t >
monomial_t determinize(value_t v) const
"Determinize" this polynomial: turn into a monomial.
weight_t_of< context_t > weight_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
value_t transpose(const value_t &v) const
static type join(const polynomialset< Ctx1, Kind1 > &ps1, const WS2 &ws2)
value_t mul(const monomial_t &lhs, const value_t &v) const
Left product by a monomial.
std::string bracketed(std::istream &i, char lbracket, char rbracket)
Extract the string which is here between lbracket and rbracket.
Definition: stream.cc:17
std::ostream & print_without_classes_(const value_t &v, std::ostream &out, format fmt, const std::string &sep) const
Print a polynomial value without classes.
In the general case, normalize by the first (non null) weight.
const weightset_ptr & weightset() const
z::value_t operator()(const value_t &v) const
std::ostream & print_weight_(const weight_t w, std::ostream &out, format fmt) const
Print a weight.
value_t rmul_label(const value_t &v, const label_t &rhs) const
Right product.
star_status_t
Definition: star-status.hh:5
value_t mul(const value_t &l, const monomial_t &rhs) const
Right product by a monomial.
std::ostream & print_with_classes_(const value_t &v, std::ostream &out, format fmt, const std::string &sep) const
Print a polynomial value with classes.
wet_kind_t
Different implementations of wets.
Definition: wet.hh:197
static ATTRIBUTE_PURE bool equal(const value_t &l, const value_t &r)
symbol sname()
Definition: name.hh:67
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:380
value_t & add_here(value_t &v, const monomial_t &m) const
v += m.
weight_t normalize_here(value_t &v) const
Normalize v in place: compute the LGCD of the weights, ldiv the monomials with that factor...
static bool is_one(const value_t &v) ATTRIBUTE_PURE
Whether is the unit polynomial.
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
Definition: wet.hh:146
Print as a parsable type string.
Definition: format.hh:24
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:82
labelset_t_of< context_t > labelset_t
static ATTRIBUTE_PURE bool less(const value_t &l, const value_t &r)
std::ostream & print(const value_t &v, std::ostream &out, format fmt={}, const std::string &sep=" + ") const
Print a value (a polynomial).
const weight_t get_weight(const value_t &v, const label_t &l) const ATTRIBUTE_PURE
auto mul(const value_t &l, const value_t &r) const -> value_t
The product of polynomials l and r.
Container::value_type front(const Container &container)
The first member of this Container.
Definition: algorithm.hh:58
static value_t conv(self_t, const value_t &v)
Conversion from (this and) other weightsets.
monomial_t mul(const monomial_t &l, const monomial_t &r) const
The product of monomials l and r.
Request the bitset implementation (bool weights).
typename context_t::weightset_ptr weightset_ptr
label_t to_label(const value_t &v) const
Convert into a label.
value_t star(const value_t &v) const
The star of polynomial v.
value_t lgcd(const value_t &lhs, const value_t &rhs) const
LGCD between two polynomials.
std::enable_if_t<!is_letterized_t< labelset_t_of< Aut > >{}, bool > is_letterized(const Aut &aut)
Definition: letterize.hh:162
typename labelset_t::value_t label_t
Polynomials over labels.
auto mul_impl(const value_t &l, const value_t &r) const -> std::enable_if_t< WetType!=wet_kind_t::bitset, value_t >
The product of polynomials l and r.
static constexpr star_status_t star_status()
value_t conv(const polynomialset< C, K > &sps, const typename polynomialset< C, K >::value_t &v) const
Convert from another polynomialset to type_t.
static ATTRIBUTE_PURE auto hash_impl(const value_t &p) -> std::enable_if_t< WetType==wet_kind_t::bitset, size_t >
value_t rmul(const value_t &v, const weight_t w) const
Right exterior product.
auto project(const value_t &v) const
Extract a single tape.
std::ostream & print_set(std::ostream &o, format fmt={}) const
boost::optional< label_t > conv_label(std::istream &i, bool weighted, const char sep= '+') const
Read a label, if there is one.
auto mul(const value_t &p, const label_t &l, const weight_t w) const -> value_t
The product of polynomials l and r.
std::ostream & print_label_class(const LabelSet &ls, const std::vector< typename LabelSet::value_t > &letters, std::ostream &out, format fmt)
Print a set of labels (letterized) with classes.
Definition: labelset.hh:335
value_t & del_weight(value_t &v, const label_t &l) const
Remove the monomial of l in v.
static ATTRIBUTE_PURE auto less_impl(const value_t &l, const value_t &r) -> std::enable_if_t< WetType!=wet_kind_t::bitset, bool >
polynomialset< Context, Kind > make_polynomialset(const Context &context)
static const monomial_t & monomial_one()
The unit monomial.
auto label_is_zero(const LabelSet &ls, const typename LabelSet::value_t *l) -> decltype(ls.is_zero(l), bool())
WeightSet::value_t operator()(const value_t &v) const
auto conv(const ValueSet &vs, const std::string &str, Args &&...args) -> decltype(vs.conv(std::declval< std::istream & >(), std::forward< Args >(args)...))
Parse str via vs.conv.
Definition: stream.hh:28
static ATTRIBUTE_PURE auto less_impl(const value_t &l, const value_t &r) -> std::enable_if_t< WetType==wet_kind_t::bitset, bool >
auto scalar_product(const value_t &l, const value_t &r) const -> std::enable_if_t< WetType!=wet_kind_t::bitset, weight_t >
The sum of the weights of the common labels.
weight_t conv_weight(std::istream &i) const
Read a weight, if there is one, bracketed.
const labelset_ptr & labelset() const
monomial_t ldiv(const monomial_t &l, const monomial_t &r) const
value_t conjunction(const value_t &l, const value_t &r) const
void clear(value_t &v)
Set to zero.
Functor to compare Values of ValueSets.
Definition: functional.hh:78
auto add_here_impl(value_t &l, const value_t &r) const -> std::enable_if_t< WetType!=wet_kind_t::bitset, value_t & >
v += p, default case.
Request the map implementation.
static constexpr char rangle
Right marker for weight in concrete syntax.