20 #define DEFINE(Type) \ 21 template <Automaton Aut> \ 22 struct Type ## _of_impl \ 24 using type = typename Aut::element_type::Type; \ 27 template <Automaton Aut> \ 28 struct Type ## _of_impl<insplit_automaton<Aut>> \ 29 : Type ## _of_impl<Aut> \ 32 template <Automaton Aut> \ 34 = typename Type ## _of_impl<Aut>::type 43 template <Automaton Lhs, Automaton Rhs>
74 template <
bool Lazy, Automaton Lhs, Automaton Rhs>
79 typename composed_type<Lhs, Rhs>::out_t,
83 "compose: lhs labelset must be a tupleset");
85 "compose: rhs labelset must be a tupleset");
89 "compose: common tape must be of same type");
92 template <std::size_t... I>
134 static symbol res(std::string{
"compose_automaton<"}
135 + (Lazy ?
"true" :
"false") +
", " 143 o <<
"compose_automaton<";
144 std::get<0>(aut_->auts_)->
print_set(o, fmt) <<
", ";
145 return std::get<1>(aut_->auts_)->
print_set(o, fmt) <<
">";
155 initialize_compose();
158 while (!aut_->todo_.empty())
160 const auto& p = aut_->todo_.front();
161 add_compose_transitions(std::get<1>(p), std::get<0>(p));
162 aut_->todo_.pop_front();
170 add_compose_transitions(src, psrc);
179 template <Automaton A>
186 template <Automaton A>
194 template <Automaton A>
207 template <std::size_t... I1, std::size_t... I2>
214 std::get<I2>(rl.sets())...};
220 return {make_labelset_(lhs->res_labelset(),
221 real_aut(rhs)->res_labelset()),
222 join(*lhs->weightset(), *rhs->weightset())};
229 aut_->todo_.emplace_back(aut_->pre_(), aut_->pre());
235 return std::tuple_cat(ll, rl);
238 template <Automaton Aut>
239 std::enable_if_t<labelset_t_of<Aut>::has_one(),
243 return aut->hidden_one();
246 template <Automaton Aut>
247 std::enable_if_t<labelset_t_of<Aut>::has_one(),
251 return real_aut(aut)->hidden_one();
254 template <Automaton Aut>
256 std::enable_if_t<!labelset_t_of<Aut>::has_one(),
260 raise(
"should not get here");
263 using super_t::transition_maps_;
271 const auto& lhs = std::get<0>(aut_->auts_);
272 const auto& rhs = std::get<1>(aut_->auts_);
275 const auto& ltm = std::get<0>(transition_maps_)[std::get<0>(psrc)];
276 const auto& rtm = std::get<1>(transition_maps_)[std::get<1>(psrc)];
278 add_one_transitions_<0>(src, psrc);
279 add_one_transitions_<1>(src, psrc);
284 using polynomialset_t
286 using polynomial_t =
typename polynomialset_t::value_t;
287 const auto ps = polynomialset_t(aut_->context());
288 auto poly_maps = std::map<state_t, polynomial_t>();
290 for (
const auto& t:
zip_maps(ltm, rtm))
293 if (!lhs->labelset()->is_one(t.first))
302 ps.add_here(poly_maps[this->state(lts.
dst, rts.
dst)],
303 join_label(lhs->hidden_label_of(lts.transition),
304 real_aut(rhs)->hidden_label_of(rts.transition)),
311 for (
const auto& elt: poly_maps)
312 for (
const auto& m: elt.second)
313 this->new_transition(src, elt.first, m.first, m.second);
317 template <std::
size_t I>
327 const auto& ls = *std::get<I>(aut_->auts_)->labelset();
328 const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
329 if (!tmap.empty() && ls.is_one(tmap.begin()->first))
330 for (
const auto& t: tmap.begin()->second)
336 return std::make_tuple(dst, std::get<1>(psrc));
339 return std::make_tuple(std::get<0>(psrc), dst);
344 ([
this, t=t.transition](
const auto& lhs,
const auto& rhs)
346 return join_label(lhs->hidden_label_of(t),
347 get_hidden_one(real_aut(rhs)));
349 [
this, t=t.transition](
const auto& lhs,
const auto& rhs)
351 return join_label(get_hidden_one(lhs),
352 real_aut(rhs)->hidden_label_of(t));
354 (std::get<0>(aut_->auts_), std::get<1>(aut_->auts_));
355 this->new_transition(src, this->state(pdst), lbl, t.weight());
360 template <Automaton Aut>
361 std::enable_if_t<labelset_t_of<Aut>::has_one(),
bool>
364 return aut->labelset()->is_one(aut->label_of(tr));
367 template <Automaton Aut>
369 std::enable_if_t<!labelset_t_of<Aut>::has_one(),
bool>
377 template <std::size_t... I>
380 return all(is_proper_in<I>(psrc)...);
387 -> std::enable_if_t<!labelset_t_of<input_automaton_t<I>>::has_one(),
400 -> std::enable_if_t<labelset_t_of<input_automaton_t<I>>::has_one(),
406 const auto& aut = std::get<I>(aut_->auts_);
407 auto s = std::get<I>(sn);
408 auto rin =
all_in(aut, s);
409 auto rtr = rin.begin();
412 return rtr == rin.end() || !is_one(aut, *rtr);
417 template <std::size_t... I>
420 return all(has_proper_out<I>(psrc)...);
432 const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
433 auto s = tmap.size();
439 return !std::get<I>(aut_->auts_)->labelset()->is_one(tmap.begin()->first);
445 template <
bool Lazy, Automaton Lhs, Automaton Rhs>
447 = std::shared_ptr<detail::compose_automaton_impl<Lazy, Lhs, Rhs>>;
449 template <
bool Lazy, std::size_t OutTape, std::size_t InTape,
454 auto l = focus<OutTape>(lhs);
455 auto r =
insplit(focus<InTape>(rhs),
true);
459 return make_shared_ptr<res_t>(l,
r);
468 std::size_t OutTape = 1, std::size_t InTape = 0>
470 compose(
const Lhs& lhs,
const Rhs& rhs)
472 auto res = make_compose_automaton<false, OutTape, InTape>(lhs, rhs);
478 template <
typename Lhs,
typename Rhs,
479 std::size_t OutTape = 1, std::size_t InTape = 0>
483 auto res = make_compose_automaton<true, OutTape, InTape>(lhs, rhs);
493 template <Automaton Lhs, Automaton Rhs,
typename Bool>
497 auto& l = lhs->
as<Lhs>();
498 auto&
r = rhs->
as<Rhs>();
Outgoing signature: weight, destination.
typename type_helper_t::weightset_t weightset_t
std::enable_if_t< labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const Aut &aut) const
std::shared_ptr< detail::focus_automaton_impl< Tape, Aut > > focus_automaton
A focus automaton as a shared pointer.
std::enable_if_t< labelset_t_of< Aut >::has_one(), bool > is_one(const Aut &aut, transition_t_of< Aut > tr) const
typename type_helper_t::hidden_l_label_t hidden_l_label_t
std::shared_ptr< insplit_automaton_impl< Aut > > insplit_automaton
An insplit automaton as a shared pointer.
typename type_helper_t::res_label_t res_label_t
void initialize_compose()
Fill the worklist with the initial source-state pairs, as needed for the composition algorithm...
void add_transitions(const state_t src, const state_name_t &psrc)
Callback for complete_ when lazy.
typename hidden_r_labelset_t::value_t hidden_r_label_t
typename concat_tupleset< hidden_l_labelset_t, hidden_r_labelset_t >::type labelset_t
The type of context of the result.
auto & as()
Extract wrapped typed automaton.
typename type_helper_t::out_t out_t
void compose()
The (accessible part of the) composition of lhs_ and rhs_.
auto insplit(Aut aut, bool lazy=false) -> std::enable_if_t< labelset_t_of< Aut >::has_one(), decltype(make_insplit_automaton(aut))>
Insplit an automaton with possible spontaneous transitions.
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
ATTRIBUTE_NORETURN std::enable_if_t<!labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const Aut &) const
join_t< weightset_t_of< context_t_of< Lhs > >, weightset_t_of< context_t_of< Rhs > >> weightset_t
typename weightset_t::value_t weight_t
auto make_compose_automaton(const Lhs &lhs, const Rhs &rhs)
typename hidden_l_labelset_t::value_t hidden_l_label_t
base_t< tuple_element_t< I, automata_t > > input_automaton_t
The type of the Ith input automaton, unqualified.
typename super_t::state_t state_t
Result state type.
bool has_proper_out(const state_name_t &psrc)
Whether the Ith state of psrc in the Ith input automaton has proper outgoing transitions (but possibl...
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
void add_one_transitions_(const state_t src, const state_name_t &psrc)
void add_compose_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::mutable_automaton_impl< Context > > mutable_automaton
typename tuple_automaton_impl::state_t state_t
weightset_mixin< detail::r_impl > r
static auto real_aut(const A &aut)
Get the focus automaton, possibly from a non insplit automaton.
typename labelset_t::value_t res_label_t
bool are_proper_in(const state_name_t &psrc, seq< I... >) const
Whether no tapes in the sequence have spontaneous incoming transitions.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
decltype(join(std::declval< ValueSets >()...)) join_t
The type of the join of the ValueSets.
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
typename type_helper_t::hidden_r_label_t hidden_r_label_t
static labelset_t make_labelset_(const hidden_l_labelset_t &ll, const hidden_r_labelset_t &rl)
constexpr auto is_proper_in(const state_name_t &) const -> std::enable_if_t<!labelset_t_of< input_automaton_t< I >>::has_one(), bool >
Whether the state has only proper incoming transitions.
typename tuple_automaton_impl::state_name_t state_name_t
typename res_labelset_t_of_impl< Aut >::type res_labelset_t_of
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
auto compose_lazy(const Lhs &lhs, const Rhs &rhs)
Build the (accessible part of the) lazy composition.
constexpr std::enable_if_t<!labelset_t_of< Aut >::has_one(), bool > is_one(const Aut &, transition_t_of< Aut >) const
typename super_t::state_name_t state_name_t
Tuple of states of input automata.
std::enable_if_t< labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const insplit_automaton< Aut > &aut) const
res_labelset_t_of< clhs_t > hidden_l_labelset_t
Build the (accessible part of the) composition.
Cache the outgoing transitions of an automaton as efficient maps label -> vector<(weight, dst)>.
An input/output format for valuesets.
typename type_helper_t::labelset_t labelset_t
The type of context of the result.
Provide a variadic mul on top of a binary mul(), and one().
typename type_helper_t::hidden_r_labelset_t hidden_r_labelset_t
typename res_label_t_of_impl< Aut >::type res_label_t_of
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
typename type_helper_t::context_t context_t
automaton compose(const automaton &lhs, const automaton &rhs, bool lazy)
Bridge.
auto is_proper_in(const state_name_t &sn) const -> std::enable_if_t< labelset_t_of< input_automaton_t< I >>::has_one(), bool >
Whether the state has only proper incoming transitions.
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Decorator implementing the laziness for an algorithm.
typename full_context_t_of_impl< Aut >::type full_context_t_of
zipped_maps< Dereference, Maps... > zip_maps(Maps &&... maps)
static labelset_t make_labelset_(const hidden_l_labelset_t &ll, seq< I1... >, const hidden_r_labelset_t &rl, seq< I2... >)
compose_automaton_impl(const Lhs &lhs, const Rhs &rhs)
std::remove_cv_t< std::remove_reference_t< T > > base_t
T without reference or const/volatile qualifiers.
std::ostream & print_set(std::ostream &o, format fmt={}) const
bool have_proper_out(const state_name_t &psrc, seq< I... >)
Whether all the tapes in the sequence have proper outgoing transitions (but possibly spontaneous too)...
res_labelset_t_of< crhs_t > hidden_r_labelset_t
std::string type(const automaton &a)
The implementation type of a.
typename type_helper_t::hidden_l_labelset_t hidden_l_labelset_t
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
static auto real_aut(const insplit_automaton< A > &aut)
Get the focus automaton from an insplit automaton.
res_label_t join_label(const hidden_l_label_t &ll, const hidden_r_label_t &rl) const
typename labelset_t::value_t label_t
static context_t make_context_(const Lhs &lhs, const Rhs &rhs)
mutable_automaton< context_t > out_t
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
std::shared_ptr< detail::compose_automaton_impl< Lazy, Lhs, Rhs > > compose_automaton
A compose automaton as a shared pointer.
bool all(Bool &&... values)
Whether all the values evaluate as true.
std::tuple< Lhs, Rhs > automata_t
The type of input automata.
Build the (accessible part of the) composition.