Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
to-expression.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_TO_EXPRESSION_HH
2 # define VCSN_ALGOS_TO_EXPRESSION_HH
3 
4 # include <vcsn/algos/copy.hh>
5 # include <vcsn/algos/lift.hh>
6 # include <vcsn/core/rat/ratexp.hh>
7 # include <vcsn/misc/vector.hh>
8 
9 namespace vcsn
10 {
11 
12  /*----------------.
13  | state_chooser. |
14  `----------------*/
15 
17  template <typename Aut,
18  typename Lifted = detail::lifted_automaton_t<Aut>>
19  using state_chooser_t =
20  std::function<state_t_of<Lifted>(const Lifted&)>;
21 
22 
23  /*--------------------------.
24  | Naive heuristics degree. |
25  `--------------------------*/
26 
27  template <typename Aut>
29  next_naive(const Aut& a)
30  {
31  state_t_of<Aut> best = 0;
32  bool best_has_loop = false;
33  size_t best_degree = std::numeric_limits<size_t>::max();
34  for (auto s: a->states())
35  {
36  size_t out = 0;
37  // Since we are in LAO, there can be at most one such loop.
38  bool has_loop = false;
39  // Don't count the loops as out-degree.
40  for (auto t: a->all_out(s))
41  if (a->dst_of(t) != s)
42  ++out;
43  else
44  has_loop = true;
45  size_t in = a->all_in(s).size();
46  size_t degree = in * out;
47  // We prefer to delete a state that has no loop transition.
48  if (degree < best_degree
49  || (degree == best_degree && has_loop < best_has_loop))
50  {
51  best = s;
52  best_degree = degree;
53  best_has_loop = has_loop;
54  }
55  }
56  assert(best);
57  return best;
58  }
59 
60  /*------------------.
61  | eliminate_state. |
62  `------------------*/
63 
64  namespace detail
65  {
66  template <typename Aut, typename Kind = typename context_t_of<Aut>::kind_t>
68 
70  template <typename Aut>
72  {
73  using automaton_t = typename std::remove_cv<Aut>::type;
77  using state_chooser_t = std::function<state_t(const automaton_t&)>;
78 
80  : debug_(0)
81  , aut_(aut)
82  {}
83 
86  {
87  require(aut_->has_state(s), "not a valid state: ", s);
88 
89  // The loop's weight.
90  auto loop = ws_.zero();
91  assert(aut_->outin(s, s).size() <= 1);
92  // There is a single possible loop labeled by \e, but it's
93  // easier and symmetrical with LAR to use a for-loop.
94  for (auto t: to_vector(aut_->outin(s, s)))
95  {
96  loop = ws_.add(loop, aut_->weight_of(t));
97  aut_->del_transition(t);
98  }
99  loop = ws_.star(loop);
100 
101  // Get all the predecessors, and successors, except itself.
102  auto outs = aut_->all_out(s);
103  for (auto in: aut_->all_in(s))
104  for (auto out: outs)
105  aut_->add_transition
106  (aut_->src_of(in), aut_->dst_of(out),
107  aut_->label_of(in),
108  ws_.mul(aut_->weight_of(in), loop, aut_->weight_of(out)));
109  aut_->del_state(s);
110  }
111 
113  void operator()(const state_chooser_t& next_state)
114  {
115  while (aut_->num_states())
116  operator()(next_state(aut_));
117  }
118 
119  private:
121  int debug_;
125  const weightset_t& ws_ = *aut_->weightset();
126  };
127 
128 
130  template <typename Aut>
132  {
133  // FIXME: ratexpset<lal_char(a-c), z>_q for instance cannot work,
134  // because we need to move the q weights inside the
135  // lal_char(a-c), z ratexps, which obviously not possible. So we
136  // need to require that there is a subtype relationship between
137  // the weightset and the weightset of the ratexp.
138  //
139  // Yet as of 2014-07, there is no means to check that subtype
140  // relationship in Vaucanson.
141 
142  using automaton_t = typename std::remove_cv<Aut>::type;
147  using state_chooser_t = std::function<state_t(const automaton_t&)>;
148 
150  : debug_(0)
151  , aut_(aut)
152  {}
153 
156  {
157  require(aut_->has_state(s), "not a valid state: ", s);
158 
159  // The loops' ratexp.
160  auto loop = rs_.zero();
161  for (auto t: to_vector(aut_->outin(s, s)))
162  {
163  loop = rs_.add(loop,
164  rs_.lmul(aut_->weight_of(t), aut_->label_of(t)));
165  aut_->del_transition(t);
166  }
167  loop = rs_.star(loop);
168 
169  // Get all the predecessors, and successors, except itself.
170  auto outs = aut_->all_out(s);
171  for (auto in: aut_->all_in(s))
172  for (auto out: outs)
173  aut_->add_transition
174  (aut_->src_of(in), aut_->dst_of(out),
175  rs_.mul(rs_.lmul(aut_->weight_of(in), aut_->label_of(in)),
176  loop,
177  rs_.lmul(aut_->weight_of(out), aut_->label_of(out))));
178  aut_->del_state(s);
179  }
180 
182  void operator()(const state_chooser_t& next_state)
183  {
184  while (aut_->num_states())
185  operator()(next_state(aut_));
186  }
187 
188  private:
190  int debug_;
194  const ratexpset_t& rs_ = *aut_->labelset();
196  const weightset_t& ws_ = *aut_->weightset();
197  };
198 
199  template <typename Aut>
202  {
203  return a;
204  }
205  }
206 
207 
209  template <typename Aut>
210  Aut&
212  {
213  if (s == res->null_state())
214  s = next_naive(res);
216  eliminate_state(s);
217  return res;
218  }
219 
221  template <typename Aut>
222  Aut
223  eliminate_state(const Aut& aut, state_t_of<Aut> s)
224  {
225  // FIXME: this is soooo wrong: we eliminate a state in a copy,
226  // whose state numbers might be completely different. We _need_
227  // the state names.
228  auto res = vcsn::copy(aut);
229  return eliminate_state_here(res, s);
230  }
231 
232 
233  /*-----------------------.
234  | dyn::eliminate_state. |
235  `-----------------------*/
236 
237  namespace dyn
238  {
239  namespace detail
240  {
242  template <typename Aut, typename Int>
243  automaton
244  eliminate_state(const automaton& aut, int state)
245  {
246  const auto& a = aut->as<Aut>();
247  auto s = a->null_state();
248  // FIXME: weak.
249  if (state != -1)
250  s = state + 2;
252  }
253 
255  (const automaton& aut, int) -> automaton);
256  }
257  }
258 
259 
260  /*-----------------.
261  | to_expression. |
262  `-----------------*/
263 
264  template <typename Aut,
265  typename RatExpSet = ratexpset<context_t_of<Aut>>>
266  typename RatExpSet::value_t
267  to_expression(const Aut& a,
268  const state_chooser_t<Aut>& next_state)
269  {
270  // State elimination is performed on the lifted automaton.
271  auto aut = lift(a);
272  auto eliminate_states = detail::make_state_eliminator(aut);
273  eliminate_states(next_state);
274  return aut->get_initial_weight(aut->post());
275  }
276 
277 
278  template <typename Aut,
279  typename RatExpSet = ratexpset<context_t_of<Aut>>>
280  typename RatExpSet::value_t
281  to_expression_naive(const Aut& a)
282  {
283  state_chooser_t<Aut> next = next_naive<detail::lifted_automaton_t<Aut>>;
284  return to_expression(a, next);
285  }
286 
287  /*----------------------.
288  | dyn::to_expression. |
289  `----------------------*/
290 
291  namespace dyn
292  {
293  namespace detail
294  {
296  template <typename Aut, typename String>
297  ratexp
298  to_expression(const automaton& aut, const std::string& algo)
299  {
300  const auto& a = aut->as<Aut>();
301  // FIXME: So far, there is a single implementation of ratexps,
302  // but we should actually be parameterized by its type too.
303  using context_t = context_t_of<Aut>;
304  using ratexpset_t = vcsn::ratexpset<context_t>;
305  ratexpset_t rs(a->context(), ratexpset_t::identities_t::trivial);
306  if (algo == "auto" || algo == "naive")
307  return make_ratexp(rs, ::vcsn::to_expression_naive(a));
308  else
309  raise("to-expression: invalid algorithm: ", str_escape(algo),
310  ": expected \"auto\", or \"naive\"");
311  }
312 
314  (const automaton& aut, const std::string& algo)
315  -> ratexp);
316  }
317  }
318 
319 } // vcsn::
320 
321 #endif // !VCSN_ALGOS_TO_EXPRESSION_HH
ratexp make_ratexp(const RatExpSet &rs, const typename RatExpSet::value_t &ratexp)
Definition: ratexp.hh:85
RatExpSet::value_t to_expression(const Aut &a, const state_chooser_t< Aut > &next_state)
Aut eliminate_state(const Aut &aut, state_t_of< Aut > s)
A copy of automaton res without the state s.
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:34
automaton_t & aut_
The automaton we work on.
automaton eliminate_state(const automaton &aut, int state)
Bridge.
int debug_
Debug level. The higher, the more details are reported.
state_t_of< Aut > next_naive(const Aut &a)
RatExpSet::value_t to_expression_naive(const Aut &a)
Aut & eliminate_state_here(Aut &res, state_t_of< Aut > s)
Remove state s from automaton res.
int debug_
Debug level. The higher, the more details are reported.
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:77
typename std::remove_cv< Aut >::type automaton_t
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Definition: escape.cc:43
std::shared_ptr< detail::ratexp_base > ratexp
Definition: fwd.hh:64
std::function< state_t_of< Lifted >(const Lifted &)> state_chooser_t
A state (inner) from an automaton.
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:32
AutOut copy(const AutIn &input, Pred keep_state)
A copy of input keeping only its states that are accepted by keep_state.
Definition: copy.hh:171
ratexp to_expression(const automaton &aut, const std::string &algo)
Bridge.
std::function< state_t(const automaton_t &)> state_chooser_t
State selector type.
detail::lifted_automaton_t< Aut > lift(const Aut &a)
Definition: lift.hh:77
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:38
std::vector< typename Cont::value_type > to_vector(const Cont &cont)
Return the content of cont as a vector.
Definition: vector.hh:56
state_eliminator< Aut > make_state_eliminator(Aut &a)
void operator()(state_t s)
Eliminate state s.
void operator()(const state_chooser_t &next_state)
Eliminate all the states, in the order specified by next_state.
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
automaton_t & aut_
The automaton we work on.
void operator()(const state_chooser_t &next_state)
Eliminate all the states, in the order specified by next_state.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
typename std::remove_cv< Aut >::type automaton_t
std::function< state_t(const automaton_t &)> state_chooser_t
State selector type.
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39