1 #ifndef VCSN_ALGOS_PRODUCT_HH
2 # define VCSN_ALGOS_PRODUCT_HH
22 template <
typename... Auts>
31 template <
typename... Auts>
46 template <
typename Aut,
typename... Auts>
51 "product: requires letterized labels");
60 template <
size_t... I>
61 using seq =
typename super_t::template
seq<I...>;
77 std::string
vname(
bool full =
true)
const
87 using label_t =
typename labelset_t::value_t;
88 using weight_t =
typename weightset_t::value_t;
109 initialize_product();
111 while (!
todo_.empty())
124 initialize_shuffle();
126 while (!
todo_.empty())
142 initialize_shuffle();
144 while (!
todo_.empty())
163 void initialize_product()
170 void initialize_shuffle()
179 template <
typename A>
180 using transition_map_t = transition_map<A, weightset_t, false, true>;
183 std::tuple<typename transition_map_t<Auts>::map_t&...>
189 template <
size_t... I>
190 std::tuple<typename transition_map_t<Auts>::map_t&...>
208 if (!
aut_->labelset()->is_one(t.first))
210 ([&] (
const typename transition_map_t<Auts>::transition&... ts)
212 aut_->new_transition(src,
state(ts.dst...),
213 t.first,
aut_->weightset()->mul(ts.wgt...));
221 template <std::size_t... I>
226 using swallow =
int[];
229 (maybe_add_one_transitions_<I>(*(std::get<I>(
auts_)->
labelset()),
235 template <std::
size_t I,
typename L>
236 typename std::enable_if<!L::has_one(), void>::type
242 template <std::
size_t I,
typename L>
243 typename std::enable_if<L::has_one(), void>::type
252 if (ls.is_one(tmap.begin()->first))
253 for (
auto t : tmap.begin()->second)
256 std::get<I>(pdst) = t.dst;
257 aut_->new_transition(src,
state(pdst), ls.one(), t.wgt);
264 template <std::size_t... I>
269 std::get<I>(psrc))... };
270 for (; i <
sizeof...(Auts); ++i)
278 template <std::size_t... I>
282 bool has_ones[] = { has_only_ones_out<I>(psrc)... };
283 for (
size_t j = 0; j < i; ++j)
291 template <
typename Aut_>
292 typename std::enable_if<labelset_t_of<Aut_>::has_one(),
296 return aut->labelset()->is_one(aut->label_of(tr));
301 template <
typename Aut_>
302 constexpr
typename std::enable_if<!labelset_t_of<Aut_>::has_one(),
312 template <
typename Aut_>
313 constexpr
typename std::enable_if<!labelset_t_of<Aut_>::has_one(),
322 template <
typename Aut_>
323 typename std::enable_if<labelset_t_of<Aut_>::has_one(),
327 auto rin = rhs->all_in(rst);
328 auto rtr = rin.begin();
329 return rtr != rin.end() &&
is_one(rhs, *rtr) && !rhs->is_initial(rst);
339 auto s = tmap.size();
345 return std::get<I>(
auts_)->
labelset()->is_one(tmap.begin()->first);
356 aut_->set_final(src,
final);
363 template <
size_t... I>
369 using swallow =
int[];
372 (res =
aut_->weightset()->mul(res,
373 add_shuffle_transitions_<I>(src, psrc)),
394 if (std::get<I>(
auts_)->labelset()->is_special(t.first))
395 res = t.second.front().wgt;
404 for (
auto d: t.second)
405 if (std::get<I>(psrc) == d.dst)
406 aut_->add_transition(src, src, t.first, d.wgt);
410 std::get<I>(pdst) = d.dst;
411 aut_->new_transition(src,
state(pdst), t.first, d.wgt);
422 template <
typename Aut,
typename... Auts>
426 template <
typename Aut,
typename... Auts>
433 return make_shared_ptr<res_t>(aut, auts...);
442 template <
typename... Auts>
460 template <std::
size_t I,
typename Aut>
461 typename std::enable_if<labelset_t_of<Aut>::has_one()
462 && I != 0, Aut>::type
468 template <std::
size_t I,
typename Aut>
469 typename std::enable_if<!labelset_t_of<Aut>::has_one()
470 || I == 0, Aut&>::type
476 template <
typename... Auts,
size_t... I>
485 template <
typename Lhs,
typename Rhs>
489 const auto& l = lhs->as<Lhs>();
490 const auto&
r = rhs->as<Rhs>();
498 template <
typename... Auts>
507 (
const std::vector<automaton>&) ->
automaton);
517 template <
typename... Auts>
520 shuffle(
const Auts&... as)
534 template <
typename Lhs,
typename Rhs>
538 const auto& l = lhs->as<Lhs>();
539 const auto&
r = rhs->as<Rhs>();
547 template <
typename... Auts,
size_t... I>
557 template <
typename... Auts>
566 (
const std::vector<automaton>&) ->
automaton);
576 template <
typename ValueSet>
578 typename ValueSet::value_t
579 shuffle(
const ValueSet& vs,
580 const typename ValueSet::value_t& lhs,
581 const typename ValueSet::value_t& rhs)
583 return vs.shuffle(lhs, rhs);
591 template <
typename RatExpSetLhs,
typename RatExpSetRhs>
595 const auto& l = lhs->as<RatExpSetLhs>();
596 const auto&
r = rhs->as<RatExpSetRhs>();
597 auto rs =
join(l.ratexpset(), r.ratexpset());
598 auto lr = rs.conv(l.ratexpset(), l.ratexp());
599 auto rr = rs.conv(r.ratexpset(), r.ratexp());
614 template <
typename... Auts>
632 template <
typename Lhs,
typename Rhs>
636 const auto& l = lhs->as<Lhs>();
637 const auto&
r = rhs->as<Rhs>();
645 template <
typename... Auts,
size_t... I>
655 template <
typename... Auts>
664 (
const std::vector<automaton>&) ->
automaton);
672 template <
typename Aut>
675 ->
typename Aut::element_type::automaton_nocv_t
677 using res_t =
typename Aut::element_type::automaton_nocv_t;
678 auto res = make_shared_ptr<res_t>(aut->context());
681 auto s = res->new_state();
684 for (
auto l: res->context().labelset()->genset())
685 res->new_transition(s, s, l);
691 static bool iterative = getenv(
"VCSN_ITERATIVE");
693 for (
size_t i = 0; i < n; ++i)
719 template <
typename Aut,
typename Un
signed>
723 const auto& a = aut->as<Aut>();
738 template <
typename RatExpSet>
740 typename RatExpSet::value_t
741 conjunction(
const RatExpSet& rs,
742 const typename RatExpSet::value_t& lhs,
743 const typename RatExpSet::value_t& rhs)
745 return rs.conjunction(lhs, rhs);
753 template <
typename RatExpSetLhs,
typename RatExpSetRhs>
757 const auto& l = lhs->as<RatExpSetLhs>();
758 const auto&
r = rhs->as<RatExpSetRhs>();
759 auto rs =
join(l.ratexpset(), r.ratexpset());
760 auto lr = rs.conv(l.ratexpset(), l.ratexp());
761 auto rr = rs.conv(r.ratexpset(), r.ratexp());
771 #endif // !VCSN_ALGOS_PRODUCT_HH
Aut automaton_t
The type of the resulting automaton.
ratexp make_ratexp(const RatExpSet &rs, const typename RatExpSet::value_t &ratexp)
std::enable_if< labelset_t_of< Aut_ >::has_one(), bool >::type 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).
automaton product_vector(const std::vector< automaton > &as)
Variadic bridge.
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
std::shared_ptr< detail::automaton_base > automaton
std::tuple< Auts...> automata_t
The type of input automata.
state_t_of< automaton_t > state_t
Result state type.
auto power(const Aut &aut, unsigned n) -> typename Aut::element_type::automaton_nocv_t
auto labelset(Args &&...args) const -> decltype(aut_-> labelset(std::forward< Args >(args)...))
auto product(const Auts &...as) -> product_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) product.
std::tuple< state_t_of< Auts >...> state_name_t
State names: Tuple of states of input automata.
product_automaton_impl(Aut aut, const Auts &...auts)
automaton shuffle_vector(const std::vector< automaton > &as)
Variadic bridge.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
state_name_t post_() const
The name of the post of the output automaton.
state_t state(state_name_t state)
The state in the product corresponding to a pair of states of operands.
context_t_of< Aut > context_t
The context of the result.
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...
RatExpSet::value_t conjunction(const RatExpSet &rs, const typename RatExpSet::value_t &lhs, const typename RatExpSet::value_t &rhs)
Intersection/Hadamard product of ratexps.
std::enable_if<!labelset_t_of< Aut >::has_one()||I==0, Aut & >::type do_insplit(Aut &aut)
static std::string sname()
std::tuple< state_t_of< Auts >...> state_name_t
State names: Tuple of states of input automata.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
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::shared_ptr< detail::ratexp_base > ratexp
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
Join between automata.
std::shared_ptr< const node< Context >> ratexp
state_t_of< automaton_t > state_t
Result state type.
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...
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.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
automaton infiltration_vector(const std::vector< automaton > &as)
Variadic bridge.
std::deque< state_name_t > todo_
Worklist of state tuples.
An automaton whose states are tuples of states of automata.
std::string vname(bool full=true) const
labelset_t_of< context_t > labelset_t
#define REGISTER_DECLARE(Name, Signature)
static std::string sname_()
The sname of the sub automata.
std::enable_if< L::has_one(), void >::type 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.
zipped_maps< Dereference, Maps...> zip_map_tuple(const std::tuple< Maps...> &maps)
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
Build the (accessible part of the) product.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
ratexp shuffle_ratexp(const ratexp &lhs, const ratexp &rhs)
Bridge.
state_name_t pre_() const
The name of the pre of the output automaton.
void cross_tuple(Fun f, const std::tuple< Ts...> &ts)
constexpr std::enable_if<!labelset_t_of< Aut_ >::has_one(), bool >::type is_one(const Aut_ &, transition_t_of< Aut_ >) const
Same as above, but for labelsets without one, so it's always false.
auto meet(const ratexpset< Ctx1 > &a, const ratexpset< Ctx2 > &b) -> ratexpset< meet_t< Ctx1, Ctx2 >>
The meet of two ratexpsets.
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Aut, Auts...>
std::enable_if< labelset_t_of< Aut >::has_one(), Aut >::type insplit(Aut &aut)
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
auto shuffle(const Auts &...as) -> product_automaton< decltype(join_automata(as...)), Auts...>
The (accessible part of the) shuffle product.
typename super_t::template seq< I...> seq
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss, seq< I...>)
Provide a variadic mul on top of a binary mul(), and one().
constexpr std::enable_if<!labelset_t_of< Aut_ >::has_one(), bool >::type has_only_ones_in(const Aut_ &, state_t_of< Aut_ >) const
Check if the state has only incoming spontaneous transitions.
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. ...
static constexpr indices_t indices
ratexp conjunction_ratexp(const ratexp &lhs, const ratexp &rhs)
Bridge.
variadic< type_t::shuffle, Context > shuffle
weightset_t_of< context_t > weightset_t
std::string vname_(bool full=true) const
The vname of the sub automata.
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
std::tuple< transition_map_t< Auts >...> transition_maps_
Transition caches.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
auto infiltration(const Auts &...as) -> product_automaton< decltype(join_automata(as...)), Auts...>
The (accessible part of the) infiltration product.
typename weightset_t::value_t weight_t
typename std::remove_cv< typename std::remove_reference< T >::type >::type base_t
T without reference or const/volatile qualifiers.
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
Meet between automata.
void add_product_transitions(const state_t src, const state_name_t &psrc)
Add transitions to the given result automaton, starting from the given result input state...
automaton product_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
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.
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.
automata_t auts_
Input automata, supplied at construction time.
typename labelset_t::value_t label_t
std::enable_if<!L::has_one(), void >::type 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< labelset_t_of< Aut_ >::has_one(), bool >::type has_only_ones_in(const Aut_ &rhs, state_t_of< Aut_ > rst) const
Whether the state has only incoming spontaneous transitions.
automaton_t aut_
The wrapped automaton, possibly const.
base_t< typename std::tuple_element< I, automata_t >::type > input_automaton_t
The type of the Ith input automaton, unqualified.
std::shared_ptr< detail::product_automaton_impl< Aut, Auts...>> product_automaton
A product automaton as a shared pointer.