32 :
public lazy_tuple_automaton<product_automaton_impl<Lazy, Aut, Auts...>, false, Lazy, Aut, Auts...>
35 "product: requires letterized labels");
47 template <Automaton A>
50 template <
size_t... I>
52 =
typename tuple_automaton_t::element_type::template seq<I...>;
55 using super_t::transition_maps_;
59 static symbol res(
"product_automaton"
60 + super_t::sname_(std::string{Lazy ?
"true" :
"false"}));
66 o <<
"product_automaton";
67 return aut_->print_set_(o, fmt);
75 using label_t =
typename labelset_t::value_t;
76 using weight_t =
typename weightset_t::value_t;
97 initialize_conjunction();
100 while (!
aut_->todo_.empty())
102 const auto& p =
aut_->todo_.front();
104 aut_->todo_.pop_front();
111 initialize_shuffle();
113 while (!
aut_->todo_.empty())
115 const auto& p =
aut_->todo_.front();
116 add_shuffle_transitions<false>(std::get<1>(p), std::get<0>(p));
117 aut_->todo_.pop_front();
142 "infiltration: variadic product does not work");
147 initialize_shuffle();
149 while (!
aut_->todo_.empty())
151 const auto& p =
aut_->todo_.front();
157 add_conjunction_transitions(std::get<1>(p), std::get<0>(p));
158 add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
160 aut_->todo_.pop_front();
165 void add_transitions(
const state_t src,
168 add_conjunction_transitions(src, psrc);
174 void initialize_conjunction()
181 void initialize_shuffle()
185 add_conjunction_transitions(
aut_->pre(),
aut_->pre_());
190 using super_t::state;
195 void add_conjunction_transitions(
const state_t src,
203 if (!
aut_->labelset()->is_one(t.first))
213 add_one_transitions_(src, psrc,
aut_->indices);
218 template <std::size_t... I>
223 using swallow =
int[];
226 (maybe_add_one_transitions_<I>(*(std::get<I>(
aut_->auts_)->
labelset()),
232 template <std::
size_t I,
typename L>
233 std::enable_if_t<!L::has_one(), void>
239 template <std::
size_t I,
typename L>
240 std::enable_if_t<L::has_one(), void>
241 maybe_add_one_transitions_(
const L& ls,
const state_t src,
244 if (!has_one_in(psrc, I + 1,
aut_->indices)
245 && !has_only_one_out(psrc, I,
aut_->indices))
249 if (!tmap.empty() && ls.is_one(tmap.begin()->first))
250 for (
auto t : tmap.begin()->second)
253 std::get<I>(pdst) = t.dst;
254 this->new_transition(src,
state(pdst), ls.one(), t.weight());
261 template <std::size_t... I>
262 bool has_one_in(
const state_name_t& psrc, std::size_t i,
265 bool has_ones[] = { is_spontaneous_in(std::get<I>(
aut_->auts_),
266 std::get<I>(psrc))... };
267 for (; i <
sizeof...(Auts); ++i)
275 template <std::size_t... I>
276 bool has_only_one_out(
const state_name_t& psrc, std::size_t i,
279 bool has_ones[] = { has_only_ones_out<I>(psrc)... };
280 for (
size_t j = 0; j < i; ++j)
288 template <Automaton Aut_>
289 std::enable_if_t<labelset_t_of<Aut_>::has_one(),
bool>
292 return aut->labelset()->is_one(aut->label_of(tr));
297 template <Automaton Aut_>
298 constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(),
bool>
307 template <Automaton Aut_>
308 constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(),
bool>
309 is_spontaneous_in(
const Aut_&,
319 template <Automaton Aut_>
320 std::enable_if_t<labelset_t_of<Aut_>::has_one(),
bool>
323 auto rin =
all_in(rhs, rst);
324 auto rtr = rin.begin();
325 return rtr != rin.end() && is_one(rhs, *rtr);
335 auto s = tmap.size();
341 return std::get<I>(
aut_->auts_)->
labelset()->is_one(tmap.begin()->first);
348 template <
bool Infiltration = false>
349 void add_shuffle_transitions(
const state_t src,
353 = add_shuffle_transitions_<Infiltration>(src, psrc,
aut_->indices);
354 aut_->set_final(src,
final);
361 template <
bool Infiltration,
size_t... I>
367 using swallow =
int[];
371 add_shuffle_transitions_<Infiltration, I>(src, psrc)),
387 template <
bool Infiltration,
size_t I>
389 add_shuffle_transitions_(
const state_t src,
397 if (std::get<I>(
aut_->auts_)->labelset()->is_special(t.first))
398 res = t.second.front().weight();
410 for (
auto d: t.second)
413 std::get<I>(pdst) = d.dst;
415 || std::get<I>(psrc) == d.dst)
437 return make_shared_ptr<res_t>(aut, auts...);
448 conjunction(
const Auts&... as)
452 auto res = make_product_automaton<false>(
meet_automata(as...),
465 auto res = make_product_automaton<true>(
meet_automata(as...),
475 template <std::
size_t I, Automaton Aut>
478 -> std::enable_if_t<labelset_t_of<Aut>::has_one() && I != 0,
484 template <std::
size_t I, Automaton Aut>
485 std::enable_if_t<!labelset_t_of<Aut>::has_one() || I == 0, Aut&>
492 template <
typename Auts,
size_t... I>
508 template <
typename Auts,
typename Bool>
510 conjunction(
const std::vector<automaton>& as,
bool lazy)
514 return conjunction_<Auts>(as, lazy, indices);
527 shuffle(
const Auts&... as)
531 auto res = make_product_automaton<false>(
join_automata(as...), as...);
541 template <
typename Auts,
size_t... I>
551 template <
typename Auts>
553 shuffle(
const std::vector<automaton>& as)
557 return shuffle_<Auts>(as, indices);
568 template <
typename ValueSet>
569 typename ValueSet::value_t
570 shuffle(
const ValueSet& vs,
571 const typename ValueSet::value_t& lhs,
572 const typename ValueSet::value_t& rhs)
574 return vs.shuffle(lhs, rhs);
582 template <
typename ExpSetLhs,
typename ExpSetRhs>
586 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
589 std::get<1>(join_elts),
590 std::get<2>(join_elts)));
601 template <Automaton A1, Automaton A2>
603 infiltration(
const A1& a1,
const A2& a2)
607 auto res = make_product_automaton<false>(
join_automata(a1, a2), a1, a2);
615 infiltration(
const A1& a1,
const A2& a2,
const A3& a3,
const Auts&... as)
616 -> decltype(infiltration(infiltration(a1, a2), a3, as...))
618 return infiltration(infiltration(a1, a2), a3, as...);
626 template <
typename Auts,
size_t... I>
637 template <
typename Auts>
639 infiltration(
const std::vector<automaton>& as)
643 return infiltration_<Auts>(as, indices);
653 template <
typename ValueSet>
654 typename ValueSet::value_t
655 infiltration(
const ValueSet& vs,
656 const typename ValueSet::value_t& lhs,
657 const typename ValueSet::value_t& rhs)
659 return vs.infiltration(lhs, rhs);
667 template <
typename ExpSetLhs,
typename ExpSetRhs>
671 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
674 std::get<1>(join_elts),
675 std::get<2>(join_elts)));
685 template <Automaton Aut>
687 conjunction(
const Aut& aut,
unsigned n)
693 auto s = res->new_state();
696 for (
auto l: res->context().labelset()->generators())
697 res->new_transition(s, s, l);
703 static bool iterative = getenv(
"VCSN_ITERATIVE");
705 for (
size_t i = 0; i < n; ++i)
706 res =
strip(conjunction(res, aut));
709 auto power =
strip(aut);
713 res =
strip(conjunction(res, power));
717 power =
strip(conjunction(power, power));
731 template <Automaton Aut,
typename Un
signed>
735 const auto& a = aut->as<Aut>();
746 template <
typename ValueSet>
747 typename ValueSet::value_t
748 conjunction(
const ValueSet&
rs,
749 const typename ValueSet::value_t& lhs,
750 const typename ValueSet::value_t& rhs)
752 return rs.conjunction(lhs, rhs);
764 template <
typename ExpSetLhs,
typename ExpSetRhs>
768 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
771 std::get<1>(join_elts),
772 std::get<2>(join_elts)));
786 template <
typename PolynomialSetLhs,
typename PolynomialSetRhs>
790 auto join_elts = join<PolynomialSetLhs, PolynomialSetRhs>(lhs, rhs);
793 std::get<1>(join_elts),
794 std::get<2>(join_elts)));
std::shared_ptr< detail::tuple_automaton_impl< Auts...>> tuple_automaton
A tuple automaton as a shared pointer.
std::shared_ptr< detail::product_automaton_impl< Lazy, Aut, Auts...>> product_automaton
A product automaton as a shared pointer.
auto infiltration(const A1 &a1, const A2 &a2) -> tuple_automaton< decltype(join_automata(a1, a2)), A1, A2 >
The (accessible part of the) infiltration product.
Decorator implementing the laziness for an algorithm.
weightset_t_of< Aut > weightset_t
state_t_of< automaton_t > state_t
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction.
std::remove_cv_t< std::remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
state_t state(Args &&...args)
Conversion from state name to state number.
auto labelset(Args &&...args) const -> decltype(aut_-> labelset(std::forward< Args >(args)...))
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
typename context_t::labelset_t labelset_t
std::shared_ptr< const node< Context >> expression
Aut automaton_t
The type of automaton to wrap.
automaton_t aut_
The wrapped automaton, possibly const.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
An input/output format for valuesets.
autodecltype(insplit(aut)) std::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
auto insplit(Aut &aut) -> std::enable_if_t< labelset_t_of< Aut >::has_one(), decltype(make_insplit_automaton(aut))>
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
std::enable_if_t< L, void > complete_(state_t s) const
Complete a state: find its outgoing transitions.
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
void cross_tuple(Fun f, const std::tuple< Ts...> &ts)
Cache the outgoing transitions of an automaton as efficient maps label -> vector<(weight, dst)>.
polynomial conjunction_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (conjunction).
typename labelset_t::value_t label_t
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
Build the (accessible part of the) product.
Aggregate an automaton, and forward calls to it.
std::tuple< transition_map_t< Auts >...> transition_maps_
Transition caches.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
static constexpr auto sname(Args &&...args) -> decltype(element_type::sname(std::forward< Args >(args)...))
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
An automaton whose type is the join between those of auts.
auto all_in(Args &&...args) const -> decltype(aut_-> all_in(std::forward< Args >(args)...))
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).
auto print_set(Args &&...args) const -> decltype(aut_-> print_set(std::forward< Args >(args)...))
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
An automaton whose type is the meet between those of auts.
lazy_tuple_automaton self_t
auto new_transition(Args &&...args) -> decltype(aut_-> new_transition(std::forward< Args >(args)...))
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I...>)
Bridge helper.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
tuple_automaton< Aut, Auts...> tuple_automaton_t
The underlying automaton, output and inputs.
std::shared_ptr< const detail::polynomial_base > polynomial
typename tuple_automaton_t::element_type::state_name_t state_name_t
zipped_maps< Dereference, Maps...> zip_map_tuple(const std::tuple< Maps...> &maps)
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Outgoing signature: weight, destination.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts...>
The (accessible part of the) shuffle product.
std::shared_ptr< detail::expression_base > expression
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
automaton_t strip()
The automaton we decorate.
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
typename weightset_t::value_t weight_t
typename tuple_automaton_t::element_type::template seq< I...> seq
const weightset_t & ws_
The resulting weightset.
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Lazy, Aut, Auts...>
auto conjunction_lazy(const Auts &...as) -> product_automaton< true, decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction, on-the-fly.
std::shared_ptr< detail::automaton_base > automaton