18 template <
typename ExpSet>
29 using weight_t =
typename weightset_t::value_t;
35 constexpr
static const char*
me() {
return "expansion"; }
40 using polys_t = std::map<label_t, polynomial_t, vcsn::less<labelset_t>>;
85 o <<
"\\mathsf{Expansion}[";
86 rs_.print_set(o, fmt);
91 rs_.print_set(o, fmt);
97 rs_.print_set(o, fmt);
112 if (!
ws_.is_zero(v.constant) || v.polynomials.empty())
117 ws_.print(v.constant, o, fmt.for_weights());
123 for (
const auto& p: v.polynomials)
130 ls_.print(p.first, o, fmt.for_labels());
134 ps_.print(p.second, o, fmt);
155 auto i = res.polynomials.find(
one);
156 if (i != std::end(res.polynomials))
158 auto j = i->second.find(
rs_.one());
159 if (j != std::end(i->second))
163 if (i->second.empty())
164 res.polynomials.erase(i);
187 if (!
ws_.is_zero(res.constant))
190 ps_.add_here(res.polynomials[
one],
192 res.constant =
ws_.zero();
215 template <
typename OtherExpSet>
222 return {ws_.conv(other_ws, v.
constant),
229 return {ws_.zero(),
polys_t{}};
241 return {ws_.zero(), {{l, ps_.one()}}};
245 void add_here(value_t& lhs,
const value_t& rhs)
const
247 lhs.constant = ws_.add(lhs.constant, rhs.constant);
248 for (
const auto& p: rhs.polynomials)
249 ps_.add_here(lhs.polynomials[p.first], p.second);
253 value_t
add(
const value_t& lhs,
const value_t& rhs)
const
271 res.constant = ws_.mul(w, res.constant);
272 for (
auto& p: res.polynomials)
273 p.second = ps_.lweight(w, p.second);
280 value_t
res = {ws_.mul(lhs.constant, w),
polys_t{}};
281 for (
auto& p: lhs.polynomials)
282 for (
const auto& m: p.second)
283 ps_.add_here(res.polynomials[p.first],
291 for (
auto& p: res.polynomials)
292 p.second = ps_.rmul_label(p.second, rhs);
299 res.constant = ws_.ldivide(w, res.constant);
300 for (
auto& p: res.polynomials)
301 for (
auto&& m: p.second)
307 template <
typename Conjunction>
310 const value_t&,
const value_t&,
315 template <
typename Conjunction>
318 const value_t& l,
const value_t&
r,
323 auto one = ls_.one();
325 auto i = l.polynomials.find(
one);
326 if (i != std::end(l.polynomials))
327 for (
const auto& rhs: r.polynomials)
328 if (!ls_.is_one(rhs.first))
329 ps_.add_here(res.polynomials[
one],
330 conjunction(i->second,
331 ps_.lmul_label(rs_.atom(rhs.first),
336 auto i = r.polynomials.find(
one);
337 if (i != std::end(r.polynomials))
338 for (
const auto& lhs: l.polynomials)
339 if (!ls_.is_one(lhs.first))
340 ps_.add_here(res.polynomials[
one],
341 conjunction(ps_.lmul_label(rs_.atom(lhs.first),
350 template <
typename LabelSet = labelset_t,
typename Conjunction>
353 -> std::enable_if_t<detail::is_letterized_t<LabelSet>{},
359 res.constant = ws_.mul(l.constant,
r.constant);
360 for (
const auto& p:
zip_maps(l.polynomials,
r.polynomials))
361 res.polynomials[p.first]
362 =
conjunction(std::get<0>(p.second), std::get<1>(p.second));
365 conjunctions_with_one_(res, l,
r, has_one,
conjunction);
373 template <
typename LabelSet = labelset_t,
typename Conjunction>
376 -> std::enable_if_t<!detail::is_letterized_t<LabelSet>{},
379 value_t res =
zero();
380 res.constant = ws_.mul(lhs.constant, rhs.constant);
381 for (
const auto& l: lhs.polynomials)
382 for (
const auto&
r: rhs.polynomials)
385 auto lcp = ls_.lgcd(l.first,
r.first);
386 if (!ls_.is_one(lcp))
388 auto left = rs_.atom(ls_.ldivide(lcp, l.first));
389 auto right = rs_.atom(ls_.ldivide(lcp,
r.first));
390 ps_.add_here(res.polynomials[lcp],
392 ps_.lmul_label(right,
r.second)));
399 template <
typename Shuffle>
406 for (
const auto& p: lhs_xpn.polynomials)
407 for (
const auto& m: p.second)
408 ps_.add_here(res.polynomials[p.first],
411 for (
const auto& p: rhs_xpn.polynomials)
412 for (
const auto& m: p.second)
413 ps_.add_here(res.polynomials[p.first],
427 return ps_.conjunction(l, r);
435 const value_t& rhs_xpn,
const expression_t& rhs_xpr)
const
438 res.constant = ws_.mul(lhs_xpn.constant, rhs_xpn.constant);
440 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
443 return rs_.shuffle(l, r);
449 const value_t& rhs_xpn,
const expression_t& rhs_xpr)
const
456 return ps_.infiltrate(l, r);
461 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
464 return rs_.infiltrate(l, r);
482 return complement_<detail::is_letterized_t<labelset_t>{}>(
v);
487 template <
bool IsLetterized>
488 std::enable_if_t<!IsLetterized, value_t>
492 ": complement: labelset must be letterized: ", ls_);
496 template <
bool IsLetterized>
497 std::enable_if_t<IsLetterized, value_t>
501 res.constant = ws_.is_zero(v.constant) ? ws_.one() : ws_.zero();
503 detail::static_if<labelset_t::has_one()>
504 ([
this](
const auto&
v,
const auto& ls)
507 me(),
": complement: expansion must be normalized: ",
513 detail::static_if<detail::has_generators_mem_fn<labelset_t>{}>
514 ([
this, &
res](
const auto&
v,
const auto& ls)
516 for (
auto l: ls.generators())
518 auto i = v.polynomials.find(l);
520 ps_.complement(i == end(v.polynomials)
521 ? ps_.zero() : i->second);
533 res.constant = v.constant;
534 for (
const auto& lp: v.polynomials)
535 res.polynomials[lp.first] = {ps_.determinize(lp.second)};
544 template <
unsigned Tape>
549 template <
unsigned Tape>
553 return {rs_.template project<Tape>()};
557 template <
typename... Expansions>
562 template <
size_t Tape>
566 auto es = eset_.template project<Tape>();
569 VCSN_REQUIRE(es.expressionset().weightset()->is_zero(res.constant),
570 es,
": to-expansion: cannot denormalize ",
572 ", need support for label one (the empty label)");
573 return res.polynomials;
577 template <
size_t... Tape>
582 using res_t = std::tuple<typename project_t<Tape>::polys_t...>;
583 return res_t{denormalize_tape<Tape>(std::get<Tape>(es))...};
589 auto t =
std::tuple<
const Expansions&...>{es...};
590 constexpr
auto indices
592 return denormalize(t, indices);
599 auto res = eset_.zero();
600 auto polys = denormalize(std::forward<Expansions>(es)...);
602 ([&res,
this](
const auto&... ps)
605 eset_.ps_.add_here(res.polynomials[l],
606 eset_.ps_.tuple(ps.second...));
609 eset_.normalize(res);
670 template <
typename... Expansions>
675 auto t = tuple_impl<Expansions...>{*
this};
676 return t.tuple(std::forward<Expansions>(es)...);
680 template <
size_t Tape>
683 auto xs = project<Tape>();
684 const auto& ps = xs.polynomialset();
685 using res_t =
typename decltype(xs)::value_t;
687 res.constant = v.constant;
688 for (
const auto& p: v.polynomials)
689 ps.add_here(res.polynomials[ls_.template project<Tape>(p.first)],
690 ps_.template project<Tape>(p.second));
699 const value_t&,
const value_t&,
700 std::false_type)
const
705 const value_t& l,
const value_t&
r,
706 std::true_type)
const
710 for (
const auto& lhs: l.polynomials)
711 if (ls_.template set<1>().is_one(std::get<1>(lhs.first)))
712 for (
const auto& rhs: r.polynomials)
713 if (!ls_.template set<0>().is_one(std::get<0>(rhs.first)))
715 ps_.add_here(res.polynomials[lhs.first],
716 ps_.compose(lhs.second,
717 ps_.lmul_label(rs_.atom(rhs.first),
722 for (
const auto& rhs: r.polynomials)
723 if (ls_.template set<0>().is_one(std::get<0>(rhs.first)))
724 for (
const auto& lhs: l.polynomials)
725 if (!ls_.template set<1>().is_one(std::get<1>(lhs.first)))
727 ps_.add_here(res.polynomials[rhs.first],
728 ps_.compose(ps_.lmul_label(rs_.atom(lhs.first),
735 template <
typename Ctx = context_t>
737 -> std::enable_if_t<are_composable<Ctx, Ctx>{}, value_t>
739 value_t res =
zero();
742 res.constant = ws_.mul(l.constant,
r.constant);
743 for (
const auto& lm: l.polynomials)
744 for (
const auto& rm:
r.polynomials)
745 if (ls_.template set<0>().equal(std::get<1>(
label_of(lm)),
748 auto l = ls_.tuple(std::get<0>(
label_of(lm)),
750 ps_.add_here(res.polynomials[l],
751 ps_.compose(lm.second, rm.second));
754 compose_with_one_(res, l,
r, has_one);
772 template <
typename ExpSet>
782 template <
typename Ctx1,
typename Ctx2>
791 return type(
vcsn::join(lhs.expressionset(), rhs.expressionset()));
const expansionset & eset_
void conjunctions_with_one_(value_t &res, const value_t &l, const value_t &r, std::true_type, Conjunction conjunction) const
value_t & denormalize_(value_t &res, std::true_type) const
Denormalize res move the constant to the polynomial associated to one.
value_t & ldivide_here(const weight_t &w, value_t &res) const
Inplace left-division by w of res.
polynomialset_t ps_
The polynomialset for the polynomials.
value_t & normalize(value_t &res) const
Normalize: move the constant term to the label one.
expansionset(const expressionset_t &rs)
std::string type(const automaton &a)
The implementation type of a.
typename polynomialset_t::monomial_t monomial_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
const context_t & context() const
The context.
static constexpr const char * me()
value_t & denormalize(value_t &res) const
Move the constant to the polynomial associated to one.
Aut1 & add_here(Aut1 &res, const Aut2 &b, standard_tag)
Merge transitions of b into those of res.
Denormalize a pack of one-tape expansions.
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.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
auto compose(value_t l, value_t r) const -> std::enable_if_t< are_composable< Ctx, Ctx >
The composition of l and r.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
auto tuple(Expansions &&...es) const -> value_t
The tuplization of single-tape expansions into a multitape expansion.
auto label_of(const welement< Label, Weight > &m) -> decltype(m.label())
The label of a welement.
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
const polynomialset_t & polynomialset() const
The polynomialset.
A structure that implements the computation of join(V1, V2).
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 infiltrate(const value_t &lhs_xpn, const expression_t &lhs_xpr, const value_t &rhs_xpn, const expression_t &rhs_xpr) const
The infiltration product of l and r.
Print as a parsable type string.
typename polynomialset_t::value_t polynomial_t
auto project() const -> project_t< Tape >
The expansionset for tape Tape.
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
value_t & lweight_here(const weight_t &w, value_t &res) const
Inplace left-multiplication by w of res.
auto tuple(Expansions &&...es) const -> value_t
value_t shuffle(const value_t &lhs_xpn, const expression_t &lhs_xpr, const value_t &rhs_xpn, const expression_t &rhs_xpr) const
The shuffle product of lhs_xpn and rhs_xpn.
value_t atom(const label_t &l) const
A single label.
ATTRIBUTE_PURE bool has(const boost::container::flat_set< Key, Compare, Allocator > &s, const Key &e)
Whether e is member of s.
value_t complement(const value_t &v) const
The complement of v.
static type join(const expansionset< expressionset< Ctx1 >> &lhs, const expansionset< expressionset< Ctx2 >> &rhs)
label_t_of< context_t > label_t
const labelset_t & ls_
Shorthand to the labelset.
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
value_t & rweight_here(value_t &res, const expression_t &rhs) const
In place right multiplication by an expression.
expressionset_t expressionset_t
weightset_t_of< expressionset_t > weightset_t
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.
labelset_t_of< context_t > labelset_t
std::map< label_t, polynomial_t, vcsn::less< labelset_t >> polys_t
std::enable_if_t< IsLetterized, value_t > complement_(const value_t &v) const
Complement on a letterized labelset.
auto project(const value_t &v) const
Project a multitape expansion.
auto normalize(const Aut &a) -> decltype(copy(a))
Normalize a automaton.
const expressionset_t & expressionset() const
The expressionset.
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
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.
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
std::enable_if_t<!IsLetterized, value_t > complement_(const value_t &) const
Complement on an invalid labelset.
An input/output format for valuesets.
static value_t conv(self_t, const value_t &v)
Conversion from (this and) other weightsets.
value_t & normalize_(value_t &res, std::true_type) const
Normalize res: There must not remain a constant-term associated to one: put it with the constant term...
constant< type_t::zero, Context > zero
value_t zero() const
The zero.
value_t conv(const expansionset< OtherExpSet > &other, const typename expansionset< OtherExpSet >::value_t &v) const
Convert from another expansionset to self.
typename weightset_t::value_t weight_t
void compose_with_one_(value_t &, const value_t &, const value_t &, std::false_type) const
Print as is. For instance, don't try to escape labels.
void add_here(value_t &lhs, const value_t &rhs) const
In place addition.
void weight_set(welement< Label, Weight > &m, const Weight &w)
Set the weight of a welement.
std::string to_string(identities i)
Wrapper around operator<<.
value_t one() const
The one.
static symbol sname()
The static name.
variadic< type_t::conjunction, Context > conjunction
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.
Print as rich UTF-8 text, escaped.
expressionset_t rs_
The expressionset used for the expressions.
Implementation of nodes of tuple of rational expressions.
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
Aut & lweight_here(const weight_t_of< Aut > &w, Aut &res, Tag tag={})
In place left-multiplication of an automaton by a weight.
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
value_t rweight(const value_t &lhs, const weight_t &w) const
Right-multiplication of lhs by w.
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.
An inner node with multiple children.
void conjunctions_with_one_(value_t &, const value_t &, const value_t &, std::false_type, Conjunction) const
auto denormalize(const Expansions &...es) const
Entry point: Denormalize all these expansions.
std::ostream & print(const value_t &v, std::ostream &o, format fmt={}) const
Print this expansion.
std::integral_constant< bool, B > bool_constant
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print this valueset.
zipped_maps< Dereference, Maps... > zip_maps(Maps &&...maps)
Provide a variadic mul on top of a binary mul(), and one().
Print as plain (ASCII) text, escaped.
value_t determinize(const value_t &v) const
Turn the polynomials into (normalized) monomials.
expansionset< ExpSet > make_expansionset(const ExpSet &expset)
context_t_of< expressionset_t > context_t
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.
const weightset_t & ws_
Shorthand to the weightset.