16 template <
typename ExpSet>
26 using weight_t =
typename weightset_t::value_t;
32 constexpr
static const char*
me() {
return "expansion"; }
37 using polys_t = std::map<label_t, polynomial_t, vcsn::less<labelset_t>>;
67 rs_.print_set(o, fmt);
72 std::ostream& print(const value_t& v, std::ostream& o,
73 format fmt = {}) const
76 if (!ws_.is_zero(v.constant) || v.polynomials.empty())
78 o << (fmt == format::latex ? "\\left\\langle " : "<");
79 ws_.print(v.constant, o, fmt.for_weights());
80 o << (fmt == format::latex ? "\\right\\rangle " : ">");
83 for (const auto& p: v.polynomials)
86 o << (fmt == format::latex ? " \\oplus " : " + ");
88 ls_.print(p.first, o, fmt.for_labels());
89 o << (fmt == format::latex ? " \\odot \\left[" : ".[");;
90 ps_.print(p.second, o, fmt);
91 o << (fmt == format::latex ? "\\right]" : "]");;
97 value_t& normalize(value_t& res) const
99 auto has_one = bool_constant<context_t::has_one()>();
100 return normalize_(res, has_one);
106 value_t& normalize_(value_t& res, std::true_type) const
108 auto one = ls_.one();
109 auto i = res.polynomials.find(one);
110 if (i != std::end(res.polynomials))
112 auto j = i->second.find(rs_.one());
113 if (j != std::end(i->second))
115 res.constant = ws_.add(res.constant, weight_of(*j));
117 if (i->second.empty())
118 res.polynomials.erase(i);
125 value_t& normalize_(value_t& res, std::false_type) const
131 value_t& denormalize(value_t& res) const
133 auto has_one = bool_constant<context_t::has_one()>();
134 return denormalize_(res, has_one);
139 value_t& denormalize_(value_t& res, std::true_type) const
141 if (!ws_.is_zero(res.constant))
143 auto one = ls_.one();
144 ps_.add_here(res.polynomials[one],
145 polynomial_t{{rs_.one(), res.constant}});
146 res.constant = ws_.zero();
152 value_t& denormalize_(value_t& res, std::false_type) const
160 return {ws_.zero(), polys_t{}};
166 return {ws_.one(), polys_t{}};
170 value_t atom(const label_t& l) const
172 return {ws_.zero(), {{l, ps_.one()}}};
176 void add_here(value_t& lhs, const value_t& rhs) const
178 lhs.constant = ws_.add(lhs.constant, rhs.constant);
179 for (const auto& p: rhs.polynomials)
180 ps_.add_here(lhs.polynomials[p.first], p.second);
184 value_t& lmul_here(const weight_t& w, value_t& res) const
186 res.constant = ws_.mul(w, res.constant);
187 for (auto& p: res.polynomials)
188 p.second = ps_.lmul(w, p.second);
193 value_t rmul(const value_t& lhs, const weight_t& w) const
195 value_t res = {ws_.mul(lhs.constant, w), polys_t{}};
196 for (auto& p: lhs.polynomials)
197 for (const auto& m: p.second)
198 ps_.add_here(res.polynomials[p.first],
199 rs_.rmul(label_of(m), w), weight_of(m));
204 value_t& rmul_here(value_t& res, const expression_t& rhs) const
206 for (auto& p: res.polynomials)
207 p.second = ps_.rmul_label(p.second, rhs);
212 value_t& ldiv_here(const weight_t& w, value_t& res) const
214 res.constant = ws_.ldiv(w, res.constant);
215 for (auto& p: res.polynomials)
216 for (auto&& m: p.second)
217 weight_set(m, ws_.ldiv(w, weight_of(m)));
218 return normalize(res);
222 template <typename Conjunction>
224 conjunctions_with_one_(value_t&,
225 const value_t&, const value_t&,
230 template <typename Conjunction>
232 conjunctions_with_one_(value_t& res,
233 const value_t& l, const value_t& r,
235 Conjunction conjunction) const
237 // Spontaneous transitions from the lhs.
238 auto one = ls_.one();
240 auto i = l.polynomials.find(one);
241 if (i != std::end(l.polynomials))
242 for (const auto& rhs: r.polynomials)
243 if (!ls_.is_one(rhs.first))
244 ps_.add_here(res.polynomials[one],
245 conjunction(i->second,
246 ps_.lmul_label(rs_.atom(rhs.first),
249 // Spontaneous transitions from the rhs.
251 auto i = r.polynomials.find(one);
252 if (i != std::end(r.polynomials))
253 for (const auto& lhs: l.polynomials)
254 if (!ls_.is_one(lhs.first))
255 ps_.add_here(res.polynomials[one],
256 conjunction(ps_.lmul_label(rs_.atom(lhs.first),
265 template <typename LabelSet = labelset_t, typename Conjunction>
266 auto conjunction_(value_t l, value_t r,
267 Conjunction conjunction) const
268 -> enable_if_t<detail::is_letterized_t<LabelSet>{},
271 value_t res = zero();
274 res.constant = ws_.mul(l.constant, r.constant);
275 for (const auto& p: zip_maps(l.polynomials, r.polynomials))
276 res.polynomials[p.first]
277 = conjunction(std::get<0>(p.second), std::get<1>(p.second));
279 auto has_one = bool_constant<context_t::has_one()>();
280 conjunctions_with_one_(res, l, r, has_one, conjunction);
288 template <typename LabelSet = labelset_t, typename Conjunction>
289 auto conjunction_(value_t lhs, value_t rhs,
290 Conjunction conjunction) const
291 -> enable_if_t<!detail::is_letterized_t<LabelSet>{},
294 value_t res = zero();
295 res.constant = ws_.mul(lhs.constant, rhs.constant);
296 for (const auto& l: lhs.polynomials)
297 for (const auto& r: rhs.polynomials)
299 // The longest common prefix.
300 auto lcp = ls_.lgcd(l.first, r.first);
301 if (!ls_.is_one(lcp))
303 auto left = rs_.atom(ls_.ldiv(lcp, l.first));
304 auto right = rs_.atom(ls_.ldiv(lcp, r.first));
305 ps_.add_here(res.polynomials[lcp],
306 conjunction(ps_.lmul_label(left, l.second),
307 ps_.lmul_label(right, r.second)));
314 template <typename Shuffle>
315 value_t& shuffle_(value_t& res,
316 const value_t& lhs_xpn, const expression_t& lhs_xpr,
317 const value_t& rhs_xpn, const expression_t& rhs_xpr,
318 Shuffle shuffle) const
320 // (i) lhs_xpn:rhs_xpr.
321 for (const auto& p: lhs_xpn.polynomials)
322 for (const auto& m: p.second)
323 ps_.add_here(res.polynomials[p.first],
324 shuffle(label_of(m), rhs_xpr), weight_of(m));
325 // (ii) lhs_xpr:rhs_xpn
326 for (const auto& p: rhs_xpn.polynomials)
327 for (const auto& m: p.second)
328 ps_.add_here(res.polynomials[p.first],
329 shuffle(lhs_xpr, label_of(m)), weight_of(m));
336 value_t conjunction(value_t l, value_t r) const
338 return conjunction_(l, r,
339 [this](const polynomial_t& l,
340 const polynomial_t& r)
342 return ps_.conjunction(l, r);
347 value_t shuffle(const value_t& lhs_xpn, const expression_t& lhs_xpr,
348 const value_t& rhs_xpn, const expression_t& rhs_xpr) const
351 res.constant = ws_.mul(lhs_xpn.constant, rhs_xpn.constant);
353 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
354 [this](const expression_t& l, const expression_t& r)
356 return rs_.shuffle(l, r);
361 value_t infiltration(const value_t& lhs_xpn, const expression_t& lhs_xpr,
362 const value_t& rhs_xpn, const expression_t& rhs_xpr) const
364 // Conjunction part: lhs_xpn&:rhs_xpn.
366 conjunction_(lhs_xpn, rhs_xpn,
367 [this](const polynomial_t& l, const polynomial_t& r)
369 return ps_.infiltration(l, r);
372 // Shuffle part: lhs_xpn&:rhs_xpr + lhs_xpr&:rhs_xpn.
374 lhs_xpn, lhs_xpr, rhs_xpn, rhs_xpr,
375 [this](const expression_t& l, const expression_t& r)
377 return rs_.infiltration(l, r);
387 value_t complement(const value_t& v) const
389 // Complement requires a free labelset.
390 return complement_<labelset_t::is_free()>(v);
395 template <bool IsFree>
396 vcsn::enable_if_t<!IsFree, value_t>
397 complement_(const value_t&) const
399 raise(me(), ": cannot handle complement without generators");
403 template <bool IsFree>
404 vcsn::enable_if_t<IsFree, value_t>
405 complement_(const value_t& v) const
408 res.constant = ws_.is_zero(v.constant) ? ws_.one() : ws_.zero();
410 // Turn the polynomials into expressions, and complement them.
411 for (auto l: ls_.genset())
413 auto i = v.polynomials.find(l);
415 ps_.complement(i == end(v.polynomials) ? ps_.zero() : i->second);
423 determinize(const value_t& v) const
426 res.constant = v.constant;
427 for (const auto& lp: v.polynomials)
428 res.polynomials[lp.first] = {ps_.determinize(lp.second)};
437 template <unsigned Tape>
439 = expansionset<typename expressionset_t::template focus_t<Tape>>;
442 template <unsigned Tape>
446 return {detail::make_project<Tape>(rs_)};
450 template <typename... Expansions>
454 template <size_t Tape>
455 void denormalize_tape(typename focus_t<Tape>::value_t& e)
457 auto es = eset_.template focus<Tape>();
459 require(es.expressionset().weightset()->is_zero(e.constant),
460 es, ": to-expansion: cannot denormalize ", to_string(es, e),
461 ", need support for label one (the empty label)");
465 template <size_t... Tape>
466 void denormalize(std::tuple<Expansions&...>& es,
467 detail::index_sequence<Tape...>)
469 using swallow = int[];
472 (denormalize_tape<Tape>(std::get<Tape>(es)), 0)...
477 void denormalize(Expansions&... es)
479 auto t = std::tuple<Expansions&...>{es...};
481 detail::make_index_sequence<sizeof...(Expansions)>{});
484 const expansionset& eset_;
541 template <typename... Expansions>
543 tuple(Expansions&&... es) const
547 tuple_impl<Expansions...>{*this}.denormalize(es...);
548 detail::cross([&res, this](const auto&... ps)
550 auto l = label_t{ps.first...};
551 ps_.add_here(res.polynomials[l],
552 ps_.tuple(ps.second...));
563 const labelset_t& ls_ = *rs_.labelset();
565 const weightset_t& ws_ = *rs_.weightset();
567 polynomialset_t ps_ = make_expression_polynomialset(rs_);
std::map< label_t, polynomial_t, vcsn::less< labelset_t >> polys_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
labelset_t_of< context_t > labelset_t
label_t_of< context_t > label_t
static symbol sname()
The static name.
typename expressionset_t::value_t expression_t
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
expansionset(const expressionset_t &rs)
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
const expressionset_t & expressionset() const
The expressionset.
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print this valueset.
expressionset_t expressionset_t
Provide a variadic mul on top of a binary mul(), and one().
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
weightset_t_of< expressionset_t > weightset_t
expressionset_t rs_
The expressionset used for the expressions.
typename polynomialset_t::value_t polynomial_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
typename polynomialset_t::monomial_t monomial_t
context_t_of< expressionset_t > context_t
static constexpr const char * me()
typename weightset_t::value_t weight_t