34 :
public lazy_tuple_automaton<product_automaton_impl<Lazy, Aut, Auts...>, false, Lazy, Aut, Auts...>
37 "product: requires letterized labels");
49 template <Automaton A>
52 template <
size_t... I>
54 =
typename tuple_automaton_t::element_type::template
seq<I...>;
61 static symbol res(
"product_automaton"
68 o <<
"product_automaton";
69 return aut_->print_set_(o, fmt);
77 using label_t =
typename labelset_t::value_t;
78 using weight_t =
typename weightset_t::value_t;
102 while (!
aut_->todo_.empty())
104 const auto& p =
aut_->todo_.front();
106 aut_->todo_.pop_front();
113 template <
bool L = Lazy>
119 auto new_initials = std::vector<state_t_of<rhs_t>>();
121 const auto& lhs = std::get<0>(
aut_->auts_);
122 auto& rhs = std::get<1>(
aut_->auts_);
124 while (!
aut_->todo_.empty())
126 const auto& p =
aut_->todo_.front();
127 const auto& state_name = std::get<0>(p);
131 if (lhs->is_final(std::get<0>(state_name)))
132 new_initials.push_back(std::get<1>(state_name));
133 aut_->todo_.pop_front();
137 rhs->unset_initial(rhs->dst_of(t));
138 for (
auto s: new_initials)
147 while (!
aut_->todo_.empty())
149 const auto& p =
aut_->todo_.front();
150 add_shuffle_transitions<false>(std::get<1>(p), std::get<0>(p));
151 aut_->todo_.pop_front();
176 "infiltration: variadic product does not work");
183 while (!
aut_->todo_.empty())
185 const auto& p =
aut_->todo_.front();
192 add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
194 aut_->todo_.pop_front();
237 if (!
aut_->labelset()->is_one(t.first))
244 ws_.mul(ts.weight()...));
252 template <std::size_t... I>
257 using swallow =
int[];
260 (maybe_add_one_transitions_<I>(*(std::get<I>(
aut_->auts_)->
labelset()),
266 template <std::
size_t I,
typename L>
267 std::enable_if_t<!L::has_one(), void>
273 template <std::
size_t I,
typename L>
274 std::enable_if_t<L::has_one(), void>
283 if (!tmap.empty() && ls.is_one(tmap.begin()->first))
284 for (
auto t : tmap.begin()->second)
287 std::get<I>(pdst) = t.dst;
288 this->new_transition(src,
state(pdst), ls.one(), t.weight());
295 template <std::size_t... I>
300 std::get<I>(psrc))... };
301 for (; i <
sizeof...(Auts); ++i)
309 template <std::size_t... I>
313 bool has_ones[] = { has_only_ones_out<I>(psrc)... };
314 for (
size_t j = 0; j < i; ++j)
322 template <Automaton Aut_>
323 std::enable_if_t<labelset_t_of<Aut_>::has_one(),
bool>
326 return aut->labelset()->is_one(aut->label_of(tr));
331 template <Automaton Aut_>
332 constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(),
bool>
341 template <Automaton Aut_>
342 constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(),
bool>
353 template <Automaton Aut_>
354 std::enable_if_t<labelset_t_of<Aut_>::has_one(),
bool>
357 auto rin =
all_in(rhs, rst);
358 auto rtr = rin.begin();
359 return rtr != rin.end() &&
is_one(rhs, *rtr);
369 auto s = tmap.size();
375 return std::get<I>(
aut_->auts_)->
labelset()->is_one(tmap.begin()->first);
382 template <
bool Infiltration = false>
387 = add_shuffle_transitions_<Infiltration>(src, psrc,
aut_->indices);
388 aut_->set_final(src,
final);
395 template <
bool Infiltration,
size_t... I>
401 using swallow =
int[];
405 add_shuffle_transitions_<Infiltration, I>(src, psrc)),
421 template <
bool Infiltration,
size_t I>
431 if (std::get<I>(
aut_->auts_)->labelset()->is_special(t.first))
432 res = t.second.front().weight();
444 for (
auto d: t.second)
447 std::get<I>(pdst) = d.dst;
449 || std::get<I>(psrc) == d.dst)
471 return make_shared_ptr<res_t>(aut, auts...);
486 auto res = make_product_automaton<false>(
meet_automata(as...),
499 auto res = make_product_automaton<true>(
meet_automata(as...),
509 template <std::
size_t I, Automaton Aut>
512 -> std::enable_if_t<labelset_t_of<Aut>::has_one() && I != 0,
518 template <std::
size_t I, Automaton Aut>
519 std::enable_if_t<!labelset_t_of<Aut>::has_one() || I == 0, Aut&>
526 template <
typename Auts,
size_t... I>
542 template <
typename Auts,
typename Bool>
548 return conjunction_<Auts>(as, lazy, indices);
562 template <Automaton Aut1, Automaton Aut2>
566 auto prod = make_product_automaton<false>(
join_automata(lhs, res), lhs, res);
580 template <Automaton Aut1, Automaton Aut2>
582 ldiv(
const Aut1& a1,
const Aut2& a2)
594 template <Automaton Aut1, Automaton Aut2>
598 const auto& a1 = aut1->
as<Aut1>();
599 const auto& a2 = aut2->
as<Aut2>();
614 template <Automaton Aut1, Automaton Aut2>
616 rdiv(
const Aut1& a1,
const Aut2& a2)
629 template <Automaton Aut1, Automaton Aut2>
633 const auto& a1 = aut1->
as<Aut1>();
634 const auto& a2 = aut2->
as<Aut2>();
652 auto res = make_product_automaton<false>(
join_automata(as...), as...);
662 template <
typename Auts,
size_t... I>
672 template <
typename Auts>
678 return shuffle_<Auts>(as, indices);
689 template <
typename ValueSet>
690 typename ValueSet::value_t
692 const typename ValueSet::value_t& lhs,
693 const typename ValueSet::value_t& rhs)
695 return vs.shuffle(lhs, rhs);
703 template <
typename ExpSetLhs,
typename ExpSetRhs>
707 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
710 std::get<1>(join_elts),
711 std::get<2>(join_elts)));
722 template <Automaton A1, Automaton A2>
728 auto res = make_product_automaton<false>(
join_automata(a1, a2), a1, a2);
736 infiltration(
const A1& a1,
const A2& a2,
const A3& a3,
const Auts&... as)
747 template <
typename Auts,
size_t... I>
758 template <
typename Auts>
764 return infiltration_<Auts>(as, indices);
774 template <
typename ValueSet>
775 typename ValueSet::value_t
777 const typename ValueSet::value_t& lhs,
778 const typename ValueSet::value_t& rhs)
780 return vs.infiltration(lhs, rhs);
788 template <
typename ExpSetLhs,
typename ExpSetRhs>
792 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
795 std::get<1>(join_elts),
796 std::get<2>(join_elts)));
806 template <Automaton Aut>
814 auto s = res->new_state();
817 for (
auto l: res->context().labelset()->generators())
818 res->new_transition(s, s, l);
824 static bool iterative = getenv(
"VCSN_ITERATIVE");
826 for (
size_t i = 0; i < n; ++i)
830 auto power =
strip(aut);
852 template <Automaton Aut,
typename Un
signed>
856 const auto& a = aut->
as<Aut>();
867 template <
typename ValueSet>
868 typename ValueSet::value_t
870 const typename ValueSet::value_t& lhs,
871 const typename ValueSet::value_t& rhs)
873 return rs.conjunction(lhs, rhs);
885 template <
typename ExpSetLhs,
typename ExpSetRhs>
889 auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
892 std::get<1>(join_elts),
893 std::get<2>(join_elts)));
907 template <
typename PolynomialSetLhs,
typename PolynomialSetRhs>
911 auto join_elts = join<PolynomialSetLhs, PolynomialSetRhs>(lhs, rhs);
914 std::get<1>(join_elts),
915 std::get<2>(join_elts)));
std::ostream & print_set(std::ostream &o, format fmt={}) const
void add_shuffle_transitions(const state_t src, const state_name_t &psrc)
Add transitions to the given result automaton, starting from the given result input state...
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
product_automaton_impl self_t
context_t_of< Aut > context_t
The context of the result.
constexpr std::enable_if_t<!labelset_t_of< Aut_ >::has_one(), bool > is_one(const Aut_ &, transition_t_of< Aut_ >) const
Same as above, but for labelsets without one, so it's always false.
tuple_automaton< automaton_t, Auts... > tuple_automaton_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
std::shared_ptr< const detail::polynomial_base > polynomial
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
auto all_in(Args &&...args) const -> decltype(aut_-> all_in(std::forward< Args >(args)...))
bool has_one_in(const state_name_t &psrc, std::size_t i, seq< I... >) const
Check if all the tapes after the Ith have only incoming spontaneous transitions.
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
void conjunction()
Compute the (accessible part of the) conjunction.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
polynomial conjunction_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (conjunction).
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
typename tuple_automaton_t::element_type::state_t state_t
zipped_maps< Dereference, Maps... > zip_map_tuple(const std::tuple< Maps... > &maps)
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
An automaton whose type is the join between those of auts.
std::enable_if_t<!L::has_one(), void > maybe_add_one_transitions_(const L &, const state_t, const state_name_t &)
In the case where the labelset doesn't have one, do nothing.
typename super_t::state_name_t state_name_t
static symbol sname_(const T &...t)
std::enable_if_t< sizeof...(Auts)==2 &&!L > ldiv_here()
Compute the left quotient in-place.
automaton_t aut_
The wrapped automaton, possibly const.
detail::automaton automaton
typename super_t::template transition_map_t< A > transition_map_t
std::shared_ptr< detail::product_automaton_impl< Lazy, Aut, Auts... >> product_automaton
A product automaton as a shared pointer.
std::enable_if_t< labelset_t_of< Aut_ >::has_one(), bool > is_spontaneous_in(const Aut_ &rhs, state_t_of< Aut_ > rst) const
Whether the state has only incoming spontaneous transitions.
auto copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans) -> decltype(keep_state(input->null_state()), keep_trans(input->null_transition()), make_fresh_automaton< AutIn, AutOut >(input))
A copy of input keeping only its states that are accepted by keep_state, and transitions accepted by ...
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
void infiltration()
Compute the (accessible part of the) infiltration product.
std::tuple< Auts... > automata_t
The type of input automata.
void add_one_transitions_(const state_t src, const state_name_t &psrc, seq< I... >)
Add the spontaneous transitions leaving state src, if it is relevant (i.e.
const weightset_t & ws_
The resulting weightset.
typename tuple_automaton_t::element_type::template seq< I... > seq
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts... >
The (accessible part of the) shuffle product.
void add_transitions(const state_t src, const state_name_t &psrc)
Tell lazy_tuple_automaton how to add the transitions to a state.
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Lazy, Aut, Auts... >
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction.
auto labelset(Args &&...args) const -> decltype(aut_-> labelset(std::forward< Args >(args)...))
std::enable_if_t< L::has_one(), void > maybe_add_one_transitions_(const L &ls, const state_t src, const state_name_t &psrc)
If the labelset has one, add the relevant spontaneous-transitions leaving the state.
typename tuple_automaton_t::element_type::state_name_t state_name_t
auto infiltration(const A1 &a1, const A2 &a2) -> tuple_automaton< decltype(join_automata(a1, a2)), A1, A2 >
The (accessible part of the) infiltration product.
typename weightset_t::value_t weight_t
auto new_transition(Args &&...args) -> decltype(aut_-> new_transition(std::forward< Args >(args)...))
bool has_only_one_out(const state_name_t &psrc, std::size_t i, seq< I... >)
Check if all the tapes before the Ith have only outgoing spontaneous transitions. ...
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
bool has_only_ones_out(const state_name_t &psrc)
Whether the Ith state of psrc in the Ith input automaton has no non-spontaneous outgoing transitions...
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
std::enable_if_t< L, void > complete_(state_t s) const
Complete a state: find its outgoing transitions.
void add_conjunction_transitions(const state_t src, const state_name_t &psrc)
Add transitions to the result automaton, starting from the given result input state, which must correspond to the given pair of input state automata.
void initialize_shuffle()
Fill the worklist with the initial source-state pairs, as needed for the shuffle algorithm.
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
autodecltype(insplit(aut)) std::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
std::remove_cv_t< std::remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
An automaton whose type is the meet between those of auts.
labelset_t_of< context_t > labelset_t
weight_t add_shuffle_transitions_(const state_t src, const state_name_t &psrc, seq< I... >)
Let all automata advance one after the other, and add the corresponding transitions in the output...
weightset_t_of< context_t > weightset_t
product_automaton_impl(Aut aut, const Auts &...auts)
Build a product automaton.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
auto rdiv(const Aut1 &a1, const Aut2 &a2)
Compute the right quotient.
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
typename labelset_t::value_t label_t
typename super_t::state_t state_t
Decorator implementing the laziness for an algorithm.
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::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Build the (accessible part of the) product.
auto insplit(Aut &aut) -> std::enable_if_t< labelset_t_of< Aut >::has_one(), decltype(make_insplit_automaton(aut))>
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
std::shared_ptr< const node< Context >> expression
std::shared_ptr< detail::tuple_automaton_impl< Auts... >> tuple_automaton
A tuple automaton as a shared pointer.
automaton_t strip()
The automaton we decorate.
auto & as()
Extract wrapped typed automaton.
std::enable_if_t< labelset_t_of< Aut_ >::has_one(), bool > is_one(const Aut_ &aut, transition_t_of< Aut_ > tr) const
Check if the transition is spontaneous (in the case of a labelset with one).
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
void shuffle()
Compute the (accessible part of the) shuffle product.
state_t state(Args &&...args)
Conversion from state name to state number.
std::shared_ptr< detail::expression_base > expression
weight_t add_shuffle_transitions_(const state_t src, const state_name_t &psrc)
Let Ith automaton advance, and add the corresponding transitions in the output.
constexpr std::enable_if_t<!labelset_t_of< Aut_ >::has_one(), bool > is_spontaneous_in(const Aut_ &, state_t_of< Aut_ >) const
Check if the state has only incoming spontaneous transitions.
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
Aut transpose(const transpose_automaton< Aut > &aut)
An input/output format for valuesets.
void initialize_conjunction()
Fill the worklist with the initial source-state pairs, as needed for the conjunction algorithm...
Aut automaton_t
The type of the resulting automaton.
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).