Vcsn  2.8
Be Rational
to-expression.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vcsn/algos/copy.hh>
4 #include <vcsn/algos/lift.hh>
5 #include <vcsn/core/automaton.hh> // all_in
7 #include <vcsn/core/rat/info.hh>
8 #include <vcsn/core/rat/size.hh>
9 #include <vcsn/dyn/value.hh>
10 #include <vcsn/misc/builtins.hh>
11 #include <vcsn/misc/getargs.hh>
12 #include <vcsn/misc/vector.hh>
14 
15 namespace vcsn
16 {
17  namespace detail
18  {
19  /*----------------.
20  | Naive profiler. |
21  `----------------*/
22 
25  template <Automaton Aut>
27  {
28  using automaton_t = Aut;
31 
33  : aut_(aut)
34  {}
35 
40  {
42  : state_(state)
43  {}
44 
45  bool operator<(const state_profile& rhs) const
46  {
47  return std::make_tuple(size_, has_loop_, state_)
48  < std::make_tuple(rhs.size_, rhs.has_loop_, rhs.state_);
49  }
50 
51  friend std::ostream& operator<<(std::ostream& o, const state_profile& p)
52  {
53  return o << p.state_
54  << 's' << p.size_
55  << 'l' << p.has_loop_;
56  }
57 
60  size_t size_ = 0;
61  bool has_loop_ = false;
63  };
64 
67  {
68  auto p = state_profile{state};
69  update(p);
70  return p;
71  }
72 
74  {}
75 
77  {
78  size_t out = 0;
79  for (auto t: all_out(aut_, p.state_))
80  if (aut_->dst_of(t) == p.state_)
81  p.has_loop_ = true;
82  else
83  ++out;
84  size_t in = all_in(aut_, p.state_).size();
85  p.size_ = in * out;
86  }
87 
89  };
90 
91  /*-------------------.
92  | Delgado profiler. |
93  `-------------------*/
94 
97  template <Automaton Aut>
99  {
100  using automaton_t = Aut;
103 
109  delgado_profiler(const automaton_t& aut, bool count_labels = false)
110  : aut_{aut}
111  , count_labels_{count_labels}
112  , transition_cache_(transitions_size(aut_), 0)
113  {}
114 
116  {
118  : state_(state)
119  {}
120 
121  bool operator<(const state_profile& rhs) const
122  {
123  return std::make_tuple(size_, state_)
124  < std::make_tuple(rhs.size_, rhs.state_);
125  }
126 
127  friend std::ostream& operator<<(std::ostream& o, const state_profile& p)
128  {
129  return o << p.state_
130  << 's' << p.size_;
131  }
132 
133  size_t size_ = 0;
135  };
136 
139  {
140  auto p = state_profile{state};
141  update(p);
142  return p;
143  }
144 
149  {
150  auto& res = transition_cache_[t];
151  if (res == 0)
152  {
153  using expset_t = weightset_t_of<automaton_t>;
154  if (count_labels_)
155  res = rat::make_info<expset_t>(aut_->weight_of(t)).atom;
156  else
157  res = rat::size<expset_t>(aut_->weight_of(t));
158  }
159  return res;
160  }
161 
167  {
168  if (transition_cache_.size() <= t)
169  transition_cache_.resize(t + 1, 0);
170  transition_cache_[t] = 0;
171  }
172 
178  {
179  // The cumulated size of the incoming transitions excluding loops.
180  size_t size_in = 0;
181  // The number of incoming transitions excluding loops.
182  size_t ins = 0;
183  // The size of the loop, if there is one.
184  size_t size_loop = 0;
185  for (auto t: all_in(aut_, p.state_))
186  if (aut_->src_of(t) == p.state_)
187  size_loop += size_of_transition(t);
188  else
189  {
190  ++ins;
191  size_in += size_of_transition(t);
192  }
193 
194  // The cumulated size of the outgoing transitions excluding loops.
195  size_t size_out = 0;
196  // The number of outgoing transitions excluding loops.
197  size_t outs = 0;
198  for (auto t: all_out(aut_, p.state_))
199  if (aut_->dst_of(t) != p.state_)
200  {
201  ++outs;
202  size_out += size_of_transition(t);
203  }
204 
205  p.size_ = (size_in * (outs - 1)
206  + size_out * (ins - 1)
207  + size_loop * (ins * outs - 1));
208  }
209 
212  std::vector<size_t> transition_cache_;
213  };
214  }
215 
216  /*------------------.
217  | eliminate_state. |
218  `------------------*/
219 
220  namespace detail
221  {
225  template <Automaton Aut, typename Profiler>
227  {
228  using profiler_t = Profiler;
229  using profile_t = typename profiler_t::state_profile;
230  using automaton_t = std::remove_cv_t<Aut>;
232 
238  : aut_(aut)
239  , profiler_(profiler)
240  , handles_(states_size(aut_))
241  {
242  for (auto s: aut_->states())
243  handles_[s] = todo_.emplace(profiler_.make_state_profile(s));
244  }
245 
248  {
249  if (s == aut_->null_state())
250  {
251  require(!todo_.empty(), "no state left to remove");
252  auto p = todo_.top();
253  todo_.pop();
254  s = p.state_;
255  }
256  else
257  require(aut_->has_state(s), "not a valid state: ", s);
258  eliminate_state_(s);
259  }
260 
262  void operator()()
263  {
264  while (!todo_.empty())
265  {
266  auto p = todo_.top();
267  todo_.pop();
268 
269 #ifdef DEBUG_LOOP
270  std::cerr << "Remove: " << p << '\n';
271 #endif
272  eliminate_state_(p.state_);
273  }
274  }
275 
276  private:
278  {
279 #ifdef DEBUG_UPDATE
280  std::cerr << "update heap: (";
281  show_heap_();
282 #endif
283  for (auto s: neighbors_)
284  if (s != aut_->pre() && s != aut_->post())
285  {
286  auto& h = handles_[s];
287  profiler_.update(*h);
288  todo_.update(h);
289  }
290 #ifdef DEBUG_UPDATE
291  std::cerr << ") => ";
292  show_heap_();
293  std::cerr << '\n';
294 #endif
295  }
296 
298  void show_heap_() const
299  {
300  const char* sep = "";
301  for (auto i = todo_.ordered_begin(), end = todo_.ordered_end();
302  i != end; ++i)
303  {
304  std::cerr << sep << *i;
305  sep = " > ";
306  }
307  }
308 
310  template <typename Kind = typename context_t_of<automaton_t>::kind_t>
312  -> std::enable_if_t<std::is_same<Kind, labels_are_one>::value,
313  void>
314  {
315  neighbors_.clear();
316 
317  // Shorthand to the labelset.
318  const auto& ls = *aut_->labelset();
319 
320  // Shorthand to the weightset.
321  const auto& ws = *aut_->weightset();
322 
323  // The loop's weight.
324  auto loop = ws.zero();
325  assert(outin(aut_, s, s).size() <= 1);
326  // There is a single possible loop labeled by \e, but it's
327  // easier and symmetrical with LAR to use a for-loop.
328  for (auto t: make_vector(outin(aut_, s, s)))
329  {
330  loop = ws.add(loop, aut_->weight_of(t));
331  aut_->del_transition(t);
332  }
333  loop = ws.star(loop);
334 
335  // Get all the predecessors, and successors, except itself.
336  auto outs = all_out(aut_, s);
337  for (auto in: all_in(aut_, s))
338  for (auto out: outs)
339  {
340  auto src = aut_->src_of(in);
341  auto dst = aut_->dst_of(out);
342  auto t = aut_->add_transition
343  (src, dst,
344  // Of course, most of the time \e\e => \e. But there
345  // is also $ to take into account when eliminating an
346  // initial/final state.
347  ls.mul(aut_->label_of(in), aut_->label_of(out)),
348  ws.mul(aut_->weight_of(in), loop, aut_->weight_of(out)));
349  profiler_.invalidate_cache(t);
350  neighbors_.emplace(src);
351  neighbors_.emplace(dst);
352  }
353 
354  aut_->del_state(s);
355  update_heap_();
356  }
357 
359  //
360  // FIXME: expressionset<lal_char(a-c), z>, q for instance cannot
361  // work, because we need to move the q weights inside the
362  // lal_char(a-c), z expressions, which is obviously not possible.
363  // So we need to require that there is a subtype relationship
364  // between the weightset and the weightset of the expression.
365  //
366  // Yet as of 2014-07, there is no means to check that subtype
367  // relationship in Vcsn.
368  template <typename Kind>
370  -> std::enable_if_t<std::is_same<Kind, labels_are_expressions>::value,
371  void>
372  {
373  neighbors_.clear();
374 
375  // Shorthand to the labelset, which is an expressionset.
376  const auto& rs = *aut_->labelset();
377 
378  // The loops' expression.
379  auto loop = rs.zero();
380  for (auto t: make_vector(outin(aut_, s, s)))
381  {
382  loop = rs.add(loop,
383  rs.lweight(aut_->weight_of(t), aut_->label_of(t)));
384  aut_->del_transition(t);
385  }
386  loop = rs.star(loop);
387 
388  // Get all the predecessors, and successors, except itself.
389  auto outs = all_out(aut_, s);
390  for (auto in: all_in(aut_, s))
391  for (auto out: outs)
392  {
393  auto src = aut_->src_of(in);
394  auto dst = aut_->dst_of(out);
395  auto t = aut_->add_transition
396  (src, dst,
397  rs.mul(rs.lweight(aut_->weight_of(in), aut_->label_of(in)),
398  loop,
399  rs.lweight(aut_->weight_of(out), aut_->label_of(out))));
400  profiler_.invalidate_cache(t);
401  neighbors_.emplace(src);
402  neighbors_.emplace(dst);
403  }
404 
405  aut_->del_state(s);
406  update_heap_();
407  }
408 
413 
418  std::vector<typename heap_t::handle_type> handles_;
419 
420  std::unordered_set<state_t> neighbors_;
421  };
422 
423  template <Automaton Aut, typename Profiler>
425  make_state_eliminator(Aut& a, Profiler& profiler)
426  {
427  return {a, profiler};
428  }
429  }
430 
431 
433  template <Automaton Aut>
434  Aut&
436  state_t_of<Aut> s = Aut::element_type::null_state())
437  {
438  // Delgado profiler not fit for lao with non expression weightset.
439  auto profiler = detail::naive_profiler<Aut>(res);
440  auto eliminate_state = detail::make_state_eliminator(res, profiler);
441  eliminate_state(s);
442  return res;
443  }
444 
446  template <Automaton Aut>
447  auto
448  eliminate_state(const Aut& aut,
449  state_t_of<Aut> s = Aut::element_type::null_state())
451  {
452  // Get a copy, but be sure to keep the correspondance bw original
453  // state numbers and the new ones.
454  auto res = make_fresh_automaton<Aut>(aut);
455  auto copy = make_copier(aut, res);
456  copy();
457  if (s != aut->null_state())
458  {
459  require(aut->has_state(s), "not a valid state: ", s);
460  s = copy.state_map().at(s);
461  }
462  return eliminate_state_here(res, s);
463  }
464 
465 
466  /*-----------------------.
467  | dyn::eliminate_state. |
468  `-----------------------*/
469 
470  namespace dyn
471  {
472  namespace detail
473  {
475  template <Automaton Aut, typename Int>
476  automaton
477  eliminate_state(const automaton& aut, int state)
478  {
479  const auto& a = aut->as<Aut>();
480  using state_t = state_t_of<Aut>;
481  auto s = 0 <= state ? state_t(state + 2) : a->null_state();
482  return vcsn::eliminate_state(a, s);
483  }
484  }
485  }
486 
487 
488  /*----------------------------.
489  | to_expression(automaton). |
490  `----------------------------*/
491 
492  template <Automaton Aut,
493  typename Profiler,
494  typename ExpSet = expressionset<context_t_of<Aut>>>
495  typename ExpSet::value_t
496  to_expression(Aut& a, Profiler& profiler)
497  {
498  try
499  {
500  auto eliminate_states = detail::make_state_eliminator(a, profiler);
501  eliminate_states();
502  return a->get_initial_weight(a->post());
503  }
504  catch (const std::runtime_error& e)
505  {
506  raise(e, " while making expression");
507  }
508  }
509 
511  {
512  best,
513  delgado,
515  naive,
516  };
517 
518  template <Automaton Aut,
519  typename ExpSet = expressionset<context_t_of<Aut>>>
520  typename ExpSet::value_t
523  {
524  // State elimination is performed on the lifted automaton.
525  auto a = lift(aut, ids);
526  using delgado_t = detail::delgado_profiler<decltype(a)>;
527  using naive_t = detail::naive_profiler<decltype(a)>;
528  switch (algo)
529  {
531  raise("next_state: invalid algorithm: best");
532 
534  {
535  auto profiler = delgado_t(a);
536  return to_expression<decltype(a), delgado_t, ExpSet>(a, profiler);
537  }
538 
540  {
541  auto profiler = delgado_t(a, true);
542  return to_expression<decltype(a), delgado_t, ExpSet>(a, profiler);
543  }
544 
546  {
547  auto profiler = naive_t(a);
548  return to_expression<decltype(a), naive_t, ExpSet>(a, profiler);
549  }
550  }
552  }
553 
554  template <Automaton Aut,
555  typename ExpSet = expressionset<context_t_of<Aut>>>
556  typename ExpSet::value_t
557  to_expression(const Aut& aut, vcsn::rat::identities ids,
559  {
561  {
562  typename ExpSet::value_t best;
563  auto best_size = std::numeric_limits<size_t>::max();
567  {
568  auto r = to_expression_heuristic<Aut, ExpSet>(aut, ids, a);
569  auto s = rat::size<ExpSet>(r);
570  if (s < best_size)
571  {
572  best = r;
573  best_size = s;
574  }
575  }
576  return best;
577  }
578  else
579  {
580  return to_expression_heuristic<Aut, ExpSet>(aut, ids, algo);
581  }
582  }
583 
584  template <Automaton Aut,
585  typename ExpSet = expressionset<context_t_of<Aut>>>
586  typename ExpSet::value_t
587  to_expression(const Aut& a, vcsn::rat::identities ids,
588  const std::string& algo)
589  {
590  static const auto map = getarg<to_expression_heuristic_t>
591  {
592  "heuristics",
593  {
594  {"auto", "best"},
597  {"delgado_label", to_expression_heuristic_t::delgado_label},
599  }
600  };
601  return to_expression<Aut, ExpSet>(a, ids, map[algo]);
602  }
603 
604  /*----------------------------.
605  | to_expression(automaton). |
606  `----------------------------*/
607 
608  namespace dyn
609  {
610  namespace detail
611  {
613  template <Automaton Aut, typename Identities, typename String>
614  expression
615  to_expression(const automaton& aut, identities ids,
616  const std::string& algo)
617  {
618  const auto& a = aut->as<Aut>();
619  using context_t = context_t_of<Aut>;
620  using expressionset_t = vcsn::expressionset<context_t>;
621  auto rs = expressionset_t{a->context(), ids};
622  auto res = ::vcsn::to_expression(a, ids, algo);
623  return {rs, res};
624  }
625  }
626  }
627 
628  /*------------------------.
629  | to_expression(label). |
630  `------------------------*/
631 
632  namespace dyn
633  {
634  namespace detail
635  {
637  template <typename Context, typename Identities, typename Label>
638  expression
640  const label& lbl)
641  {
642  const auto& c = ctx->as<Context>();
643  const auto& l = lbl->as<Label>();
644  auto rs = vcsn::make_expressionset(c, ids);
645  return {rs, rs.atom(l.value())};
646  }
647  }
648  }
649 
650 
651  /*-------------------------------.
652  | to_expression(letter_class). |
653  `-------------------------------*/
654 
655  namespace detail
656  {
658  template <typename ExpSet>
659  auto letter_class_impl(const ExpSet&,
660  const letter_class_t&, bool,
661  std::false_type, std::true_type)
662  -> typename ExpSet::value_t
663  {
664  raise("letter_class: not implemented (is_expressionset)");
665  }
666 
668  template <typename ExpSet>
669  auto letter_class_impl(const ExpSet& rs,
670  const letter_class_t&, bool,
671  std::true_type, std::false_type)
672  -> typename ExpSet::value_t
673  {
674  return rs.one();
675  }
676 
678  template <typename ExpSet>
679  auto letter_class_impl(const ExpSet& rs,
680  const letter_class_t& chars, bool accept,
681  std::false_type, std::false_type)
682  -> typename ExpSet::value_t
683  {
684  auto ls = *rs.labelset();
685 
686  using labelset_t = decltype(ls);
687  using letter_t = typename labelset_t::letter_t;
688 
689  auto ccs = std::set<std::pair<letter_t, letter_t>>{};
690  for (const auto& cc: chars)
691  {
692  std::istringstream i1{cc.first};
693  std::istringstream i2{cc.second};
694  letter_t l1 = ls.get_letter(i1, false);
695  letter_t l2 = ls.get_letter(i2, false);
696  ccs.emplace(l1, l2);
697  }
698  return rs.letter_class(ccs, accept);
699  }
700  }
701 
711  template <typename ExpressionSet>
712  typename ExpressionSet::value_t
713  to_expression(const ExpressionSet& rs, const letter_class_t& letters,
714  bool accept = true)
715  {
716  using labelset_t = labelset_t_of<ExpressionSet>;
717  using is_one_t = std::is_same<labelset_t, vcsn::oneset>;
719  return detail::letter_class_impl(rs, letters, accept,
720  is_one_t{}, is_expset_t{});
721  }
722 
723  namespace dyn
724  {
725  namespace detail
726  {
728  template <typename Context, typename Identities,
729  typename Letters, typename Bool>
730  expression
732  const letter_class_t& letters, bool accept)
733  {
734  const auto& c = ctx->as<Context>();
735  auto rs = vcsn::make_expressionset(c, ids);
736  return {rs, to_expression(rs, letters, accept)};
737  }
738  }
739  }
740 } // vcsn::
std::unordered_set< state_t > neighbors_
std::vector< typename heap_t::handle_type > handles_
Map: state -> heap-handle.
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
std::shared_ptr< const node< Context > > expression
Definition: fwd.hh:195
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
auto eliminate_state_impl_(state_t s) -> std::enable_if_t< std::is_same< Kind, labels_are_expressions >::value, void >
Eliminate state s in the case of labels are expressions.
std::vector< size_t > transition_cache_
void operator()(state_t s)
Eliminate state s.
friend std::ostream & operator<<(std::ostream &o, const state_profile &p)
std::remove_cv_t< Aut > automaton_t
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Definition: traits.hh:65
profiler_t & profiler_
The profiler we work with. Corresponding to a specific heuristic.
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:41
void invalidate_cache(transition_t t)
Updating transitions&#39; size in the cache during the profiler&#39;s construction would be clearer but appea...
state_profile make_state_profile(state_t state)
auto eliminate_state_(state_t s) -> std::enable_if_t< std::is_same< Kind, labels_are_one >::value, void >
Eliminate state s in the case of labels are one.
std::vector< typename Cont::value_type > make_vector(const Cont &cont)
The content of cont as a vector.
Definition: vector.hh:18
state_t_of< automaton_t > state_t
void update(state_profile &p)
The "weight" of a state, as defined by Delgado-Morais.
naive_profiler(const automaton_t &aut)
void operator()()
Eliminate all the states, in the order specified by next_state.
state_t_of< automaton_t > state_t
size_t size_of_transition(transition_t t)
The "weight" of a transition.
typename profiler_t::state_profile profile_t
friend std::ostream & operator<<(std::ostream &o, const state_profile &p)
auto all_in(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions entering state s.
Definition: automaton.hh:116
transition_t_of< automaton_t > transition_t
state_eliminator< Aut, Profiler > make_state_eliminator(Aut &a, Profiler &profiler)
bool operator<(const state_profile &rhs) const
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:67
An expressionset can implement several different sets of identities on expressions.
Definition: identities.hh:20
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
transition_t_of< automaton_t > transition_t
auto letter_class_impl(const ExpSet &, const letter_class_t &, bool, std::false_type, std::true_type) -> typename ExpSet::value_t
Case where labelset is an expressionset.
detail::lifted_automaton_t< Aut, Tapes... > lift(const Aut &a, vcsn::rat::identities ids={})
Lift some tapes of the transducer.
Definition: lift.hh:215
Aut & eliminate_state_here(Aut &res, state_t_of< Aut > s=Aut::element_type::null_state())
In place removal of state s from automaton res.
std::integral_constant< bool, B > bool_constant
Definition: type_traits.hh:12
Eliminate states in an automaton.
auto outin(const Aut &aut, state_t_of< Aut > s, state_t_of< Aut > d)
Indexes of visible transitions from state s to state d.
Definition: automaton.hh:189
The state profile is the product of the number of (strictly) incoming transitions with the number of ...
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:322
expression to_expression_class(const context &ctx, identities ids, const letter_class_t &letters, bool accept)
Bridge (to_expression).
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
void update(state_profile &p)
Definition: a-star.hh:8
auto in(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions arriving to state s.
Definition: automaton.hh:135
delgado_profiler(const automaton_t &aut, bool count_labels=false)
Build a generator of Delgado-Morais state profiles.
automaton_t aut_
The automaton we work on.
expression to_expression_label(const context &ctx, identities ids, const label &lbl)
Bridge (to_expression).
std::set< std::pair< std::string, std::string > > letter_class_t
A set of letter ranges.
Definition: fwd.hh:111
detail::copier< AutIn, AutOut > make_copier(const AutIn &in, AutOut &out, bool safe=true)
Build an automaton copier.
Definition: copy.hh:256
state_t_of< automaton_t > state_t
ExpSet::value_t to_expression(Aut &a, Profiler &profiler)
Definition: to-automaton.hh:65
auto make_expressionset(const context< LabelSet, WeightSet > &ctx, rat::identities ids={}) -> expressionset< context< LabelSet, WeightSet >>
Shorthand to expressionset constructor.
vcsn::min_fibonacci_heap< profile_t > heap_t
Max-heap to decide the order of state-elimination.
auto eliminate_state(const Aut &aut, state_t_of< Aut > s=Aut::element_type::null_state()) -> fresh_automaton_t_of< Aut >
A copy of automaton res without the state s.
Definition: to-automaton.hh:17
void show_heap_() const
Show the heap, for debugging.
size_t size_
Number of strictly incoming transitions, times the number of strictly outgoing transitions.
boost::heap::fibonacci_heap< Elt, detail::comparator_t< Elt > > min_fibonacci_heap
value_impl< detail::label_tag > label
Definition: fwd.hh:32
bool operator<(const state_profile &rhs) const
to_expression_heuristic_t
Definition: to-automaton.hh:79
A mapping from strings to Values.
Definition: getargs.hh:33
Compute a state profile for state-elimination based on connectivity.
void invalidate_cache(transition_t)
state_eliminator(automaton_t &aut, profiler_t &profiler)
Prepare for state-elimination.
size_t transitions_size(const Aut &aut)
The largest transition number, plus one.
Definition: automaton.hh:51
static identities ids(const driver &d)
Get the identities of the driver.
Definition: parse.cc:91
::vcsn::rat::identities identities
Sets of identities on expressions.
Definition: fwd.hh:17
state_profile make_state_profile(state_t state)
#define Automaton
Definition: automaton.hh:23
ExpSet::value_t to_expression_heuristic(const Aut &aut, vcsn::rat::identities ids, to_expression_heuristic_t algo)
Definition: to-automaton.hh:90
void require(Bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:87
Compute a state profile for state-elimination based on the Delgado-Morais heuristic.
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:82
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13
auto map(const std::tuple< Ts... > &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
Definition: tuple.hh:223
return res
Definition: multiply.hh:399
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:86