Vcsn  2.1
Be Rational
conjunction.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <map>
5 #include <utility>
6 
7 #include <vcsn/algos/insplit.hh>
8 #include <vcsn/algos/strip.hh>
12 #include <vcsn/ctx/context.hh>
13 #include <vcsn/ctx/traits.hh>
14 #include <vcsn/dyn/automaton.hh> // dyn::make_automaton
15 #include <vcsn/dyn/expression.hh> // dyn::make_expression
16 #include <vcsn/misc/tuple.hh> // tuple_element_t, cross_tuple
17 #include <vcsn/misc/zip-maps.hh>
18 
19 namespace vcsn
20 {
21  namespace detail
22  {
23  /*---------------------------------.
24  | product_automaton_impl<Aut...>. |
25  `---------------------------------*/
26 
28  template <typename Aut, typename... Auts>
30  : public automaton_decorator<tuple_automaton<Aut, Auts...>>
31  {
32  static_assert(all_<labelset_t_of<Auts>::is_letterized()...>(),
33  "product: requires letterized labels");
34 
36  using automaton_t = Aut;
40 
41  public:
42  using state_name_t
43  = typename tuple_automaton_t::element_type::state_name_t;
44  using state_t
45  = typename tuple_automaton_t::element_type::state_t;
46  template <size_t... I>
47  using seq
48  = typename tuple_automaton_t::element_type::template seq<I...>;
49 
50  static symbol sname()
51  {
52  static symbol res("product_automaton"
53  + tuple_automaton_t::element_type::sname_());
54  return res;
55  }
56 
57  std::ostream& print_set(std::ostream& o, format fmt = {}) const
58  {
59  o << "product_automaton";
60  return aut_->print_set_(o, fmt);
61  }
62 
67 
68  using label_t = typename labelset_t::value_t;
69  using weight_t = typename weightset_t::value_t;
70 
71  public:
73  using automata_t = std::tuple<Auts...>;
74 
76  template <size_t I>
78 
79  using super_t::aut_;
80 
84  product_automaton_impl(Aut aut, const Auts&... auts)
85  : super_t{make_tuple_automaton(aut, auts...)}
86  , transition_maps_{{auts, ws_}...}
87  {}
88 
90  auto origins() const
91  -> decltype(aut_->origins())
92  {
93  return aut_->origins();
94  }
95 
98  bool state_is_strict(state_t s) const
99  {
100  return has(done_, s);
101  }
102 
104  void complete_(state_t s) const
105  {
106  const auto& orig = origins();
107  state_name_t sn = orig.at(s);
108  const_cast<self_t&>(*this).add_conjunction_transitions(s, sn);
109  done_.insert(s);
110  }
111 
113  using super_t::all_out;
114  auto all_out(state_t s) const
115  -> decltype(aut_->all_out(s))
116  {
117  if (!state_is_strict(s))
118  complete_(s);
119  return aut_->all_out(s);
120  }
121 
123  template <typename Pred>
124  auto all_out(state_t s, Pred pred) const
125  -> decltype(aut_->all_out(s, pred))
126  {
127  if (!state_is_strict(s))
128  complete_(s);
129  return aut_->all_out(s, pred);
130  }
131 
132  // FIXME: clang workaround.
134  {
136  {
137  return aut_.labelset()->equal(aut_.label_of(t), label_);
138  }
139  const self_t& aut_;
140  // Capture by copy: in the case of the transpose_automaton, the
141  // labels are transposed, so they are temporaries.
143  };
144 
145  // FIXME: clang workaround.
147  {
149  {
150  return aut_.dst_of(t) != aut_.post();
151  }
152  const self_t& aut_;
153  };
154 
157  auto out(state_t s)
158  -> decltype(this->all_out(s, not_to_post_p{*this}))
159  {
160  return all_out(s, not_to_post_p{*this});
161  }
162 
166  -> decltype(this->all_out(s, label_equal_p{*this, l}))
167  {
168  return all_out(s, label_equal_p{*this, l});
169  }
170 
172  void conjunction(bool lazy = false)
173  {
175 
176  if (!lazy)
177  while (!aut_->todo_.empty())
178  {
179  const auto& p = aut_->todo_.front();
180  add_conjunction_transitions(std::get<1>(p), std::get<0>(p));
181  aut_->todo_.pop_front();
182  }
183  }
184 
186  void shuffle()
187  {
189 
190  while (!aut_->todo_.empty())
191  {
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();
195  }
196  }
197 
200  {
201  // Variadic infiltration is not trivial to implement, it's not
202  // just conjunction and shuffle in series. For instance, consider
203  // three automata:
204  //
205  // <x>a
206  // x = -> 0 ------> 1 ->
207  //
208  // and likewise for y and z. Let's use `&:` to denote
209  // infiltration. In (x &: y) there is a transition ((0,0),
210  // <xy>a, (1,1)) coming from the conjunction-like transitions.
211  //
212  // Therefore in (x &: y) &: z there is a transition ((0,0),0),
213  // <xy>a, (1,1), 0) by virtue of the shuffle-like transitions.
214  //
215  // This kind of transition that mixes conjunction and shuffle
216  // would never appear in a naive implementation with only
217  // conjunction and shuffle transitions, but no combinations.
218  require(sizeof...(Auts) == 2,
219  "infiltration: variadic product does not work");
220 
221  // Infiltrate is a mix of conjunction and shuffle operations, and
222  // the initial states for shuffle are a superset of the
223  // initial states for conjunction:
225 
226  while (!aut_->todo_.empty())
227  {
228  const auto& p = aut_->todo_.front();
229  // Infiltrate is a mix of conjunction and shuffle operations.
230  //
231  // Conjunction transitions must be added before shuffle ones:
232  // this way "conjunction" can use "new_transition" only, which
233  // is faster than "add_transition".
234  add_conjunction_transitions(std::get<1>(p), std::get<0>(p));
235  add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
236 
237  aut_->todo_.pop_front();
238  }
239  }
240 
241  private:
245  {
246  aut_->todo_.emplace_back(aut_->pre_(), aut_->pre());
247  }
248 
252  {
253  // Make the result automaton initial states: same as the
254  // conjunction of pre: synchronized transitions on $.
255  add_conjunction_transitions(aut_->pre(), aut_->pre_());
256  }
257 
259  template <typename... Args>
260  state_t state(Args&&... args)
261  {
262  return aut_->state(std::forward<Args>(args)...);
263  }
264 
267  template <typename A>
269 
271  std::tuple<typename transition_map_t<Auts>::map_t&...>
272  out_(const state_name_t& ss)
273  {
274  return out_(ss, aut_->indices);
275  }
276 
277  template <size_t... I>
278  std::tuple<typename transition_map_t<Auts>::map_t&...>
280  {
281  return std::tie(std::get<I>(transition_maps_)[std::get<I>(ss)]...);
282  }
283 
289  const state_name_t& psrc)
290  {
291  for (auto t: zip_map_tuple(out_(psrc)))
292  // These are always new transitions: first because the
293  // source state is visited for the first time, and second
294  // because the couple (left destination, label) is unique,
295  // and so is (right destination, label).
296  if (!aut_->labelset()->is_one(t.first))
298  ([this,src,&t]
299  (const typename transition_map_t<Auts>::transition&... ts)
300  {
301  this->new_transition(src, state(ts.dst...),
302  t.first,
303  ws_.mul(ts.weight()...));
304  },
305  t.second);
306  add_one_transitions_(src, psrc, aut_->indices);
307  }
308 
311  template <std::size_t... I>
312  void
313  add_one_transitions_(const state_t src, const state_name_t& psrc,
314  seq<I...>)
315  {
316  using swallow = int[];
317  (void) swallow
318  {
319  (maybe_add_one_transitions_<I>(*(std::get<I>(aut_->auts_)->labelset()),
320  src, psrc), 0)...
321  };
322  }
323 
325  template <std::size_t I, typename L>
328  {}
329 
332  template <std::size_t I, typename L>
334  maybe_add_one_transitions_(const L& ls, const state_t src,
335  const state_name_t& psrc)
336  {
337  if (!has_one_in(psrc, I + 1, aut_->indices)
338  && !has_only_one_out(psrc, I, aut_->indices))
339  {
340  // one is guaranteed to be first.
341  const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
342  if (ls.is_one(tmap.begin()->first))
343  for (auto t : tmap.begin()->second)
344  {
345  auto pdst = psrc;
346  std::get<I>(pdst) = t.dst;
347  this->new_transition(src, state(pdst), ls.one(), t.weight());
348  }
349  }
350  }
351 
354  template <std::size_t... I>
355  bool has_one_in(const state_name_t& psrc, std::size_t i,
356  seq<I...>) const
357  {
358  bool has_ones[] = { is_spontaneous_in(std::get<I>(aut_->auts_),
359  std::get<I>(psrc))... };
360  for (; i < sizeof...(Auts); ++i)
361  if (has_ones[i])
362  return true;
363  return false;
364  }
365 
368  template <std::size_t... I>
369  bool has_only_one_out(const state_name_t& psrc, std::size_t i,
370  seq<I...>)
371  {
372  bool has_ones[] = { has_only_ones_out<I>(psrc)... };
373  for (size_t j = 0; j < i; ++j)
374  if (has_ones[j])
375  return true;
376  return false;
377  }
378 
381  template <typename Aut_>
383  is_one(const Aut_& aut, transition_t_of<Aut_> tr) const
384  {
385  return aut->labelset()->is_one(aut->label_of(tr));
386  }
387 
390  template <typename Aut_>
392  is_one(const Aut_&, transition_t_of<Aut_>) const
393  {
394  return false;
395  }
396 
400  template <typename Aut_>
402  is_spontaneous_in(const Aut_&,
403  state_t_of<Aut_>) const
404  {
405  return false;
406  }
407 
412  template <typename Aut_>
414  is_spontaneous_in(const Aut_& rhs, state_t_of<Aut_> rst) const
415  {
416  auto rin = rhs->all_in(rst);
417  auto rtr = rin.begin();
418  return rtr != rin.end() && is_one(rhs, *rtr);
419  }
420 
423  template <size_t I>
424  bool
426  {
427  const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
428  auto s = tmap.size();
429  if (s == 0)
430  return true;
431  else if (2 <= s)
432  return false;
433  else
434  return std::get<I>(aut_->auts_)->labelset()->is_one(tmap.begin()->first);
435  }
436 
441  template <bool Infiltration = false>
443  const state_name_t& psrc)
444  {
445  weight_t final
446  = add_shuffle_transitions_<Infiltration>(src, psrc, aut_->indices);
447  aut_->set_final(src, final);
448  }
449 
454  template <bool Infiltration, size_t... I>
456  const state_name_t& psrc,
457  seq<I...>)
458  {
459  weight_t res = ws_.one();
460  using swallow = int[];
461  (void) swallow
462  {
463  (res = ws_.mul(res,
464  add_shuffle_transitions_<Infiltration, I>(src, psrc)),
465  0)...
466  };
467  return res;
468  }
469 
480  template <bool Infiltration, size_t I>
481  weight_t
483  const state_name_t& psrc)
484  {
485  // Whether is a final state.
486  weight_t res = ws_.zero();
487 
488  auto& ts = std::get<I>(transition_maps_)[std::get<I>(psrc)];
489  for (auto t: ts)
490  if (std::get<I>(aut_->auts_)->labelset()->is_special(t.first))
491  res = t.second.front().weight();
492  else
493  // The src state is visited for the first time, so all
494  // these transitions are new. *Except* in the case where
495  // we have a loop on some tapes.
496  //
497  // If add_conjunction_transitions was called before (in the
498  // case of infiltration), there may even exist such a
499  // transition in the first loop.
500  //
501  // To trigger the later case, try the self-infiltration on
502  // derived_term('a*a').
503  for (auto d: t.second)
504  {
505  auto pdst = psrc;
506  std::get<I>(pdst) = d.dst;
507  if (Infiltration
508  || std::get<I>(psrc) == d.dst)
509  this->add_transition(src, state(pdst), t.first, d.weight());
510  else
511  this->new_transition(src, state(pdst), t.first, d.weight());
512  }
513  return res;
514  }
515 
517  const weightset_t& ws_ = *aut_->weightset();
518 
520  std::tuple<transition_map_t<Auts>...> transition_maps_;
521 
525  mutable std::set<state_t> done_ = {aut_->post()};
526  };
527  }
528 
530  template <typename Aut, typename... Auts>
531  using product_automaton
532  = std::shared_ptr<detail::product_automaton_impl<Aut, Auts...>>;
533 
534  template <typename Aut, typename... Auts>
535  inline
536  auto
537  make_product_automaton(Aut aut, const Auts&... auts)
538  -> product_automaton<Aut, Auts...>
539  {
540  using res_t = product_automaton<Aut, Auts...>;
541  return make_shared_ptr<res_t>(aut, auts...);
542  }
543 
544 
545  /*-----------------------------.
546  | conjunction(automaton...). |
547  `-----------------------------*/
548 
550  template <typename... Auts>
551  inline
552  auto
553  conjunction(const Auts&... as)
554  -> tuple_automaton<decltype(meet_automata(as...)),
555  Auts...>
556  {
557  auto res = make_product_automaton(meet_automata(as...),
558  as...);
559  res->conjunction();
560  return res->strip();
561  }
562 
564  template <typename... Auts>
565  inline
566  auto
567  conjunction_lazy(const Auts&... as)
568  -> product_automaton<decltype(meet_automata(as...)),
569  Auts...>
570  {
571  auto res = make_product_automaton(meet_automata(as...),
572  as...);
573  res->conjunction(true);
574  return res;
575  }
576 
577  namespace dyn
578  {
579  namespace detail
580  {
581  template <std::size_t I, typename Aut>
583  do_insplit(Aut& aut)
584  {
585  return insplit(aut);
586  }
587 
588  template <std::size_t I, typename Aut>
590  do_insplit(Aut& aut)
591  {
592  return aut;
593  }
594 
596  template <typename Auts, size_t... I>
597  automaton
598  conjunction_(const std::vector<automaton>& as,
599  bool lazy,
601  {
602  if (lazy)
603  return make_automaton
606  else
607  return make_automaton
610  }
611 
613  template <typename Auts, typename Bool>
614  automaton
615  conjunction(const std::vector<automaton>& as,
616  bool lazy)
617  {
618  auto indices
620  return conjunction_<Auts>(as, lazy, indices);
621  }
622  }
623  }
624 
625 
626  /*------------------------.
627  | shuffle(automaton...). |
628  `------------------------*/
629 
631  template <typename... Auts>
632  inline
633  auto
634  shuffle(const Auts&... as)
635  -> tuple_automaton<decltype(join_automata(as...)),
636  Auts...>
637  {
638  auto res = make_product_automaton(join_automata(as...), as...);
639  res->shuffle();
640  return res->strip();
641  }
642 
643  namespace dyn
644  {
645  namespace detail
646  {
648  template <typename Auts, size_t... I>
649  automaton
650  shuffle_(const std::vector<automaton>& as,
652  {
653  auto res = vcsn::shuffle(as[I]->as<tuple_element_t<I, Auts>>()...);
654  return make_automaton(res);
655  }
656 
658  template <typename Auts>
659  automaton
660  shuffle(const std::vector<automaton>& as)
661  {
662  auto indices
664  return shuffle_<Auts>(as, indices);
665  }
666  }
667  }
668 
669 
670  /*-----------------------------------.
671  | shuffle(expression, expression). |
672  `-----------------------------------*/
673 
675  template <typename ValueSet>
676  inline
677  typename ValueSet::value_t
678  shuffle(const ValueSet& vs,
679  const typename ValueSet::value_t& lhs,
680  const typename ValueSet::value_t& rhs)
681  {
682  return vs.shuffle(lhs, rhs);
683  }
684 
685  namespace dyn
686  {
687  namespace detail
688  {
690  template <typename ExpSetLhs, typename ExpSetRhs>
691  expression
692  shuffle_expression(const expression& lhs, const expression& rhs)
693  {
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());
699  return make_expression(rs, ::vcsn::shuffle(rs, lr, rr));
700  }
701  }
702  }
703 
704 
705  /*-----------------------------.
706  | infiltration(automaton...). |
707  `-----------------------------*/
708 
710  template <typename A1, typename A2>
711  inline
712  auto
713  infiltration(const A1& a1, const A2& a2)
714  -> tuple_automaton<decltype(join_automata(a1, a2)),
715  A1, A2>
716  {
717  auto res = make_product_automaton(join_automata(a1, a2), a1, a2);
718  res->infiltration();
719  return res->strip();
720  }
721 
723  template <typename A1, typename A2, typename A3, typename... Auts>
724  inline
725  auto
726  infiltration(const A1& a1, const A2& a2, const A3& a3, const Auts&... as)
727  -> decltype(infiltration(infiltration(a1, a2), a3, as...))
728  {
729  return infiltration(infiltration(a1, a2), a3, as...);
730  }
731 
732  namespace dyn
733  {
734  namespace detail
735  {
737  template <typename Auts, size_t... I>
738  automaton
739  infiltration_(const std::vector<automaton>& as,
741  {
742  auto res
743  = vcsn::infiltration(as[I]->as<tuple_element_t<I, Auts>>()...);
744  return make_automaton(res);
745  }
746 
748  template <typename Auts>
749  automaton
750  infiltration(const std::vector<automaton>& as)
751  {
752  auto indices
754  return infiltration_<Auts>(as, indices);
755  }
756  }
757  }
758 
759  /*----------------------------------------.
760  | infiltration(expression, expression). |
761  `----------------------------------------*/
762 
764  template <typename ValueSet>
765  inline
766  typename ValueSet::value_t
767  infiltration(const ValueSet& vs,
768  const typename ValueSet::value_t& lhs,
769  const typename ValueSet::value_t& rhs)
770  {
771  return vs.infiltration(lhs, rhs);
772  }
773 
774  namespace dyn
775  {
776  namespace detail
777  {
779  template <typename ExpSetLhs, typename ExpSetRhs>
780  expression
782  {
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());
788  return make_expression(rs, ::vcsn::infiltration(rs, lr, rr));
789  }
790  }
791  }
792 
793 
794  /*-----------------------------.
795  | conjunction(automaton, n). |
796  `-----------------------------*/
797 
798  template <typename Aut>
799  auto
800  conjunction(const Aut& aut, unsigned n)
802  {
803  auto res = make_fresh_automaton(aut);
804  {
805  // automatonset::one().
806  auto s = res->new_state();
807  res->set_initial(s);
808  res->set_final(s);
809  for (auto l: res->context().labelset()->genset())
810  res->new_transition(s, s, l);
811  }
812 
813  if (n)
814  {
815  // FIXME: for 1, we should return the accessible part only.
816  static bool iterative = getenv("VCSN_ITERATIVE");
817  if (iterative)
818  for (size_t i = 0; i < n; ++i)
819  res = strip(conjunction(res, aut));
820  else
821  {
822  auto power = strip(aut);
823  while (true)
824  {
825  if (n % 2)
826  res = strip(conjunction(res, power));
827  n /= 2;
828  if (!n)
829  break;
830  power = strip(conjunction(power, power));
831  }
832  }
833  }
834 
835  return res;
836  }
837 
838 
839  namespace dyn
840  {
841  namespace detail
842  {
844  template <typename Aut, typename Unsigned>
845  automaton
846  conjunction_repeated(const automaton& aut, unsigned n)
847  {
848  const auto& a = aut->as<Aut>();
849  return make_automaton(::vcsn::conjunction(a, n));
850  }
851  }
852  }
853 
854 
855  /*---------------------------------------.
856  | conjunction(expression, expression). |
857  `---------------------------------------*/
858 
860  template <typename ExpSet>
861  inline
862  typename ExpSet::value_t
863  conjunction(const ExpSet& rs,
864  const typename ExpSet::value_t& lhs,
865  const typename ExpSet::value_t& rhs)
866  {
867  return rs.conjunction(lhs, rhs);
868  }
869 
870  namespace dyn
871  {
872  namespace detail
873  {
875  template <typename ExpSetLhs, typename ExpSetRhs>
876  expression
878  {
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());
884  return make_expression(rs, ::vcsn::conjunction(rs, lr, rr));
885  }
886  }
887  }
888 }
void shuffle()
Compute the (accessible part of the) shuffle product.
Definition: conjunction.hh:186
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.
Definition: traits.hh:12
product_automaton_impl self_t
Definition: conjunction.hh:38
std::tuple< transition_map_t< Auts >...> transition_maps_
Transition caches.
Definition: conjunction.hh:520
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:46
std::shared_ptr< detail::product_automaton_impl< Aut, Auts...>> product_automaton
A product automaton as a shared pointer.
Definition: conjunction.hh:532
bool operator()(transition_t_of< self_t > t) const
Definition: conjunction.hh:135
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I...>)
Bridge helper.
Definition: conjunction.hh:598
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.
Definition: conjunction.hh:64
state_t state(Args &&...args)
Conversion from state name to state number.
Definition: conjunction.hh:260
const weightset_t & ws_
The resulting weightset.
Definition: conjunction.hh:517
Aut automaton_t
The type of the resulting automaton.
Definition: conjunction.hh:36
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.
Definition: conjunction.hh:165
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. ...
Definition: conjunction.hh:369
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
Definition: copy.hh:239
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I...>)
Variadic bridge helper.
Definition: conjunction.hh:739
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.
Definition: conjunction.hh:414
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
void initialize_conjunction()
Fill the worklist with the initial source-state pairs, as needed for the conjunction algorithm...
Definition: conjunction.hh:244
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
Definition: traits.hh:48
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:45
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...
Definition: conjunction.hh:455
constexpr bool all_()
Definition: tuple.hh:404
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
auto conjunction_lazy(const Auts &...as) -> product_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:567
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.
Definition: conjunction.hh:650
typename std::enable_if< Cond, T >::type enable_if_t
Definition: type_traits.hh:16
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Aut, Auts...>
Definition: conjunction.hh:537
std::tuple< Auts...> automata_t
The type of input automata.
Definition: conjunction.hh:73
void infiltration()
Compute the (accessible part of the) infiltration product.
Definition: conjunction.hh:199
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...>)
Definition: conjunction.hh:279
auto all_out(state_t s) const -> decltype(aut_->all_out(s))
Definition: conjunction.hh:114
void conjunction(bool lazy=false)
Compute the (accessible part of the) conjunction.
Definition: conjunction.hh:172
void cross_tuple(Fun f, const std::tuple< Ts...> &ts)
Definition: tuple.hh:235
auto infiltration(const A1 &a1, const A2 &a2) -> tuple_automaton< decltype(join_automata(a1, a2)), A1, A2 >
The (accessible part of the) infiltration product.
Definition: conjunction.hh:713
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:28
typename tuple_automaton_t::element_type::state_t state_t
Definition: conjunction.hh:45
typename tuple_automaton_t::element_type::state_name_t state_name_t
Definition: conjunction.hh:43
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.
Definition: conjunction.hh:288
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
std::shared_ptr< const node< Context >> expression
Definition: fwd.hh:182
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...
Definition: conjunction.hh:442
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
Definition: conjunction.hh:781
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts...>
The (accessible part of the) shuffle product.
Definition: conjunction.hh:634
std::tuple< typename transition_map_t< Auts >::map_t &...> out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
Definition: conjunction.hh:272
tuple_automaton< automaton_t, Auts...> tuple_automaton_t
Definition: conjunction.hh:37
An input/output format.
Definition: format.hh:11
auto out(state_t s) -> decltype(this->all_out(s, not_to_post_p
Indexes of visible transitions leaving state s.
Definition: conjunction.hh:157
bool operator()(transition_t_of< self_t > t) const
Definition: conjunction.hh:148
vcsn::enable_if_t< labelset_t_of< Aut >::has_one(), Aut > insplit(Aut &aut)
Definition: insplit.hh:90
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
Definition: conjunction.hh:846
std::shared_ptr< detail::tuple_automaton_impl< Auts...>> tuple_automaton
A tuple automaton as a shared pointer.
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:553
typename tuple_automaton_t::element_type::template seq< I...> seq
Definition: conjunction.hh:48
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).
Definition: conjunction.hh:383
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:47
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: conjunction.hh:57
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.
Definition: conjunction.hh:327
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:49
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.
Definition: conjunction.hh:313
auto rs
Definition: lift.hh:151
auto make_tuple_automaton(const Auts &...auts) -> tuple_automaton< Auts...>
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).
Definition: conjunction.hh:877
Build the (accessible part of the) product.
Definition: conjunction.hh:29
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
vcsn::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
Definition: conjunction.hh:590
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.
Definition: conjunction.hh:482
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
Definition: expression.hh:83
typename weightset_t::value_t weight_t
Definition: conjunction.hh:69
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.
Definition: conjunction.hh:334
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
weightset_t_of< context_t > weightset_t
Definition: conjunction.hh:66
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
Definition: conjunction.hh:77
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:78
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.
Definition: conjunction.hh:392
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
Definition: conjunction.hh:692
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.
Definition: conjunction.hh:251
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.
Definition: conjunction.hh:402
zipped_maps< Dereference, Maps...> zip_map_tuple(const std::tuple< Maps...> &maps)
Definition: zip-maps.hh:257
automaton_t aut_
The wrapped automaton, possibly const.
typename labelset_t::value_t label_t
Definition: conjunction.hh:68
product_automaton_impl(Aut aut, const Auts &...auts)
Build a product automaton.
Definition: conjunction.hh:84
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).
Definition: conjunction.hh:525
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.
Definition: conjunction.hh:355
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...
Definition: conjunction.hh:425
auto all_out(state_t s, Pred pred) const -> decltype(aut_->all_out(s, pred))
All the outgoing transitions satisfying the predicate.
Definition: conjunction.hh:124
labelset_t_of< context_t > labelset_t
Definition: conjunction.hh:65