5 #include <vcsn/algos/fwd.hh>
26 template <
typename Context>
30 , identities_(identities)
35 template <
typename Context>
40 "series (currently) depend on weightset commutativity");
44 template <typename Context> \
47 ratexpset_impl<Context>
73 res +=
context().vname(full) +
'>';
77 DEFINE::make(std::istream&
is)
81 eat(
is,
"ratexpset<");
82 auto ctx = Context::make(
is);
94 DEFINE::open(
bool o)
const
97 return this->labelset()->open(o);
110 DEFINE::is_series() const ->
bool
117 return ctx_.labelset();
122 return ctx_.weightset();
128 if (labelset_t::is_one(v))
130 return std::make_shared<atom_t>(v);
136 return std::make_shared<zero_t>();
142 return std::make_shared<one_t>();
145 template <
typename Context>
152 static bool binary = !! getenv(
"VCSN_BINARY");
160 template <
typename Context>
168 gather_<Type>(res, l);
169 gather_<Type>(res,
r);
184 else if (is_series())
185 res = add_nonzero_series_(l,
r);
187 res = std::make_shared<sum_t>(gather_<type_t::sum>(l,
r));
194 return less_than(unwrap_possible_lweight_(l), unwrap_possible_lweight_(
r));
198 typename values_t::iterator i)
const
201 switch (addends.size())
212 return std::make_shared<sum_t>(std::move(addends));
222 assert(copy.size() > 0);
225 const auto& ws = weightset();
226 auto rw = possibly_implicit_lweight_(
r);
227 auto rn = unwrap_possible_lweight_(
r);
231 return less_than_ignoring_weight_(l,
r);
233 const auto i = std::lower_bound(copy.begin(), copy.end(), rn, closure);
235 && equals(unwrap_possible_lweight_(*i), rn))
238 const weight_t& iw = possibly_implicit_lweight_(*i);
241 return remove_from_sum_series_(std::move(copy), i);
248 return std::make_shared<sum_t>(std::move(copy));
255 for (
const auto& e: addends1)
256 res = add_nonzero_series_(res, e);
263 assert(! is_zero(
r));
269 return merge_sum_series_(*ls,
r);
271 return insert_in_sum_series_(*ls,
r);
274 return add_nonzero_series_(
r, l);
278 auto ls = std::make_shared<sum_t>(
values_t{l});
279 return insert_in_sum_series_(*ls,
r);
283 DEFINE::type_ignoring_lweight_(
value_t e)
const
286 return unwrap_possible_lweight_(e)->type();
289 DEFINE::possibly_implicit_lweight_(
value_t e)
const
292 if (
auto lw = std::dynamic_pointer_cast<const lweight_t>(e))
295 return weightset()->one();
298 DEFINE::unwrap_possible_lweight_(
value_t e)
const
301 if (
auto lw = std::dynamic_pointer_cast<const lweight_t>(e))
311 return mul_series_(l,
r);
313 return mul_expressions_(l,
r);
319 return mul_(l,
r,
false);
325 return mul_(l,
r,
true);
340 res = rmul(l, possibly_implicit_lweight_(
r));
343 res = lmul(possibly_implicit_lweight_(l),
r);
346 res = nontrivial_mul_series_(l,
r);
348 res = nontrivial_mul_expressions_(l,
r);
352 DEFINE::is_unweighted_nonsum_(
value_t v)
const
370 return is_unweighted_nonsum_(unwrap_possible_lweight_(v));
382 return atom(labelset()->concat(a, b));
394 assert(! is_zero(a));
395 assert(! is_zero(
b));
398 assert(! std::dynamic_pointer_cast<const lweight_t>(a));
399 assert(! std::dynamic_pointer_cast<const lweight_t>(
b));
411 assert(! is_zero(a));
412 assert(! is_zero(
b));
413 value_t na = unwrap_possible_lweight_(a), nb = unwrap_possible_lweight_(
b);
416 return lmul(possibly_implicit_lweight_(a),
b);
418 return lmul(weightset()->mul(possibly_implicit_lweight_(a),
419 possibly_implicit_lweight_(
b)),
422 return lmul(weightset()->mul(possibly_implicit_lweight_(a),
423 possibly_implicit_lweight_(
b)),
424 mul_unweighted_nontrivial_products_(na, nb));
430 return std::make_shared<prod_t>(gather_<type_t::prod>(l,
r));
439 const auto& lt = type_ignoring_lweight_(l), rt = type_ignoring_lweight_(
r);
443 for (
const auto& la: *down_pointer_cast<const sum_t>(l))
444 res = add(res, mul(la,
r));
447 for (
const auto& ra: *down_pointer_cast<const sum_t>(
r))
448 res = add(res, mul(l, ra));
450 else if (is_nonsum_(l) && is_nonsum_(
r))
451 return mul_products_(l,
r);
454 weight_t lw = possibly_implicit_lweight_(l)
455 , rw = possibly_implicit_lweight_(
r);
456 value_t nl = unwrap_possible_lweight_(l)
457 , nr = unwrap_possible_lweight_(
r);
458 return lmul(weightset()->mul(lw, rw),
459 std::make_shared<prod_t>(gather_<type_t::prod>(nl, nr)));
477 res = lmul(weightset()->mul(possibly_implicit_lweight_(l),
478 possibly_implicit_lweight_(
r)),
488 if (labelset()->equals(lhs, rhs))
489 res = rmul(l, possibly_implicit_lweight_(
r));
494 else if ( (type_ignoring_lweight_(l) ==
type_t::one
501 res = std::make_shared<conjunction_t>(gather_<type_t::conjunction>(l,
r));
519 res = std::make_shared<ldiv_t>(
values_t{l,
r});
547 res = std::make_shared<shuffle_t>(gather_<type_t::shuffle>(l,
r));
561 return mul_expressions_(l, r);
577 gather_<type_t::prod>(ls, l);
580 gather_<type_t::prod>(rs,
r);
585 auto lhs = std::dynamic_pointer_cast<
const atom_t>(ls.back());
586 auto rhs = std::dynamic_pointer_cast<
const atom_t>(rs.front());
587 ls.back() =
atom(labelset()->concat(lhs->value(), rhs->value()));
588 ls.insert(ls.end(), rs.begin() + 1, rs.end());
591 ls.insert(ls.end(), rs.begin(), rs.end());
595 return std::make_shared<prod_t>(ls);
599 return mul_expressions_(l, r);
611 value_t res = std::make_shared<star_t>(e);
613 "star argument ", e,
" not starrable");
623 if (
auto w = std::dynamic_pointer_cast<const lweight_t>(e))
625 else if (
auto w = std::dynamic_pointer_cast<const rweight_t>(e))
628 return std::make_shared<complement_t>(e);
643 else if (
auto l = std::dynamic_pointer_cast<const atom_t>(e))
644 res =
atom(labelset()->transpose(l->value()));
647 res = std::make_shared<transposition_t>(e);
659 if (e->type() ==
type_t::zero || weightset()->is_one(w))
662 else if (weightset()->is_zero(w))
665 else if (
auto lw = std::dynamic_pointer_cast<const lweight_t>(e))
666 return lmul(weightset()->mul(w, lw->weight()), lw->sub());
675 addends.emplace_back(lmul(w, a));
676 return std::make_shared<sum_t>(std::move(addends));
679 return std::make_shared<lweight_t>(w, e);
686 if (weightset()->is_zero(w))
689 else if (weightset()->is_one(w))
691 else if (e->is_leaf())
695 else if (
auto lw = std::dynamic_pointer_cast<const lweight_t>(e))
696 return lmul(lw->weight(), rmul(lw->sub(), w));
698 else if (
auto rw = std::dynamic_pointer_cast<const rweight_t>(e))
699 return rmul(rw->sub(), weightset()->mul(rw->weight(), w));
709 res = add(res, rmul(a, w));
714 return std::make_shared<rweight_t>(w, e);
737 size_t l = sizer(lhs),
r = sizer(rhs);
770 return copy(rs, *
this, v);
773 template <
typename Context>
774 template <
typename GenSet>
781 return atom(labelset()->
conv(ls, v));
793 return lmul(weightset()->
conv(ws, v),
one());
799 return lmul(weightset()->
conv(ws, v),
one());
805 return lmul(weightset()->
conv(ws, v),
one());
811 return lmul(weightset()->
conv(ws, v),
one());
814 template <
typename Context>
815 template <
typename Ctx2>
822 return copy(rs, *
this,
r);
829 const auto& res = dynres->template as<ratexpset_impl>();
838 printer_t
print(*
this, o);
839 print.format(format);
850 template <
typename Context>
851 template <
typename... Args>
857 return letter_class_<labelset_t>(std::forward<Args>(args)...,
858 std::is_same<labelset_t, vcsn::oneset>{});
861 template <
typename Context>
862 template <
typename LabelSet_>
867 typename LabelSet_::letter_t>> ccs,
869 std::false_type)
const
873 auto gens = labelset()->genset();
880 for (
const auto& cc: ccs)
882 auto i =
std::find(std::begin(gens), std::end(gens), cc.first);
883 auto end =
std::find(i, std::end(gens), cc.second);
885 "invalid letter interval: ",
886 to_string(*labelset(), labelset()->value(std::get<0>(cc))),
888 to_string(*labelset(), labelset()->value(std::get<1>(cc))));
889 for (end = std::next(end); i != end; ++i)
890 res = add(res,
atom(labelset()->value(*i)));
893 else if (ccs.empty())
895 res = add(res,
atom(labelset()->value(l)));
900 std::set<typename LabelSet_::letter_t> accepted;
901 for (
const auto& cc: ccs)
903 auto i =
std::find(std::begin(gens), std::end(gens), cc.first);
904 auto end =
std::find(i, std::end(gens), cc.second);
906 "invalid letter interval: ",
907 to_string(*labelset(), labelset()->value(std::get<0>(cc))),
909 to_string(*labelset(), labelset()->value(std::get<1>(cc))));
910 for (end = std::next(end); i != end; ++i)
911 accepted.emplace(*i);
914 if (!
has(accepted, c))
915 res = add(res,
atom(labelset()->value(c)));
918 "invalid empty letter class");
922 template <
typename Context>
923 template <
typename LabelSet_,
typename... Args>
927 std::true_type) const
variadic< type_t::ldiv, Context > ldiv
unary< type_t::complement, Context > complement
typename node_t::values_t values_t
A list (vector) of ratexps.
An inner node with multiple children.
typename node_t::type_t type_t
Type tag for AST classes.
OutRatExpSet::value_t copy(const InRatExpSet &in_rs, const OutRatExpSet &out_rs, const typename InRatExpSet::value_t &v)
ratexpset make_ratexpset(const context &ctx,::vcsn::rat::identities is)
Build an ratexpset from its context.
unary< type_t::transposition, Context > transposition
typename node_t::value_t value_t
A ratexp (a shared pointer to a tree).
std::string to_string(identities i)
void require_weightset_commutativity() const
void gather_(values_t &res, value_t v) const
Push v in res, applying associativity if possible.
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
boost::flyweight< std::string, boost::flyweights::no_tracking > symbol
An internalized string.
typename context_t::labelset_ptr labelset_ptr
variadic_mul_mixin< detail::b_impl > b
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.
bool is_valid(const Aut &aut)
typename weightset_t::value_t weight_t
typename context_t::weightset_ptr weightset_ptr
label_t_of< context_t > label_t
std::ostream & print(const ValueSet &vs, const typename ValueSet::value_t &v, std::ostream &o, const std::string &format)
Applies to (ValueSet, Value, ostream, string): for expansionset, polynomialset, ratexpset, and weightset.
type_t
The possible types of ratexps.
value_t letter_class(Args &&...chars) const
A ratexp matching one character amongst chars.
#define down_pointer_cast
Trivial identities plus series identities.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
ratexpset_impl(const context_t &ctx, identities_t identities)
Constructor.
std::istringstream is
The input stream: the specification to translate.
constant< type_t::one, Context > one
constant< type_t::zero, Context > zero
Provide a variadic mul on top of a binary mul(), and one().
std::shared_ptr< const detail::context_base > context
Aut transpose(const transpose_automaton< Aut > &aut)
char eat(std::istream &is, char c)
Check lookahead character and advance.
ratexp read_ratexp(std::istream &is, const ratexpset &rs, const std::string &format="default")
Read a ratexp from a stream.
Implementation of labels are letters.
value_t letter_class_(const Args &&...chars, std::true_type) const
If labelset is oneset.
RatExpSet::value_t less_than(const RatExpSet &rs, const typename RatExpSet::value_t &v)
identities
A ratexpset can implement several different sets of identities on expressions.
value_t conv(const letterset< GenSet > &ls, typename letterset< GenSet >::value_t v) const
variadic_mul_mixin< detail::r_impl > r
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
ATTRIBUTE_PURE auto find(const std::vector< T, Alloc > &s, const T &e) -> typename std::vector< T, Alloc >::const_iterator
Convenience wrapper around std::find.