28 template <
typename Aut,
typename... Auts>
33 "product: requires letterized labels");
43 =
typename tuple_automaton_t::element_type::state_name_t;
45 =
typename tuple_automaton_t::element_type::state_t;
46 template <
size_t... I>
48 =
typename tuple_automaton_t::element_type::template
seq<I...>;
52 static symbol res(
"product_automaton"
53 + tuple_automaton_t::element_type::sname_());
59 o <<
"product_automaton";
60 return aut_->print_set_(o, fmt);
68 using label_t =
typename labelset_t::value_t;
69 using weight_t =
typename weightset_t::value_t;
91 -> decltype(
aut_->origins())
93 return aut_->origins();
104 void complete_(
state_t s)
const
106 const auto& orig = origins();
115 -> decltype(
aut_->all_out(s))
119 return aut_->all_out(s);
123 template <
typename Pred>
125 -> decltype(
aut_->all_out(s, pred))
129 return aut_->all_out(s, pred);
160 return all_out(s, not_to_post_p{*
this});
168 return all_out(s, label_equal_p{*
this, l});
177 while (!
aut_->todo_.empty())
179 const auto& p =
aut_->todo_.front();
181 aut_->todo_.pop_front();
190 while (!
aut_->todo_.empty())
192 const auto& p =
aut_->todo_.front();
193 add_shuffle_transitions<false>(std::get<1>(p), std::get<0>(p));
194 aut_->todo_.pop_front();
219 "infiltration: variadic product does not work");
226 while (!
aut_->todo_.empty())
228 const auto& p =
aut_->todo_.front();
235 add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
237 aut_->todo_.pop_front();
259 template <
typename... Args>
262 return aut_->state(std::forward<Args>(args)...);
267 template <
typename A>
271 std::tuple<typename transition_map_t<Auts>::map_t&...>
277 template <
size_t... I>
278 std::tuple<typename transition_map_t<Auts>::map_t&...>
296 if (!
aut_->labelset()->is_one(t.first))
311 template <std::size_t... I>
316 using swallow =
int[];
319 (maybe_add_one_transitions_<I>(*(std::get<I>(
aut_->auts_)->
labelset()),
325 template <std::
size_t I,
typename L>
332 template <std::
size_t I,
typename L>
342 if (ls.is_one(tmap.begin()->first))
343 for (
auto t : tmap.begin()->second)
346 std::get<I>(pdst) = t.dst;
347 this->new_transition(src,
state(pdst), ls.one(), t.weight());
354 template <std::size_t... I>
359 std::get<I>(psrc))... };
360 for (; i <
sizeof...(Auts); ++i)
368 template <std::size_t... I>
372 bool has_ones[] = { has_only_ones_out<I>(psrc)... };
373 for (
size_t j = 0; j < i; ++j)
381 template <
typename Aut_>
385 return aut->labelset()->is_one(aut->label_of(tr));
390 template <
typename Aut_>
400 template <
typename Aut_>
412 template <
typename Aut_>
416 auto rin = rhs->all_in(rst);
417 auto rtr = rin.begin();
418 return rtr != rin.end() &&
is_one(rhs, *rtr);
428 auto s = tmap.size();
434 return std::get<I>(
aut_->auts_)->
labelset()->is_one(tmap.begin()->first);
441 template <
bool Infiltration = false>
446 = add_shuffle_transitions_<Infiltration>(src, psrc,
aut_->indices);
447 aut_->set_final(src,
final);
454 template <
bool Infiltration,
size_t... I>
460 using swallow =
int[];
464 add_shuffle_transitions_<Infiltration, I>(src, psrc)),
480 template <
bool Infiltration,
size_t I>
490 if (std::get<I>(
aut_->auts_)->labelset()->is_special(t.first))
491 res = t.second.front().weight();
503 for (
auto d: t.second)
506 std::get<I>(pdst) = d.dst;
508 || std::get<I>(psrc) == d.dst)
530 template <
typename Aut,
typename... Auts>
534 template <
typename Aut,
typename... Auts>
541 return make_shared_ptr<res_t>(aut, auts...);
550 template <
typename... Auts>
564 template <
typename... Auts>
573 res->conjunction(
true);
581 template <std::
size_t I,
typename Aut>
588 template <std::
size_t I,
typename Aut>
596 template <
typename Auts,
size_t... I>
613 template <
typename Auts,
typename Bool>
620 return conjunction_<Auts>(as, lazy, indices);
631 template <
typename... Auts>
648 template <
typename Auts,
size_t... I>
658 template <
typename Auts>
664 return shuffle_<Auts>(as, indices);
675 template <
typename ValueSet>
677 typename ValueSet::value_t
679 const typename ValueSet::value_t& lhs,
680 const typename ValueSet::value_t& rhs)
682 return vs.shuffle(lhs, rhs);
690 template <
typename ExpSetLhs,
typename ExpSetRhs>
694 const auto& l = lhs->as<ExpSetLhs>();
695 const auto&
r = rhs->as<ExpSetRhs>();
696 auto rs =
join(l.expressionset(), r.expressionset());
697 auto lr = rs.conv(l.expressionset(), l.expression());
698 auto rr = rs.conv(r.expressionset(), r.expression());
710 template <
typename A1,
typename A2>
723 template <
typename A1,
typename A2,
typename A3,
typename... Auts>
726 infiltration(
const A1& a1,
const A2& a2,
const A3& a3,
const Auts&... as)
737 template <
typename Auts,
size_t... I>
748 template <
typename Auts>
754 return infiltration_<Auts>(as, indices);
764 template <
typename ValueSet>
766 typename ValueSet::value_t
768 const typename ValueSet::value_t& lhs,
769 const typename ValueSet::value_t& rhs)
771 return vs.infiltration(lhs, rhs);
779 template <
typename ExpSetLhs,
typename ExpSetRhs>
783 const auto& l = lhs->as<ExpSetLhs>();
784 const auto&
r = rhs->as<ExpSetRhs>();
785 auto rs =
join(l.expressionset(), r.expressionset());
786 auto lr = rs.conv(l.expressionset(), l.expression());
787 auto rr = rs.conv(r.expressionset(), r.expression());
798 template <
typename Aut>
806 auto s = res->new_state();
809 for (
auto l: res->context().labelset()->genset())
810 res->new_transition(s, s, l);
816 static bool iterative = getenv(
"VCSN_ITERATIVE");
818 for (
size_t i = 0; i < n; ++i)
822 auto power =
strip(aut);
844 template <
typename Aut,
typename Un
signed>
848 const auto& a = aut->as<Aut>();
860 template <
typename ExpSet>
862 typename ExpSet::value_t
864 const typename ExpSet::value_t& lhs,
865 const typename ExpSet::value_t& rhs)
867 return rs.conjunction(lhs, rhs);
875 template <
typename ExpSetLhs,
typename ExpSetRhs>
879 const auto& l = lhs->as<ExpSetLhs>();
880 const auto&
r = rhs->as<ExpSetRhs>();
881 auto rs =
join(l.expressionset(), r.expressionset());
882 auto lr = rs.conv(l.expressionset(), l.expression());
883 auto rr = rs.conv(r.expressionset(), r.expression());
void shuffle()
Compute the (accessible part of the) shuffle product.
auto state_is_strict(Args &&...args) const -> decltype(aut_-> state_is_strict(std::forward< Args >(args)...))
auto new_transition(Args &&...args) -> decltype(aut_-> new_transition(std::forward< Args >(args)...))
remove_cv_t< remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
product_automaton_impl self_t
std::tuple< transition_map_t< Auts >...> transition_maps_
Transition caches.
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
std::shared_ptr< detail::product_automaton_impl< Aut, Auts...>> product_automaton
A product automaton as a shared pointer.
bool operator()(transition_t_of< self_t > t) const
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I...>)
Bridge helper.
auto all_out(Args &&...args) const -> decltype(aut_-> all_out(std::forward< Args >(args)...))
Outgoing signature: weight, destination.
context_t_of< Aut > context_t
The context of the result.
state_t state(Args &&...args)
Conversion from state name to state number.
const weightset_t & ws_
The resulting weightset.
Aut automaton_t
The type of the resulting automaton.
auto out(state_t s, label_t_of< self_t > l) -> decltype(this->all_out(s, label_equal_p
Indexes of all transitions leaving state s on label l.
static constexpr auto post(Args &&...args) -> decltype(element_type::post(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. ...
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
vcsn::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 join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
void initialize_conjunction()
Fill the worklist with the initial source-state pairs, as needed for the conjunction algorithm...
auto label_of(Args &&...args) const -> decltype(aut_-> label_of(std::forward< Args >(args)...))
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
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...
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
auto conjunction_lazy(const Auts &...as) -> product_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)...))
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
typename std::enable_if< Cond, T >::type enable_if_t
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Aut, Auts...>
std::tuple< Auts...> automata_t
The type of input automata.
void infiltration()
Compute the (accessible part of the) infiltration product.
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
An automaton whose type is the meet between those of auts.
Aggregate an automaton, and forward calls to it.
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss, seq< I...>)
auto all_out(state_t s) const -> decltype(aut_->all_out(s))
void conjunction(bool lazy=false)
Compute the (accessible part of the) conjunction.
void cross_tuple(Fun f, const std::tuple< Ts...> &ts)
auto infiltration(const A1 &a1, const A2 &a2) -> tuple_automaton< decltype(join_automata(a1, a2)), A1, A2 >
The (accessible part of the) infiltration product.
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
typename tuple_automaton_t::element_type::state_t state_t
typename tuple_automaton_t::element_type::state_name_t state_name_t
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.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
std::shared_ptr< const node< Context >> expression
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...
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts...>
The (accessible part of the) shuffle product.
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
tuple_automaton< automaton_t, Auts...> tuple_automaton_t
auto out(state_t s) -> decltype(this->all_out(s, not_to_post_p
Indexes of visible transitions leaving state s.
bool operator()(transition_t_of< self_t > t) const
vcsn::enable_if_t< labelset_t_of< Aut >::has_one(), Aut > insplit(Aut &aut)
Provide a variadic mul on top of a binary mul(), and one().
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
std::shared_ptr< detail::tuple_automaton_impl< Auts...>> tuple_automaton
A tuple automaton as a shared pointer.
std::shared_ptr< detail::automaton_base > automaton
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction.
typename tuple_automaton_t::element_type::template seq< I...> seq
vcsn::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 require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
std::ostream & print_set(std::ostream &o, format fmt={}) const
vcsn::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 detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
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.
auto make_tuple_automaton(const Auts &...auts) -> tuple_automaton< Auts...>
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).
Build the (accessible part of the) product.
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
vcsn::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
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.
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
typename weightset_t::value_t weight_t
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
An automaton whose type is the join between those of auts.
Cache the outgoing transitions of an automaton as efficient maps label -> vector<(weight, dst)>.
vcsn::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.
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
weightset_t_of< context_t > weightset_t
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
std::shared_ptr< detail::expression_base > expression
constexpr vcsn::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.
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
auto dst_of(Args &&...args) const -> decltype(aut_-> dst_of(std::forward< Args >(args)...))
void initialize_shuffle()
Fill the worklist with the initial source-state pairs, as needed for the shuffle algorithm.
constexpr vcsn::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.
zipped_maps< Dereference, Maps...> zip_map_tuple(const std::tuple< Maps...> &maps)
label_t_of< self_t > label_
automaton_t aut_
The wrapped automaton, possibly const.
typename labelset_t::value_t label_t
product_automaton_impl(Aut aut, const Auts &...auts)
Build a product automaton.
std::set< state_t > done_
When performing the lazy construction, list of states that have been completed (i.e., their outgoing transitions have been computed).
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.
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...
auto all_out(state_t s, Pred pred) const -> decltype(aut_->all_out(s, pred))
All the outgoing transitions satisfying the predicate.
labelset_t_of< context_t > labelset_t