Vcsn  2.2a
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>
9 #include <vcsn/algos/copy.hh>
10 #include <vcsn/algos/transpose.hh>
15 #include <vcsn/ctx/context.hh>
16 #include <vcsn/ctx/traits.hh>
17 #include <vcsn/dyn/automaton.hh> // dyn::make_automaton
18 #include <vcsn/dyn/expression.hh> // dyn::make_expression
19 #include <vcsn/dyn/polynomial.hh>
20 #include <vcsn/misc/tuple.hh> // tuple_element_t, cross_tuple
21 #include <vcsn/misc/zip-maps.hh>
22 
23 namespace vcsn
24 {
25  namespace detail
26  {
27  /*---------------------------------.
28  | product_automaton_impl<Aut...>. |
29  `---------------------------------*/
30 
32  template <bool Lazy, Automaton Aut, Automaton... Auts>
34  : public lazy_tuple_automaton<product_automaton_impl<Lazy, Aut, Auts...>, false, Lazy, Aut, Auts...>
35  {
36  static_assert(all_<labelset_t_of<Auts>::is_letterized()...>(),
37  "product: requires letterized labels");
38 
40  using automaton_t = Aut;
43  using super_t = lazy_tuple_automaton<self_t, false, Lazy, Aut, Auts...>;
44 
45  public:
47  using state_t = typename super_t::state_t;
48 
49  template <Automaton A>
50  using transition_map_t = typename super_t::template transition_map_t<A>;
51 
52  template <size_t... I>
53  using seq
54  = typename tuple_automaton_t::element_type::template seq<I...>;
55 
56  using super_t::ws_;
58 
59  static symbol sname()
60  {
61  static symbol res("product_automaton"
62  + super_t::sname_(std::string{Lazy ? "true" : "false"}));
63  return res;
64  }
65 
66  std::ostream& print_set(std::ostream& o, format fmt = {}) const
67  {
68  o << "product_automaton";
69  return aut_->print_set_(o, fmt);
70  }
71 
76 
77  using label_t = typename labelset_t::value_t;
78  using weight_t = typename weightset_t::value_t;
79 
81  using automata_t = std::tuple<Auts...>;
82 
84  template <size_t I>
86 
87  using super_t::aut_;
88 
92  product_automaton_impl(Aut aut, const Auts&... auts)
93  : super_t{aut, auts...}
94  {}
95 
97  void conjunction()
98  {
100 
101  if (!Lazy)
102  while (!aut_->todo_.empty())
103  {
104  const auto& p = aut_->todo_.front();
105  this->complete_(std::get<1>(p));
106  aut_->todo_.pop_front();
107  }
108  }
109 
111  // Division only makes sense for two automata.
112  // Lazy version is not implemented yet.
113  template <bool L = Lazy>
114  std::enable_if_t<sizeof...(Auts) == 2 && !L> ldiv_here()
115  {
117 
118  using rhs_t = tuple_element_t<1, std::tuple<Auts...>>;
119  auto new_initials = std::vector<state_t_of<rhs_t>>();
120 
121  const auto& lhs = std::get<0>(aut_->auts_);
122  auto& rhs = std::get<1>(aut_->auts_);
123 
124  while (!aut_->todo_.empty())
125  {
126  const auto& p = aut_->todo_.front();
127  const auto& state_name = std::get<0>(p);
128  this->complete_(std::get<1>(p));
129 
130  // If lhs's state is final, rhs's corresponding state is initial.
131  if (lhs->is_final(std::get<0>(state_name)))
132  new_initials.push_back(std::get<1>(state_name));
133  aut_->todo_.pop_front();
134  }
135 
136  for (auto t: initial_transitions(rhs))
137  rhs->unset_initial(rhs->dst_of(t));
138  for (auto s: new_initials)
139  rhs->set_initial(s);
140  }
141 
143  void shuffle()
144  {
146 
147  while (!aut_->todo_.empty())
148  {
149  const auto& p = aut_->todo_.front();
150  add_shuffle_transitions<false>(std::get<1>(p), std::get<0>(p));
151  aut_->todo_.pop_front();
152  }
153  }
154 
157  {
158  // Variadic infiltration is not trivial to implement, it's not
159  // just conjunction and shuffle in series. For instance, consider
160  // three automata:
161  //
162  // <x>a
163  // x = -> 0 ------> 1 ->
164  //
165  // and likewise for y and z. Let's use `&:` to denote
166  // infiltration. In (x &: y) there is a transition ((0,0),
167  // <xy>a, (1,1)) coming from the conjunction-like transitions.
168  //
169  // Therefore in (x &: y) &: z there is a transition ((0,0),0),
170  // <xy>a, (1,1), 0) by virtue of the shuffle-like transitions.
171  //
172  // This kind of transition that mixes conjunction and shuffle
173  // would never appear in a naive implementation with only
174  // conjunction and shuffle transitions, but no combinations.
175  require(sizeof...(Auts) == 2,
176  "infiltration: variadic product does not work");
177 
178  // Infiltrate is a mix of conjunction and shuffle operations, and
179  // the initial states for shuffle are a superset of the
180  // initial states for conjunction:
182 
183  while (!aut_->todo_.empty())
184  {
185  const auto& p = aut_->todo_.front();
186  // Infiltrate is a mix of conjunction and shuffle operations.
187  //
188  // Conjunction transitions must be added before shuffle ones:
189  // this way "conjunction" can use "new_transition" only, which
190  // is faster than "add_transition".
191  add_conjunction_transitions(std::get<1>(p), std::get<0>(p));
192  add_shuffle_transitions<true>(std::get<1>(p), std::get<0>(p));
193 
194  aut_->todo_.pop_front();
195  }
196  }
197 
199  void add_transitions(const state_t src,
200  const state_name_t& psrc)
201  {
202  add_conjunction_transitions(src, psrc);
203  }
204 
205  private:
209  {
210  aut_->todo_.emplace_back(aut_->pre_(), aut_->pre());
211  }
212 
216  {
217  // Make the result automaton initial states: same as the
218  // conjunction of pre: synchronized transitions on $.
219  add_conjunction_transitions(aut_->pre(), aut_->pre_());
220  }
221 
222 
223  using super_t::out_;
224  using super_t::state;
230  const state_name_t& psrc)
231  {
232  for (auto t: zip_map_tuple(out_(psrc)))
233  // These are always new transitions: first because the
234  // source state is visited for the first time, and second
235  // because the couple (left destination, label) is unique,
236  // and so is (right destination, label).
237  if (!aut_->labelset()->is_one(t.first))
239  ([this,src,&t]
240  (const typename transition_map_t<Auts>::transition&... ts)
241  {
242  this->new_transition(src, state(ts.dst...),
243  t.first,
244  ws_.mul(ts.weight()...));
245  },
246  t.second);
247  add_one_transitions_(src, psrc, aut_->indices);
248  }
249 
252  template <std::size_t... I>
253  void
254  add_one_transitions_(const state_t src, const state_name_t& psrc,
255  seq<I...>)
256  {
257  using swallow = int[];
258  (void) swallow
259  {
260  (maybe_add_one_transitions_<I>(*(std::get<I>(aut_->auts_)->labelset()),
261  src, psrc), 0)...
262  };
263  }
264 
266  template <std::size_t I, typename L>
267  std::enable_if_t<!L::has_one(), void>
269  {}
270 
273  template <std::size_t I, typename L>
274  std::enable_if_t<L::has_one(), void>
275  maybe_add_one_transitions_(const L& ls, const state_t src,
276  const state_name_t& psrc)
277  {
278  if (!has_one_in(psrc, I + 1, aut_->indices)
279  && !has_only_one_out(psrc, I, aut_->indices))
280  {
281  // one is guaranteed to be first.
282  const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
283  if (!tmap.empty() && ls.is_one(tmap.begin()->first))
284  for (auto t : tmap.begin()->second)
285  {
286  auto pdst = psrc;
287  std::get<I>(pdst) = t.dst;
288  this->new_transition(src, state(pdst), ls.one(), t.weight());
289  }
290  }
291  }
292 
295  template <std::size_t... I>
296  bool has_one_in(const state_name_t& psrc, std::size_t i,
297  seq<I...>) const
298  {
299  bool has_ones[] = { is_spontaneous_in(std::get<I>(aut_->auts_),
300  std::get<I>(psrc))... };
301  for (; i < sizeof...(Auts); ++i)
302  if (has_ones[i])
303  return true;
304  return false;
305  }
306 
309  template <std::size_t... I>
310  bool has_only_one_out(const state_name_t& psrc, std::size_t i,
311  seq<I...>)
312  {
313  bool has_ones[] = { has_only_ones_out<I>(psrc)... };
314  for (size_t j = 0; j < i; ++j)
315  if (has_ones[j])
316  return true;
317  return false;
318  }
319 
322  template <Automaton Aut_>
323  std::enable_if_t<labelset_t_of<Aut_>::has_one(), bool>
324  is_one(const Aut_& aut, transition_t_of<Aut_> tr) const
325  {
326  return aut->labelset()->is_one(aut->label_of(tr));
327  }
328 
331  template <Automaton Aut_>
332  constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(), bool>
333  is_one(const Aut_&, transition_t_of<Aut_>) const
334  {
335  return false;
336  }
337 
341  template <Automaton Aut_>
342  constexpr std::enable_if_t<!labelset_t_of<Aut_>::has_one(), bool>
343  is_spontaneous_in(const Aut_&,
344  state_t_of<Aut_>) const
345  {
346  return false;
347  }
348 
353  template <Automaton Aut_>
354  std::enable_if_t<labelset_t_of<Aut_>::has_one(), bool>
355  is_spontaneous_in(const Aut_& rhs, state_t_of<Aut_> rst) const
356  {
357  auto rin = all_in(rhs, rst);
358  auto rtr = rin.begin();
359  return rtr != rin.end() && is_one(rhs, *rtr);
360  }
361 
364  template <size_t I>
365  bool
367  {
368  const auto& tmap = std::get<I>(transition_maps_)[std::get<I>(psrc)];
369  auto s = tmap.size();
370  if (s == 0)
371  return true;
372  else if (2 <= s)
373  return false;
374  else
375  return std::get<I>(aut_->auts_)->labelset()->is_one(tmap.begin()->first);
376  }
377 
382  template <bool Infiltration = false>
384  const state_name_t& psrc)
385  {
386  weight_t final
387  = add_shuffle_transitions_<Infiltration>(src, psrc, aut_->indices);
388  aut_->set_final(src, final);
389  }
390 
395  template <bool Infiltration, size_t... I>
397  const state_name_t& psrc,
398  seq<I...>)
399  {
400  weight_t res = ws_.one();
401  using swallow = int[];
402  (void) swallow
403  {
404  (res = ws_.mul(res,
405  add_shuffle_transitions_<Infiltration, I>(src, psrc)),
406  0)...
407  };
408  return res;
409  }
410 
421  template <bool Infiltration, size_t I>
422  weight_t
424  const state_name_t& psrc)
425  {
426  // Whether is a final state.
427  weight_t res = ws_.zero();
428 
429  auto& ts = std::get<I>(transition_maps_)[std::get<I>(psrc)];
430  for (auto t: ts)
431  if (std::get<I>(aut_->auts_)->labelset()->is_special(t.first))
432  res = t.second.front().weight();
433  else
434  // The src state is visited for the first time, so all
435  // these transitions are new. *Except* in the case where
436  // we have a loop on some tapes.
437  //
438  // If add_conjunction_transitions was called before (in the
439  // case of infiltration), there may even exist such a
440  // transition in the first loop.
441  //
442  // To trigger the later case, try the self-infiltration on
443  // derived_term('a*a').
444  for (auto d: t.second)
445  {
446  auto pdst = psrc;
447  std::get<I>(pdst) = d.dst;
448  if (Infiltration
449  || std::get<I>(psrc) == d.dst)
450  this->add_transition(src, state(pdst), t.first, d.weight());
451  else
452  this->new_transition(src, state(pdst), t.first, d.weight());
453  }
454  return res;
455  }
456  };
457  }
458 
460  template <bool Lazy, Automaton Aut, Automaton... Auts>
461  using product_automaton
462  = std::shared_ptr<detail::product_automaton_impl<Lazy, Aut, Auts...>>;
463 
464  template <bool Lazy, Automaton Aut, Automaton... Auts>
465  inline
466  auto
467  make_product_automaton(Aut aut, const Auts&... auts)
468  -> product_automaton<Lazy, Aut, Auts...>
469  {
470  using res_t = product_automaton<Lazy, Aut, Auts...>;
471  return make_shared_ptr<res_t>(aut, auts...);
472  }
473 
474 
475  /*-----------------------------.
476  | conjunction(automaton...). |
477  `-----------------------------*/
478 
480  template <Automaton... Auts>
481  auto
482  conjunction(const Auts&... as)
483  -> tuple_automaton<decltype(meet_automata(as...)),
484  Auts...>
485  {
486  auto res = make_product_automaton<false>(meet_automata(as...),
487  as...);
488  res->conjunction();
489  return res->strip();
490  }
491 
493  template <Automaton... Auts>
494  auto
495  conjunction_lazy(const Auts&... as)
496  -> product_automaton<true, decltype(meet_automata(as...)),
497  Auts...>
498  {
499  auto res = make_product_automaton<true>(meet_automata(as...),
500  as...);
501  res->conjunction();
502  return res;
503  }
504 
505  namespace dyn
506  {
507  namespace detail
508  {
509  template <std::size_t I, Automaton Aut>
510  auto
511  do_insplit(Aut& aut)
512  -> std::enable_if_t<labelset_t_of<Aut>::has_one() && I != 0,
513  decltype(insplit(aut))>
514  {
515  return insplit(aut);
516  }
517 
518  template <std::size_t I, Automaton Aut>
519  std::enable_if_t<!labelset_t_of<Aut>::has_one() || I == 0, Aut&>
520  do_insplit(Aut& aut)
521  {
522  return aut;
523  }
524 
526  template <typename Auts, size_t... I>
527  automaton
528  conjunction_(const std::vector<automaton>& as, bool lazy,
530  {
531  if (lazy)
532  return make_automaton
534  (do_insplit<I>(as[I]->as<tuple_element_t<I, Auts>>())...));
535  else
536  return make_automaton
538  (do_insplit<I>(as[I]->as<tuple_element_t<I, Auts>>())...));
539  }
540 
542  template <typename Auts, typename Bool>
543  automaton
544  conjunction(const std::vector<automaton>& as, bool lazy)
545  {
546  auto indices
548  return conjunction_<Auts>(as, lazy, indices);
549  }
550  }
551  }
552 
553 
554  /*----------------------------------.
555  | ldiv_here(automaton, automaton). |
556  `----------------------------------*/
557 
562  template <Automaton Aut1, Automaton Aut2>
563  Aut2&
564  ldiv_here(const Aut1& lhs, Aut2& res)
565  {
566  auto prod = make_product_automaton<false>(join_automata(lhs, res), lhs, res);
567  prod->ldiv_here();
568  return res;
569  }
570 
571 
572  /*-----------------------------.
573  | ldiv(automaton, automaton). |
574  `-----------------------------*/
575 
580  template <Automaton Aut1, Automaton Aut2>
581  auto
582  ldiv(const Aut1& a1, const Aut2& a2)
583  {
584  auto res = copy(a2);
585  ldiv_here(a1, res);
586  return res;
587  }
588 
589  namespace dyn
590  {
591  namespace detail
592  {
594  template <Automaton Aut1, Automaton Aut2>
595  automaton
596  ldiv(const automaton& aut1, const automaton& aut2)
597  {
598  const auto& a1 = aut1->as<Aut1>();
599  const auto& a2 = aut2->as<Aut2>();
600  return make_automaton(vcsn::ldiv<Aut1, Aut2>(a1, a2));
601  }
602  }
603  }
604 
605 
606  /*-----------------------------.
607  | rdiv(automaton, automaton). |
608  `-----------------------------*/
609 
614  template <Automaton Aut1, Automaton Aut2>
615  auto
616  rdiv(const Aut1& a1, const Aut2& a2)
617  {
618  auto a1t = transpose(a1);
619  auto a2t = transpose(a2);
620  ldiv_here(a2t, a1t);
621  return transpose(a1t);
622  }
623 
624  namespace dyn
625  {
626  namespace detail
627  {
629  template <Automaton Aut1, Automaton Aut2>
630  automaton
631  rdiv(const automaton& aut1, const automaton& aut2)
632  {
633  const auto& a1 = aut1->as<Aut1>();
634  const auto& a2 = aut2->as<Aut2>();
635  return make_automaton(vcsn::rdiv(a1, a2));
636  }
637  }
638  }
639 
640 
641  /*------------------------.
642  | shuffle(automaton...). |
643  `------------------------*/
644 
646  template <Automaton... Auts>
647  auto
648  shuffle(const Auts&... as)
649  -> tuple_automaton<decltype(join_automata(as...)),
650  Auts...>
651  {
652  auto res = make_product_automaton<false>(join_automata(as...), as...);
653  res->shuffle();
654  return res->strip();
655  }
656 
657  namespace dyn
658  {
659  namespace detail
660  {
662  template <typename Auts, size_t... I>
663  automaton
664  shuffle_(const std::vector<automaton>& as,
666  {
667  auto res = vcsn::shuffle(as[I]->as<tuple_element_t<I, Auts>>()...);
668  return make_automaton(res);
669  }
670 
672  template <typename Auts>
673  automaton
674  shuffle(const std::vector<automaton>& as)
675  {
676  auto indices
678  return shuffle_<Auts>(as, indices);
679  }
680  }
681  }
682 
683 
684  /*-----------------------------------.
685  | shuffle(expression, expression). |
686  `-----------------------------------*/
687 
689  template <typename ValueSet>
690  typename ValueSet::value_t
691  shuffle(const ValueSet& vs,
692  const typename ValueSet::value_t& lhs,
693  const typename ValueSet::value_t& rhs)
694  {
695  return vs.shuffle(lhs, rhs);
696  }
697 
698  namespace dyn
699  {
700  namespace detail
701  {
703  template <typename ExpSetLhs, typename ExpSetRhs>
704  expression
705  shuffle_expression(const expression& lhs, const expression& rhs)
706  {
707  auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
708  return make_expression(std::get<0>(join_elts),
709  ::vcsn::shuffle(std::get<0>(join_elts),
710  std::get<1>(join_elts),
711  std::get<2>(join_elts)));
712  }
713  }
714  }
715 
716 
717  /*-----------------------------.
718  | infiltration(automaton...). |
719  `-----------------------------*/
720 
722  template <Automaton A1, Automaton A2>
723  auto
724  infiltration(const A1& a1, const A2& a2)
725  -> tuple_automaton<decltype(join_automata(a1, a2)),
726  A1, A2>
727  {
728  auto res = make_product_automaton<false>(join_automata(a1, a2), a1, a2);
729  res->infiltration();
730  return res->strip();
731  }
732 
734  template <Automaton A1, Automaton A2, Automaton A3, Automaton... Auts>
735  auto
736  infiltration(const A1& a1, const A2& a2, const A3& a3, const Auts&... as)
737  -> decltype(infiltration(infiltration(a1, a2), a3, as...))
738  {
739  return infiltration(infiltration(a1, a2), a3, as...);
740  }
741 
742  namespace dyn
743  {
744  namespace detail
745  {
747  template <typename Auts, size_t... I>
748  automaton
749  infiltration_(const std::vector<automaton>& as,
751  {
752  auto res
753  = vcsn::infiltration(as[I]->as<tuple_element_t<I, Auts>>()...);
754  return make_automaton(res);
755  }
756 
758  template <typename Auts>
759  automaton
760  infiltration(const std::vector<automaton>& as)
761  {
762  auto indices
764  return infiltration_<Auts>(as, indices);
765  }
766  }
767  }
768 
769  /*----------------------------------------.
770  | infiltration(expression, expression). |
771  `----------------------------------------*/
772 
774  template <typename ValueSet>
775  typename ValueSet::value_t
776  infiltration(const ValueSet& vs,
777  const typename ValueSet::value_t& lhs,
778  const typename ValueSet::value_t& rhs)
779  {
780  return vs.infiltration(lhs, rhs);
781  }
782 
783  namespace dyn
784  {
785  namespace detail
786  {
788  template <typename ExpSetLhs, typename ExpSetRhs>
789  expression
791  {
792  auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
793  return make_expression(std::get<0>(join_elts),
794  ::vcsn::infiltration(std::get<0>(join_elts),
795  std::get<1>(join_elts),
796  std::get<2>(join_elts)));
797  }
798  }
799  }
800 
801 
802  /*-----------------------------.
803  | conjunction(automaton, n). |
804  `-----------------------------*/
805 
806  template <Automaton Aut>
807  auto
808  conjunction(const Aut& aut, unsigned n)
810  {
811  auto res = make_fresh_automaton(aut);
812  {
813  // automatonset::one().
814  auto s = res->new_state();
815  res->set_initial(s);
816  res->set_final(s);
817  for (auto l: res->context().labelset()->generators())
818  res->new_transition(s, s, l);
819  }
820 
821  if (n)
822  {
823  // FIXME: for 1, we should return the accessible part only.
824  static bool iterative = getenv("VCSN_ITERATIVE");
825  if (iterative)
826  for (size_t i = 0; i < n; ++i)
827  res = strip(conjunction(res, aut));
828  else
829  {
830  auto power = strip(aut);
831  while (true)
832  {
833  if (n % 2)
834  res = strip(conjunction(res, power));
835  n /= 2;
836  if (!n)
837  break;
838  power = strip(conjunction(power, power));
839  }
840  }
841  }
842 
843  return res;
844  }
845 
846 
847  namespace dyn
848  {
849  namespace detail
850  {
852  template <Automaton Aut, typename Unsigned>
853  automaton
854  conjunction_repeated(const automaton& aut, unsigned n)
855  {
856  const auto& a = aut->as<Aut>();
857  return make_automaton(::vcsn::conjunction(a, n));
858  }
859  }
860  }
861 
862  /*-----------------------------.
863  | conjunction(value, value). |
864  `-----------------------------*/
865 
867  template <typename ValueSet>
868  typename ValueSet::value_t
869  conjunction(const ValueSet& rs,
870  const typename ValueSet::value_t& lhs,
871  const typename ValueSet::value_t& rhs)
872  {
873  return rs.conjunction(lhs, rhs);
874  }
875 
876  /*---------------------------------------.
877  | conjunction(expression, expression). |
878  `---------------------------------------*/
879 
880  namespace dyn
881  {
882  namespace detail
883  {
885  template <typename ExpSetLhs, typename ExpSetRhs>
886  expression
888  {
889  auto join_elts = join<ExpSetLhs, ExpSetRhs>(lhs, rhs);
890  return make_expression(std::get<0>(join_elts),
891  ::vcsn::conjunction(std::get<0>(join_elts),
892  std::get<1>(join_elts),
893  std::get<2>(join_elts)));
894  }
895  }
896  }
897 
898  /*---------------------------------------.
899  | conjunction(polynomial, polynomial). |
900  `---------------------------------------*/
901 
902  namespace dyn
903  {
904  namespace detail
905  {
907  template <typename PolynomialSetLhs, typename PolynomialSetRhs>
908  polynomial
910  {
911  auto join_elts = join<PolynomialSetLhs, PolynomialSetRhs>(lhs, rhs);
912  return make_polynomial(std::get<0>(join_elts),
913  ::vcsn::conjunction(std::get<0>(join_elts),
914  std::get<1>(join_elts),
915  std::get<2>(join_elts)));
916  }
917  }
918  }
919 }
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: conjunction.hh:66
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:383
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
Definition: automaton.hh:137
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:53
product_automaton_impl self_t
Definition: conjunction.hh:42
context_t_of< Aut > context_t
The context of the result.
Definition: conjunction.hh:73
constexpr std::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:333
tuple_automaton< automaton_t, Auts... > tuple_automaton_t
Definition: conjunction.hh:41
A dyn automaton.
Definition: automaton.hh:19
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
std::shared_ptr< const detail::polynomial_base > polynomial
Definition: fwd.hh:53
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
Definition: traits.hh:74
auto all_in(Args &&...args) const -> decltype(aut_-> all_in(std::forward< Args >(args)...))
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:296
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
Definition: copy.hh:90
void conjunction()
Compute the (accessible part of the) conjunction.
Definition: conjunction.hh:97
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:57
polynomial conjunction_polynomial(const polynomial &lhs, const polynomial &rhs)
Bridge (conjunction).
Definition: conjunction.hh:909
constexpr bool all_()
Definition: tuple.hh:404
std::tuple< typename transition_map_t< Auts >::map_t &... > out_(const state_name_t &ss)
The outgoing tuple of transitions from state tuple ss.
expression infiltration_expression(const expression &lhs, const expression &rhs)
Bridge (infiltration).
Definition: conjunction.hh:790
typename tuple_automaton_t::element_type::state_t state_t
zipped_maps< Dereference, Maps... > zip_map_tuple(const std::tuple< Maps... > &maps)
Definition: zip-maps.hh:257
expression make_expression(const ExpSet &rs, const typename ExpSet::value_t &r)
Definition: expression.hh:97
auto join_automata(Auts &&...auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
An automaton whose type is the join between those of auts.
std::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:268
typename super_t::state_name_t state_name_t
Definition: conjunction.hh:46
static symbol sname_(const T &...t)
std::enable_if_t< sizeof...(Auts)==2 &&!L > ldiv_here()
Compute the left quotient in-place.
Definition: conjunction.hh:114
automaton_t aut_
The wrapped automaton, possibly const.
detail::automaton automaton
Definition: automaton.hh:108
typename super_t::template transition_map_t< A > transition_map_t
Definition: conjunction.hh:50
std::shared_ptr< detail::product_automaton_impl< Lazy, Aut, Auts... >> product_automaton
A product automaton as a shared pointer.
Definition: conjunction.hh:462
std::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:355
auto copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans) -> decltype(keep_state(input->null_state()), keep_trans(input->null_transition()), make_fresh_automaton< AutIn, AutOut >(input))
A copy of input keeping only its states that are accepted by keep_state, and transitions accepted by ...
Definition: copy.hh:308
automaton shuffle_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:664
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:43
automaton infiltration_(const std::vector< automaton > &as, vcsn::detail::index_sequence< I... >)
Variadic bridge helper.
Definition: conjunction.hh:749
void infiltration()
Compute the (accessible part of the) infiltration product.
Definition: conjunction.hh:156
std::tuple< Auts... > automata_t
The type of input automata.
Definition: conjunction.hh:81
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:254
const weightset_t & ws_
The resulting weightset.
typename tuple_automaton_t::element_type::template seq< I... > seq
Definition: conjunction.hh:54
auto shuffle(const Auts &...as) -> tuple_automaton< decltype(join_automata(as...)), Auts... >
The (accessible part of the) shuffle product.
Definition: conjunction.hh:648
auto rs
Definition: lift.hh:151
void add_transitions(const state_t src, const state_name_t &psrc)
Tell lazy_tuple_automaton how to add the transitions to a state.
Definition: conjunction.hh:199
#define Automaton
Definition: automaton.hh:24
auto make_product_automaton(Aut aut, const Auts &...auts) -> product_automaton< Lazy, Aut, Auts... >
Definition: conjunction.hh:467
auto conjunction(const Auts &...as) -> tuple_automaton< decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction.
Definition: conjunction.hh:482
auto labelset(Args &&...args) const -> decltype(aut_-> labelset(std::forward< Args >(args)...))
std::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:275
typename tuple_automaton_t::element_type::state_name_t state_name_t
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:724
typename weightset_t::value_t weight_t
Definition: conjunction.hh:78
auto new_transition(Args &&...args) -> decltype(aut_-> new_transition(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:310
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:78
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:366
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
Definition: tuple.hh:235
std::enable_if_t< L, void > complete_(state_t s) const
Complete a state: find its outgoing transitions.
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:229
void initialize_shuffle()
Fill the worklist with the initial source-state pairs, as needed for the shuffle algorithm.
Definition: conjunction.hh:215
automaton conjunction_repeated(const automaton &aut, unsigned n)
Bridge (conjunction).
Definition: conjunction.hh:854
autodecltype(insplit(aut)) std::enable_if_t<!labelset_t_of< Aut >::has_one()||I==0, Aut & > do_insplit(Aut &aut)
Definition: conjunction.hh:520
std::remove_cv_t< std::remove_reference_t< T >> base_t
T without reference or const/volatile qualifiers.
Definition: traits.hh:12
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
Definition: polynomial.hh:103
auto meet_automata(Auts &&...auts) -> decltype(make_mutable_automaton(meet(auts->context()...)))
An automaton whose type is the meet between those of auts.
labelset_t_of< context_t > labelset_t
Definition: conjunction.hh:74
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:396
weightset_t_of< context_t > weightset_t
Definition: conjunction.hh:75
product_automaton_impl(Aut aut, const Auts &...auts)
Build a product automaton.
Definition: conjunction.hh:92
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:59
auto rdiv(const Aut1 &a1, const Aut2 &a2)
Compute the right quotient.
Definition: conjunction.hh:616
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
typename labelset_t::value_t label_t
Definition: conjunction.hh:77
typename super_t::state_t state_t
Definition: conjunction.hh:47
Decorator implementing the laziness for an algorithm.
auto conjunction_lazy(const Auts &...as) -> product_automaton< true, decltype(meet_automata(as...)), Auts... >
Build the (accessible part of the) conjunction, on-the-fly.
Definition: conjunction.hh:495
std::tuple< transition_map_t< Auts >... > transition_maps_
Transition caches.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:113
Build the (accessible part of the) product.
Definition: conjunction.hh:33
auto insplit(Aut &aut) -> std::enable_if_t< labelset_t_of< Aut >::has_one(), decltype(make_insplit_automaton(aut))>
Definition: insplit.hh:291
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:56
std::shared_ptr< const node< Context >> expression
Definition: fwd.hh:182
std::shared_ptr< detail::tuple_automaton_impl< Auts... >> tuple_automaton
A tuple automaton as a shared pointer.
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:39
std::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:324
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:55
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
void shuffle()
Compute the (accessible part of the) shuffle product.
Definition: conjunction.hh:143
state_t state(Args &&...args)
Conversion from state name to state number.
std::shared_ptr< detail::expression_base > expression
Definition: expression.hh:92
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:423
constexpr std::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:343
automaton conjunction_(const std::vector< automaton > &as, bool lazy, vcsn::detail::index_sequence< I... >)
Bridge helper.
Definition: conjunction.hh:528
Aut transpose(const transpose_automaton< Aut > &aut)
Definition: transpose.hh:227
An input/output format for valuesets.
Definition: format.hh:11
void initialize_conjunction()
Fill the worklist with the initial source-state pairs, as needed for the conjunction algorithm...
Definition: conjunction.hh:208
Aut automaton_t
The type of the resulting automaton.
Definition: conjunction.hh:40
base_t< tuple_element_t< I, automata_t >> input_automaton_t
The type of the Ith input automaton, unqualified.
Definition: conjunction.hh:85
expression shuffle_expression(const expression &lhs, const expression &rhs)
Bridge (shuffle).
Definition: conjunction.hh:705
Definition: a-star.hh:8
expression conjunction_expression(const expression &lhs, const expression &rhs)
Bridge (conjunction).
Definition: conjunction.hh:887