17 template <
typename ExpSet>
28 using weight_t =
typename weightset_t::value_t;
34 constexpr
static const char*
me() {
return "expansion"; }
39 using polys_t = std::map<label_t, polynomial_t, vcsn::less<labelset_t>>;
84 o <<
"\\mathsf{Expansion}[";
85 rs_.print_set(o, fmt);
90 rs_.print_set(o, fmt);
96 rs_.print_set(o, fmt);
111 if (!
ws_.is_zero(v.constant) || v.polynomials.empty())
116 ws_.print(v.constant, o, fmt.for_weights());
122 for (
const auto& p: v.polynomials)
129 ls_.print(p.first, o, fmt.for_labels());
133 ps_.print(p.second, o, fmt);
154 auto i = res.polynomials.find(
one);
155 if (i != std::end(res.polynomials))
157 auto j = i->second.find(
rs_.one());
158 if (j != std::end(i->second))
162 if (i->second.empty())
163 res.polynomials.erase(i);
186 if (!
ws_.is_zero(res.constant))
189 ps_.add_here(res.polynomials[
one],
191 res.constant =
ws_.zero();
214 template <
typename OtherExpSet>
221 return {ws_.conv(other_ws, v.
constant),
228 return {ws_.zero(),
polys_t{}};
240 return {ws_.zero(), {{l, ps_.one()}}};
244 void add_here(value_t& lhs,
const value_t& rhs)
const
246 lhs.constant = ws_.add(lhs.constant, rhs.constant);
247 for (
const auto& p: rhs.polynomials)
248 ps_.add_here(lhs.polynomials[p.first], p.second);
252 value_t
add(
const value_t& lhs,
const value_t& rhs)
const
270 res.constant = ws_.mul(w, res.constant);
271 for (
auto& p: res.polynomials)
272 p.second = ps_.lmul(w, p.second);
279 value_t res = {ws_.mul(lhs.constant, w),
polys_t{}};
280 for (
auto& p: lhs.polynomials)
281 for (
const auto& m: p.second)
282 ps_.add_here(res.polynomials[p.first],
290 for (
auto& p: res.polynomials)
291 p.second = ps_.rmul_label(p.second, rhs);
298 res.constant = ws_.ldiv(w, res.constant);
299 for (
auto& p: res.polynomials)
300 for (
auto&& m: p.second)
306 template <
typename Conjunction>
309 const value_t&,
const value_t&,
314 template <
typename Conjunction>
317 const value_t& l,
const value_t&
r,
322 auto one = ls_.one();
324 auto i = l.polynomials.find(
one);
325 if (i != std::end(l.polynomials))
326 for (
const auto& rhs: r.polynomials)
327 if (!ls_.is_one(rhs.first))
328 ps_.add_here(res.polynomials[
one],
329 conjunction(i->second,
330 ps_.lmul_label(rs_.atom(rhs.first),
335 auto i = r.polynomials.find(
one);
336 if (i != std::end(r.polynomials))
337 for (
const auto& lhs: l.polynomials)
338 if (!ls_.is_one(lhs.first))
339 ps_.add_here(res.polynomials[
one],
340 conjunction(ps_.lmul_label(rs_.atom(lhs.first),
349 template <
typename LabelSet = labelset_t,
typename Conjunction>
352 -> std::enable_if_t<detail::is_letterized_t<LabelSet>{},
355 value_t res =
zero();
358 res.constant = ws_.mul(l.constant,
r.constant);
359 for (
const auto& p:
zip_maps(l.polynomials,
r.polynomials))
360 res.polynomials[p.first]
361 =
conjunction(std::get<0>(p.second), std::get<1>(p.second));
364 conjunctions_with_one_(res, l,
r, has_one,
conjunction);
372 template <
typename LabelSet = labelset_t,
typename Conjunction>
375 -> std::enable_if_t<!detail::is_letterized_t<LabelSet>{},
378 value_t res =
zero();
379 res.constant = ws_.mul(lhs.constant, rhs.constant);
380 for (
const auto& l: lhs.polynomials)
381 for (
const auto&
r: rhs.polynomials)
384 auto lcp = ls_.lgcd(l.first,
r.first);
385 if (!ls_.is_one(lcp))
387 auto left = rs_.atom(ls_.ldiv(lcp, l.first));
388 auto right = rs_.atom(ls_.ldiv(lcp,
r.first));
389 ps_.add_here(res.polynomials[lcp],
391 ps_.lmul_label(right,
r.second)));
398 template <
typename Shuffle>
405 for (
const auto& p: lhs_xpn.polynomials)
406 for (
const auto& m: p.second)
407 ps_.add_here(res.polynomials[p.first],
410 for (
const auto& p: rhs_xpn.polynomials)
411 for (
const auto& m: p.second)
412 ps_.add_here(res.polynomials[p.first],
426 return ps_.conjunction(l, r);
432 const value_t& rhs_xpn,
const expression_t& rhs_xpr)
const
435 res.constant = ws_.mul(lhs_xpn.constant, rhs_xpn.constant);
437 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
440 return rs_.shuffle(l, r);
446 const value_t& rhs_xpn,
const expression_t& rhs_xpr)
const
453 return ps_.infiltration(l, r);
458 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
461 return rs_.infiltration(l, r);
474 return complement_<labelset_t::is_free()>(
v);
479 template <
bool IsFree>
480 std::enable_if_t<!IsFree, value_t>
483 raise(me(),
": cannot handle complement without generators");
487 template <
bool IsFree>
488 std::enable_if_t<IsFree, value_t>
492 res.constant = ws_.is_zero(v.constant) ? ws_.one() : ws_.zero();
495 for (
auto l: ls_.generators())
497 auto i = v.polynomials.find(l);
499 ps_.complement(i == end(v.polynomials) ? ps_.zero() : i->second);
510 res.constant = v.constant;
511 for (
const auto& lp: v.polynomials)
512 res.polynomials[lp.first] = {ps_.determinize(lp.second)};
521 template <
unsigned Tape>
526 template <
unsigned Tape>
530 return {detail::project<Tape>(rs_)};
534 template <
typename... Expansions>
539 template <
size_t Tape>
543 auto es = eset_.template project<Tape>();
546 VCSN_REQUIRE(es.expressionset().weightset()->is_zero(res.constant),
547 es,
": to-expansion: cannot denormalize ",
549 ", need support for label one (the empty label)");
550 return res.polynomials;
554 template <
size_t... Tape>
559 using res_t = std::tuple<typename project_t<Tape>::polys_t...>;
560 return res_t{denormalize_tape<Tape>(std::get<Tape>(es))...};
566 auto t =
std::tuple<
const Expansions&...>{es...};
567 constexpr
auto indices
569 return denormalize(t, indices);
576 auto res = eset_.zero();
577 auto polys = denormalize(std::forward<Expansions>(es)...);
579 ([&res,
this](
const auto&... ps)
582 eset_.ps_.add_here(res.polynomials[l],
583 eset_.ps_.tuple(ps.second...));
586 eset_.normalize(res);
647 template <
typename... Expansions>
652 auto t = tuple_impl<Expansions...>{*
this};
653 return t.tuple(std::forward<Expansions>(es)...);
668 template <
typename ExpSet>
678 template <
typename Ctx1,
typename Ctx2>
687 return type(
vcsn::join(lhs.expressionset(), rhs.expressionset()));
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.
std::integral_constant< bool, B > bool_constant
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
static value_t conv(self_t, const value_t &v)
Conversion from (this and) other weightsets.
value_t conjunction(value_t l, value_t r) const
The conjunction of l and r.
std::enable_if_t< IsFree, value_t > complement_(const value_t &v) const
Complement on a free labelset.
#define VCSN_REQUIRE(Cond,...)
A macro similar to require.
value_t complement(const value_t &v) const
The complement of v.
label_t_of< context_t > label_t
const labelset_t & ls_
Shorthand to the labelset.
auto tuple(Expansions &&...es) const -> value_t
value_t lmul(const weight_t &w, const value_t &rhs) const
Left-multiplication by w of rhs.
value_t conv(const expansionset< OtherExpSet > &other, const typename expansionset< OtherExpSet >::value_t &v) const
Convert from another expansionset to self.
expressionset_t expressionset_t
void add_here(value_t &lhs, const value_t &rhs) const
In place addition.
Print as rich UTF-8 text, escaped.
void weight_set(welement< Label, Weight > &m, const Weight &w)
Set the weight of a welement.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
value_t & rmul_here(value_t &res, const expression_t &rhs) const
In place right multiplication by an expression.
auto denormalize(const Expansions &...es) const
Entry point: Denormalize all these expansions.
auto conjunction_(value_t lhs, value_t rhs, Conjunction conjunction) const -> std::enable_if_t<!detail::is_letterized_t< LabelSet >
The conjunction of l and r.
value_t rmul(const value_t &lhs, const weight_t &w) const
Right-multiplication of lhs by w.
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...
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.
variadic< type_t::conjunction, Context > conjunction
typename weightset_t::value_t weight_t
value_t infiltration(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 is. For instance, don't try to escape labels.
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print this valueset.
Denormalize a pack of one-tape expansions.
value_t one() const
The one.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
std::string type(const automaton &a)
The implementation type of a.
static symbol sname()
The static name.
An input/output format for valuesets.
value_t determinize(const value_t &v) const
Turn the polynomials into (normalized) monomials.
const expansionset & eset_
Provide a variadic mul on top of a binary mul(), and one().
An inner node with multiple children.
expressionset_t rs_
The expressionset used for the expressions.
auto weight_of(const welement< Label, Weight > &m) -> decltype(m.weight())
The weight of a welement.
context_t_of< expressionset_t > context_t
value_t add(const value_t &lhs, const value_t &rhs) const
Addition.
A structure that implements the computation of join(V1, V2).
std::enable_if_t<!IsFree, value_t > complement_(const value_t &) const
Cannot complement on a non-free labelset.
expansionset< ExpSet > make_expansionset(const ExpSet &expset)
void conjunctions_with_one_(value_t &, const value_t &, const value_t &, std::false_type, Conjunction) const
value_t & normalize(value_t &res) const
Normalize: move the constant term to the label one.
std::ostream & print(const value_t &v, std::ostream &o, format fmt={}) const
Print this expansion.
expansionset(const expressionset_t &rs)
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
auto normalize(const Aut &a) -> decltype(copy(a))
Normalize a automaton.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Print as plain (ASCII) text, escaped.
const context_t & context() const
The context.
static constexpr const char * me()
const weightset_t & ws_
Shorthand to the weightset.
constant< type_t::zero, Context > zero
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.
polynomialset_t ps_
The polynomialset for the polynomials.
static type join(const expansionset< expressionset< Ctx1 >> &lhs, const expansionset< expressionset< Ctx2 >> &rhs)
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.
typename polynomialset_t::monomial_t monomial_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Print as a parsable type string.
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
value_t & normalize_(value_t &res, std::false_type) const
Normalize when there is no label one: identity.
value_t & denormalize(value_t &res) const
Move the constant to the polynomial associated to one.
std::string to_string(identities i)
Wrapper around operator<<.
typename polynomialset_t::value_t polynomial_t
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
value_t & denormalize_(value_t &res, std::false_type) const
Denormalize when there is no label one: identity.
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.
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 l and r.
expression_polynomialset_t< ExpSet > make_expression_polynomialset(const ExpSet &rs)
From a ExpSet to its polynomialset.
value_t & lmul_here(const weight_t &w, value_t &res) const
Inplace left-multiplication by w of res.
value_t atom(const label_t &l) const
A single label.
const polynomialset_t & polynomialset() const
The polynomialset.
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
Implementation of nodes of tuple of rational expressions.
weightset_t_of< expressionset_t > weightset_t
auto project() const -> project_t< Tape >
The expansionsset for tape Tape.
value_t & ldiv_here(const weight_t &w, value_t &res) const
Inplace left-division by w of res.
zipped_maps< Dereference, Maps... > zip_maps(Maps &&...maps)
labelset_t_of< context_t > labelset_t
std::map< label_t, polynomial_t, vcsn::less< labelset_t >> polys_t
const expressionset_t & expressionset() const
The expressionset.