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...>;
59 static symbol res(
"product_automaton"
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;
100 while (!
aut_->todo_.empty())
102 const auto& p =
aut_->todo_.front();
104 aut_->todo_.pop_front();
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");
149 while (!
aut_->todo_.empty())
151 const auto& p =
aut_->todo_.front();
158 add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
160 aut_->todo_.pop_front();
203 if (!
aut_->labelset()->is_one(t.first))
210 ws_.mul(ts.weight()...));
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>
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>
266 std::get<I>(psrc))... };
267 for (; i <
sizeof...(Auts); ++i)
275 template <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>
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>
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>
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...);
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>
514 return conjunction_<Auts>(as, lazy, indices);
531 auto res = make_product_automaton<false>(
join_automata(as...), as...);
541 template <
typename Auts,
size_t... I>
551 template <
typename Auts>
557 return shuffle_<Auts>(as, indices);
568 template <
typename ValueSet>
569 typename ValueSet::value_t
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>
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)
626 template <
typename Auts,
size_t... I>
637 template <
typename Auts>
643 return infiltration_<Auts>(as, indices);
653 template <
typename ValueSet>
654 typename ValueSet::value_t
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>
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)
709 auto power =
strip(aut);
731 template <Automaton Aut,
typename Un
signed>
735 const auto& a = aut->as<Aut>();
746 template <
typename ValueSet>
747 typename ValueSet::value_t
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)));
void shuffle()
Compute the (accessible part of the) shuffle product.
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
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.
typename super_t::state_name_t state_name_t
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.
std::shared_ptr< const detail::polynomial_base > polynomial
labelset_t_of< context_t > labelset_t
Decorator implementing the laziness for an algorithm.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
void initialize_conjunction()
Fill the worklist with the initial source-state pairs, as needed for the conjunction algorithm...
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Lazy, Aut, Auts... >
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction.
auto all_in(Args &&...args) const -> decltype(aut_-> all_in(std::forward< Args >(args)...))
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
auto conjunction_lazy(const Auts &...as) -> product_automaton< true, decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction, on-the-fly.
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
auto infiltration(const A1 &a1, const A2 &a2) -> tuple_automaton< decltype(join_automata(a1, a2)), A1, A2 >
The (accessible part of the) infiltration product.
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
polynomial conjunction_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (conjunction).
state_t state(Args &&...args)
Conversion from state name to state number.
context_t_of< Aut > context_t
The context of the result.
std::ostream & print_set(std::ostream &o, format fmt={}) const
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.
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.
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...
std::remove_cv_t< std::remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
typename labelset_t::value_t label_t
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
Aut automaton_t
The type of the resulting automaton.
void infiltration()
Compute the (accessible part of the) infiltration product.
automaton_t aut_
The wrapped automaton, possibly const.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
auto insplit(Aut &aut) -> std::enable_if_t< labelset_t_of< Aut >::has_one(), decltype(make_insplit_automaton(aut))>
An input/output format for valuesets.
tuple_automaton< automaton_t, Auts... > tuple_automaton_t
typename tuple_automaton_t::element_type::template seq< I... > seq
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. ...
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...
std::enable_if_t< L, void > complete_(state_t s) const
Complete a state: find its outgoing transitions.
product_automaton_impl(Aut aut, const Auts &...auts)
Build a product automaton.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
std::shared_ptr< detail::tuple_automaton_impl< Auts... >> tuple_automaton
A tuple automaton as a shared pointer.
void add_transitions(const state_t src, const state_name_t &psrc)
Tell lazy_tuple_automaton how to add the transitions to a state.
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
Build the (accessible part of the) product.
std::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
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.
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
std::shared_ptr< detail::automaton_base > automaton
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.
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.
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 detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
auto labelset(Args &&...args) const -> decltype(aut_-> labelset(std::forward< Args >(args)...))
static symbol sname_(const T &...t)
auto new_transition(Args &&...args) -> decltype(aut_-> new_transition(std::forward< Args >(args)...))
typename super_t::state_t state_t
void conjunction()
Compute the (accessible part of the) conjunction.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
typename tuple_automaton_t::element_type::state_t state_t
product_automaton_impl self_t
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
typename tuple_automaton_t::element_type::state_name_t state_name_t
std::shared_ptr< const node< Context >> expression
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(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.
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
typename super_t::template transition_map_t< A > transition_map_t
std::shared_ptr< detail::expression_base > expression
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
zipped_maps< Dereference, Maps... > zip_map_tuple(const std::tuple< Maps... > &maps)
weightset_t_of< context_t > weightset_t
automaton_t strip()
The automaton we decorate.
std::tuple< Auts... > automata_t
The type of input automata.
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
An automaton whose type is the meet between those of auts.
const weightset_t & ws_
The resulting weightset.
autodecltype(insplit(aut)) std::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts... >
The (accessible part of the) shuffle product.
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...
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).
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.
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).
std::shared_ptr< detail::product_automaton_impl< Lazy, Aut, Auts... >> product_automaton
A product automaton as a shared pointer.
void initialize_shuffle()
Fill the worklist with the initial source-state pairs, as needed for the shuffle algorithm.
typename weightset_t::value_t weight_t