24 #define DEFINE(Type) \ 25 template <Automaton Aut> \ 26 struct Type ## _of_impl \ 28 using type = typename Aut::element_type::Type; \ 31 template <Automaton Aut> \ 32 struct Type ## _of_impl<insplit_automaton<Aut>> \ 33 : Type ## _of_impl<Aut> \ 36 template <Automaton Aut> \ 38 = typename Type ## _of_impl<Aut>::type 46 template <Automaton Lhs, Automaton Rhs>
78 template <
bool Lazy, Automaton Lhs, Automaton Rhs>
83 typename composed_type<Lhs, Rhs>::out_t,
87 "compose: lhs labelset must be a tupleset");
89 "compose: rhs labelset must be a tupleset");
93 "compose: common tape must be of same type");
96 template <std::size_t... I>
138 static symbol res(std::string{
"compose_automaton<"}
139 + (Lazy ?
"true" :
"false") +
", " 147 o <<
"compose_automaton<";
148 std::get<0>(aut_->auts_)->
print_set(o, fmt) <<
", ";
149 return std::get<1>(aut_->auts_)->
print_set(o, fmt) <<
">";
159 initialize_compose();
162 while (!aut_->todo_.empty())
164 const auto& p = aut_->todo_.front();
165 add_compose_transitions(std::get<1>(p), std::get<0>(p));
166 aut_->todo_.pop_front();
174 add_compose_transitions(src, psrc);
183 template <Automaton A>
190 template <Automaton A>
198 template <Automaton A>
211 template <std::size_t... I1, std::size_t... I2>
218 std::get<I2>(rl.sets())...};
224 return {make_labelset_(lhs->res_labelset(),
225 real_aut(rhs)->res_labelset()),
226 join(*lhs->weightset(), *rhs->weightset())};
233 aut_->todo_.emplace_back(aut_->pre_(), aut_->pre());
239 return std::tuple_cat(ll, rl);
242 template <Automaton Aut>
243 std::enable_if_t<labelset_t_of<Aut>::has_one(),
247 return aut->hidden_one();
250 template <Automaton Aut>
251 std::enable_if_t<labelset_t_of<Aut>::has_one(),
255 return real_aut(aut)->hidden_one();
258 template <Automaton Aut>
260 std::enable_if_t<!labelset_t_of<Aut>::has_one(),
264 raise(
"should not get here");
267 using super_t::transition_maps_;
275 const auto& lhs = std::get<0>(aut_->auts_);
276 const auto& rhs = std::get<1>(aut_->auts_);
279 const auto& ltm = std::get<0>(transition_maps_)[std::get<0>(psrc)];
280 const auto& rtm = std::get<1>(transition_maps_)[std::get<1>(psrc)];
282 add_one_transitions_<0>(src, psrc);
283 add_one_transitions_<1>(src, psrc);
288 using polynomialset_t
290 using polynomial_t =
typename polynomialset_t::value_t;
291 const auto ps = polynomialset_t(aut_->context());
292 auto poly_maps = std::map<state_t, polynomial_t>();
294 for (
const auto& t:
zip_maps(ltm, rtm))
297 if (!lhs->labelset()->is_one(t.first))
306 ps.add_here(poly_maps[this->state(lts.
dst, rts.
dst)],
307 join_label(lhs->hidden_label_of(lts.transition),
308 real_aut(rhs)->hidden_label_of(rts.transition)),
315 for (
const auto& elt: poly_maps)
316 for (
const auto& m: elt.second)
317 this->new_transition(src, elt.first, m.first, m.second);
321 template <std::
size_t I>
331 const auto& ls = *std::get<I>(aut_->auts_)->labelset();
332 const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
333 if (!tmap.empty() && ls.is_one(tmap.begin()->first))
334 for (
const auto& t: tmap.begin()->second)
340 return std::make_tuple(dst, std::get<1>(psrc));
343 return std::make_tuple(std::get<0>(psrc), dst);
348 ([
this, t=t.transition](
const auto& lhs,
const auto& rhs)
350 return join_label(lhs->hidden_label_of(t),
351 get_hidden_one(real_aut(rhs)));
353 [
this, t=t.transition](
const auto& lhs,
const auto& rhs)
355 return join_label(get_hidden_one(lhs),
356 real_aut(rhs)->hidden_label_of(t));
358 (std::get<0>(aut_->auts_), std::get<1>(aut_->auts_));
359 this->new_transition(src, this->state(pdst), lbl, t.weight());
364 template <Automaton Aut>
365 std::enable_if_t<labelset_t_of<Aut>::has_one(),
bool>
368 return aut->labelset()->is_one(aut->label_of(tr));
371 template <Automaton Aut>
373 std::enable_if_t<!labelset_t_of<Aut>::has_one(),
bool>
381 template <std::size_t... I>
384 return all(is_proper_in<I>(psrc)...);
391 -> std::enable_if_t<!labelset_t_of<input_automaton_t<I>>::has_one(),
404 -> std::enable_if_t<labelset_t_of<input_automaton_t<I>>::has_one(),
410 const auto& aut = std::get<I>(aut_->auts_);
411 auto s = std::get<I>(sn);
412 auto rin =
all_in(aut, s);
413 auto rtr = rin.begin();
416 return rtr == rin.end() || !is_one(aut, *rtr);
421 template <std::size_t... I>
424 return all(has_proper_out<I>(psrc)...);
436 const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
437 auto s = tmap.size();
443 return !std::get<I>(aut_->auts_)->labelset()->is_one(tmap.begin()->first);
449 template <
bool Lazy, Automaton Lhs, Automaton Rhs>
451 = std::shared_ptr<detail::compose_automaton_impl<Lazy, Lhs, Rhs>>;
453 template <
bool Lazy, std::size_t OutTape, std::size_t InTape,
458 auto l = focus<OutTape>(lhs);
459 auto r =
insplit(focus<InTape>(rhs),
true);
463 return make_shared_ptr<res_t>(l,
r);
472 std::size_t OutTape = 1, std::size_t InTape = 0>
474 compose(
const Lhs& lhs,
const Rhs& rhs)
476 auto res = make_compose_automaton<false, OutTape, InTape>(lhs, rhs);
482 template <
typename Lhs,
typename Rhs,
483 std::size_t OutTape = 1, std::size_t InTape = 0>
487 auto res = make_compose_automaton<true, OutTape, InTape>(lhs, rhs);
497 template <Automaton Lhs, Automaton Rhs,
typename Bool>
501 auto& l = lhs->
as<Lhs>();
502 auto&
r = rhs->
as<Rhs>();
weightset_mixin< detail::r_impl > r
zipped_maps< Dereference, Maps... > zip_maps(Maps &&... maps)
Outgoing signature: weight, destination.
std::string type(const automaton &a)
The implementation type of a.
typename type_helper_t::labelset_t labelset_t
The type of context of the result.
typename type_helper_t::hidden_l_label_t hidden_l_label_t
auto make_compose_automaton(const Lhs &lhs, const Rhs &rhs)
typename hidden_r_labelset_t::value_t hidden_r_label_t
typename weightset_t::value_t weight_t
std::shared_ptr< detail::mutable_automaton_impl< Context > > mutable_automaton
typename res_labelset_t_of_impl< Aut >::type res_labelset_t_of
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
base_t< tuple_element_t< I, automata_t > > input_automaton_t
The type of the Ith input automaton, unqualified.
std::ostream & print_set(std::ostream &o, format fmt={}) const
typename super_t::state_t state_t
Result state type.
bool all(Bool &&... values)
Whether all the values evaluate as true.
#define DEFINE(Type)
Get a type from a possibly insplit automaton.
std::shared_ptr< insplit_automaton_impl< Aut > > insplit_automaton
An insplit automaton as a shared pointer.
typename type_helper_t::hidden_r_labelset_t hidden_r_labelset_t
void add_one_transitions_(const state_t src, const state_name_t &psrc)
static context_t make_context_(const Lhs &lhs, const Rhs &rhs)
compose_automaton_impl(const Lhs &lhs, const Rhs &rhs)
std::shared_ptr< detail::focus_automaton_impl< Tape, Aut > > focus_automaton
A focus automaton as a shared pointer.
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.
auto compose_lazy(const Lhs &lhs, const Rhs &rhs)
Build the (accessible part of the) lazy composition.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
typename hidden_l_labelset_t::value_t hidden_l_label_t
automaton compose(const automaton &lhs, const automaton &rhs, bool lazy)
Bridge.
res_label_t join_label(const hidden_l_label_t &ll, const hidden_r_label_t &rl) const
std::enable_if_t< labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const Aut &aut) const
mutable_automaton< context_t > out_t
The automaton type for the composition of Lhs with Rhs.
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
typename tuple_automaton_impl::state_name_t state_name_t
static auto real_aut(const insplit_automaton< A > &aut)
Get the focus automaton from an insplit automaton.
static labelset_t make_labelset_(const hidden_l_labelset_t &ll, seq< I1... >, const hidden_r_labelset_t &rl, seq< I2... >)
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...
typename super_t::state_name_t state_name_t
Tuple of states of input automata.
void add_transitions(const state_t src, const state_name_t &psrc)
Callback for complete_ when lazy.
bool are_proper_in(const state_name_t &psrc, seq< I... >) const
Whether no tapes in the sequence have spontaneous incoming transitions.
ATTRIBUTE_NORETURN std::enable_if_t<!labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const Aut &) const
Decorator implementing the laziness for an algorithm.
join_t< weightset_t_of< context_t_of< Lhs > >, weightset_t_of< context_t_of< Rhs > >> weightset_t
typename type_helper_t::hidden_l_labelset_t hidden_l_labelset_t
std::shared_ptr< detail::compose_automaton_impl< Lazy, Lhs, Rhs > > compose_automaton
A compose automaton as a shared pointer.
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
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.
void initialize_compose()
Fill the worklist with the initial source-state pairs, as needed for the composition algorithm...
res_labelset_t_of< crhs_t > hidden_r_labelset_t
Build the (accessible part of the) composition.
Cache the outgoing transitions of an automaton as efficient maps label -> vector<(weight, dst)>.
typename labelset_t::value_t res_label_t
res_labelset_t_of< clhs_t > hidden_l_labelset_t
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
typename type_helper_t::res_label_t res_label_t
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
An input/output format for valuesets.
Provide a variadic mul on top of a binary mul(), and one().
auto & as()
Extract wrapped typed automaton.
void compose()
The (accessible part of the) composition of lhs_ and rhs_.
typename type_helper_t::context_t context_t
Build the static sequence of size_t [0, N[.
constexpr std::enable_if_t<!labelset_t_of< Aut >::has_one(), bool > is_one(const Aut &, transition_t_of< Aut >) const
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.
std::enable_if_t< labelset_t_of< Aut >::has_one(), res_label_t_of< Aut > > get_hidden_one(const insplit_automaton< Aut > &aut) const
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
std::enable_if_t< labelset_t_of< Aut >::has_one(), bool > is_one(const Aut &aut, transition_t_of< Aut > tr) const
Build the (accessible part of the) composition.
typename full_context_t_of_impl< Aut >::type full_context_t_of
typename type_helper_t::hidden_r_label_t hidden_r_label_t
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...
typename labelset_t::value_t label_t
typename type_helper_t::out_t out_t
typename tuple_automaton_impl::state_t state_t
typename concat_tupleset< hidden_l_labelset_t, hidden_r_labelset_t >::type labelset_t
The type of context of the result.
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)...
std::remove_cv_t< std::remove_reference_t< T > > base_t
T without reference or const/volatile qualifiers.
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
static labelset_t make_labelset_(const hidden_l_labelset_t &ll, const hidden_r_labelset_t &rl)
std::tuple< Lhs, Rhs > automata_t
The type of input automata.
typename res_label_t_of_impl< Aut >::type res_label_t_of
static auto real_aut(const A &aut)
Get the focus automaton, possibly from a non insplit automaton.
typename type_helper_t::weightset_t weightset_t