Vcsn  2.1
Be Rational
lightest.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <deque>
5 #include <fstream>
6 
7 #include <boost/heap/binomial_heap.hpp>
8 #include <boost/optional.hpp>
9 
10 #include <vcsn/ctx/context.hh>
11 #include <vcsn/dyn/automaton.hh>
12 #include <vcsn/dyn/fwd.hh>
13 #include <vcsn/dyn/polynomial.hh>
15 
16 namespace vcsn
17 {
18 
19  /*----------------------.
20  | lightest(automaton). |
21  `----------------------*/
22 
23  namespace detail
24  {
25 
34  template <typename Aut>
35  class weighter
36  {
37  public:
38  using automaton_t = Aut;
40 
44  using monomial_t = typename polynomialset_t::monomial_t;
45 
49 
53 
54  using datum_t = std::tuple<state_t, word_t, weight_t>;
55  struct datum_less
56  {
58  bool operator()(const datum_t& r, const datum_t& l) const
59  {
60  if (weightset_t::less(std::get<2>(l), std::get<2>(r)))
61  return true;
62  else if (weightset_t::less(std::get<2>(r), std::get<2>(l)))
63  return false;
64  else if (labelset_t::less(std::get<1>(l), std::get<1>(r)))
65  return true;
66  else if (labelset_t::less(std::get<1>(r), std::get<1>(l)))
67  return false;
68  else
69  return std::get<0>(l) < std::get<0>(r);
70  }
71  };
72  using queue_t =
73  boost::heap::binomial_heap<datum_t,
74  boost::heap::compare<datum_less>>;
75 
79  weighter(const automaton_t& aut)
80  : aut_(aut)
81  {}
82 
85  polynomial_t operator()(boost::optional<unsigned> num)
86  {
87  if (!num)
88  num = 1;
89 
90  return lightest_(*num);
91  }
92 
93  private:
94  polynomial_t lightest_(unsigned num)
95  {
96  auto queue = queue_t{};
97  queue.emplace(aut_->pre(), ls_.one(), ws_.one());
98 
99  // The approximated behavior: the first orders to post's past.
100  polynomial_t res;
101  while (!queue.empty())
102  {
103  state_t s; word_t l; weight_t w;
104  std::tie(s, l, w) = queue.top();
105 
106  queue.pop();
107 
108  for (const auto t: aut_->all_out(s))
109  {
110  auto dst = aut_->dst_of(t);
111  auto nw = ws_.mul(w, aut_->weight_of(t));
112  if (aut_->src_of(t) == aut_->pre())
113  queue.emplace(dst, l, std::move(nw));
114  else if (dst == aut_->post())
115  ps_.add_here(res, l, std::move(nw));
116  else
117  {
118  auto nl = ls_.mul(l, aut_->label_of(t));
119  queue.emplace(dst, std::move(nl), std::move(nw));
120  }
121  }
122 
123  // If we found enough words *and* we have completely
124  // treated the current word (there are no other copies in
125  // other states), we're done.
126  if (queue.empty()
127  || (num == res.size()
128  && !ls_.equal(std::get<1>(queue.top()), l)))
129  break;
130  }
131 
132  return res;
133  }
134 
136  void show_heap_(const queue_t& q, std::ostream& os = std::cerr)
137  {
138  const char* sep = "";
139  for (auto i = q.ordered_begin(), end = q.ordered_end();
140  i != end; ++i)
141  {
142  os << sep;
143  sep = " , ";
144  aut_->print_state_name(std::get<0>(*i), os) << ":<";
145  ws_.print(std::get<2>(*i), os);
146  os << ">:";
147  ls_.print(std::get<1>(*i), os);
148  }
149  os << '\n';
150  }
151 
154  const weightset_t& ws_ = *aut_->weightset();
155  const polynomialset_t ps_ = make_word_polynomialset(aut_->context());
156  const labelset_t& ls_ = *ps_.labelset();
157  };
158  }
159 
164  template <typename Automaton>
165  inline
167  lightest(const Automaton& aut, boost::optional<unsigned> num = {})
168  {
169  detail::weighter<Automaton> weighter(aut);
170  return weighter(num);
171  }
172 
173 
177  template <typename Automaton>
178  inline
179  typename detail::weighter<Automaton>::polynomial_t
180  weigh(const Automaton& aut)
181  {
182  return lightest(aut, boost::none);
183  }
184 
185 
186  namespace dyn
187  {
188  namespace detail
189  {
191  template <typename Aut, typename Num>
192  polynomial
193  lightest(const automaton& aut, boost::optional<unsigned> num)
194  {
195  const auto& a = aut->as<Aut>();
196  auto ps = vcsn::detail::make_word_polynomialset(a->context());
197  return make_polynomial(ps, lightest(a, num));
198  }
199  }
200  }
201 }
state_t_of< automaton_t > state_t
Definition: lightest.hh:52
weightset_t_of< automaton_t > weightset_t
Definition: lightest.hh:50
detail::weighter< Automaton >::polynomial_t lightest(const Automaton &aut, boost::optional< unsigned > num={})
The approximated behavior of an automaton.
Definition: lightest.hh:167
word_t_of< automaton_t > word_t
Definition: lightest.hh:48
typename polynomialset_t::monomial_t monomial_t
Definition: lightest.hh:44
detail::weighter< Automaton >::polynomial_t weigh(const Automaton &aut)
The approximated behavior of an automaton.
Definition: lightest.hh:180
const weightset_t & ws_
Definition: lightest.hh:154
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
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
const polynomialset_t ps_
Definition: lightest.hh:155
weight_t_of< automaton_t > weight_t
Definition: lightest.hh:51
automaton_t aut_
The automaton whose behavior to approximate.
Definition: lightest.hh:153
typename labelset_t_of< base_t< ValueSet >>::word_t word_t_of
Definition: traits.hh:65
labelset_t_of< polynomialset_t > labelset_t
Wordset.
Definition: lightest.hh:47
polynomial make_polynomial(const PolynomialSet &ps, const typename PolynomialSet::value_t &p)
Definition: polynomial.hh:88
weighter(const automaton_t &aut)
Prepare to compute an approximation of the behavior.
Definition: lightest.hh:79
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
auto make_word_polynomialset(const Ctx &ctx) -> word_polynomialset_t< Ctx >
The polynomialset of words of a labelset (not necessarily on words itself).
The lightest algorithm computes the paths between pre and post with the smallest weight possible...
Definition: lightest.hh:35
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
polynomial_t operator()(boost::optional< unsigned > num)
The approximated behavior of the automaton.
Definition: lightest.hh:85
context_t_of< Aut > context_t
Definition: lightest.hh:39
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:47
typename polynomialset_t::value_t polynomial_t
Definition: lightest.hh:43
std::ostringstream os
The output stream: the corresponding C++ snippet to compile.
Definition: translate.cc:374
polynomial lightest(const automaton &aut, boost::optional< unsigned > num)
Bridge.
Definition: lightest.hh:193
std::shared_ptr< const detail::polynomial_base > polynomial
Definition: fwd.hh:68
std::tuple< state_t, word_t, weight_t > datum_t
Definition: lightest.hh:54
polynomial_t lightest_(unsigned num)
Definition: lightest.hh:94
bool operator()(const datum_t &r, const datum_t &l) const
Whether l < r (as this is a max heap).
Definition: lightest.hh:58
const labelset_t & ls_
Definition: lightest.hh:156
boost::heap::binomial_heap< datum_t, boost::heap::compare< datum_less >> queue_t
Definition: lightest.hh:74
void show_heap_(const queue_t &q, std::ostream &os=std::cerr)
Show the heap, for debugging.
Definition: lightest.hh:136
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:50