Vcsn  2.5.dev
Be Rational
k-lightest-path.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 
5 #include <boost/algorithm/string/predicate.hpp>
6 #include <boost/range/algorithm/mismatch.hpp>
7 #include <boost/range/iterator_range_core.hpp>
8 
9 #include <vcsn/algos/dijkstra.hh>
10 #include <vcsn/algos/filter.hh>
14 
15 namespace vcsn
16 {
20  struct yen_tag {};
21 
22  namespace detail
23  {
41  template <Automaton Aut, typename ValueSet,
42  typename Mul, typename GetValue>
43  struct yen_impl
44  {
45  using automaton_t = Aut;
51  using paths_t = std::vector<path_t>;
52 
53  using valueset_t = ValueSet;
54  using value_t = typename valueset_t::value_t;
55 
56  yen_impl(const automaton_t& aut, const ValueSet& vs,
57  Mul mul, GetValue get_value)
58  : aut_{aut}
59  , vs_{vs}
60  , mul_{mul}
61  , get_value_(get_value)
62  {}
63 
64  struct profile
65  {
66  profile(const path_t& path, const valueset_t& vs,
67  const value_t& v)
68  : path_{path}
69  , vs_{vs}
70  , v_{v}
71  {}
72 
73  bool operator<(const profile& rhs) const
74  {
75  return vs_.less(v_, rhs.v_);
76  }
77 
79  const valueset_t& vs_;
81  };
82 
85 
94  template <Automaton AnyAut>
96  path(const AnyAut& aut,
98  state_t_of<AnyAut> src = AnyAut::element_type::pre(),
99  state_t_of<AnyAut> dst = AnyAut::element_type::post())
100  {
101  auto res = path_t_of<AnyAut>{};
102  for (auto t = path[dst];
103  t != aut->null_transition();
104  t = path[aut->src_of(t)])
105  {
106  res.emplace_back(t);
107  if (aut->src_of(t) == src)
108  break;
109  }
110  std::reverse(res.begin(), res.end());
111  return res;
112  }
113 
120  template <Automaton AnyAut>
122  compute_lightest_path(const AnyAut& aut,
123  state_t_of<AnyAut> src = Aut::element_type::pre(),
124  state_t_of<AnyAut> dst = Aut::element_type::post())
125  {
126  auto algo = detail::make_dijkstra_impl(aut, vs_, mul_);
127  return algo(src, dst);
128  }
129 
130  paths_t
131  operator()(state_t src, state_t dst, unsigned k)
132  {
133  using boost::starts_with;
134  using boost::make_iterator_range;
135  auto first = compute_lightest_path(aut_, src, dst);
136  auto res = paths_t{path(aut_, first, src, dst)};
137  auto ps = make_word_polynomialset(aut_->context());
138 
139  auto heap = heap_t{};
140 
141  for (auto i = 1u; i < k; i++)
142  {
143  const auto& prev = res[i - 1];
144  for (auto j = 0u; j < prev.size(); j++)
145  {
146  auto filter_aut = filter<automaton_t, true>(aut_);
147  auto spur_node = filter_aut->src_of(prev[j]);
148  auto root_path = path_t(prev.begin(), prev.begin() + j);
149 
150  for (const auto& selected_path: res)
151  if (boost::starts_with(selected_path, root_path))
152  filter_aut->hide_transition(selected_path[j]);
153 
154  for (auto t: root_path)
155  if (t != filter_aut->null_transition()
156  && filter_aut->src_of(t) != spur_node
157  && filter_aut->src_of(t) != aut_->pre())
158  filter_aut->hide_state(filter_aut->src_of(t));
159 
160  auto lightest_path
161  = compute_lightest_path(filter_aut, spur_node, dst);
162  auto spur_path
163  = path(filter_aut, lightest_path, spur_node, dst);
164  root_path.insert(root_path.end(),
165  spur_path.begin(), spur_path.end());
166  if (!root_path.empty()
167  && filter_aut->src_of(root_path.front()) == src
168  && filter_aut->dst_of(root_path.back()) == dst
169  && none_of(heap,
170  [&root_path](const auto& profile)
171  {
172  return profile.path_ == root_path;
173  }))
174  {
175  auto m
176  = *path_monomial(filter_aut,
177  format_lightest(filter_aut, root_path),
178  src, dst);
179  heap.emplace(std::move(root_path), vs_, get_value_(m));
180  }
181  }
182  if (heap.empty())
183  break;
184  res.push_back(heap.top().path_);
185  heap.pop();
186  }
187  return res;
188  }
189 
191  const ValueSet& vs_;
192  Mul mul_;
193  GetValue get_value_;
194  };
195 
196  template <Automaton Aut, typename ValueSet, typename Mul, typename GetValue>
197  auto
198  make_yen(const Aut& aut, const ValueSet& vs, Mul mul, GetValue get_value)
199  {
201  (aut, vs, mul, get_value));
202  }
203  }
204 
205 
206  template <Automaton Aut>
207  std::vector<path_t_of<Aut>>
209  unsigned k)
210  {
211  auto mul = [&aut](auto lhs, transition_t_of<Aut> t)
212  {
213  return aut->weightset()->mul(lhs, aut->weight_of(t));
214  };
215  auto get_value = [](auto m) { return m.second; };
216  auto yen = detail::make_yen(aut, *aut->weightset(), mul, get_value);
217  return yen(src, dst, k);
218  }
219 
226  template <Automaton Aut>
228  format_lightest(const Aut& aut, const std::vector<transition_t_of<Aut>>& path)
229  {
230  auto res = predecessors_t_of<Aut>(states_size(aut), aut->null_transition());
231  for (auto t : path)
232  if (t != aut->null_transition())
233  res[aut->dst_of(t)] = t;
234  return res;
235  }
236 
237  template <Automaton Aut>
240  yen_tag)
241  {
242  auto paths = k_lightest_path(aut, src, dst, 1);
243  auto res = paths.empty() ? predecessors_t_of<Aut>() : paths.front();
244  return format_lightest(aut, res);
245  }
246 }
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
path_t_of< AnyAut > path(const AnyAut &aut, const predecessors_t_of< AnyAut > &path, state_t_of< AnyAut > src=AnyAut::element_type::pre(), state_t_of< AnyAut > dst=AnyAut::element_type::post())
Transform a map transition_t -> transition_t representing the predecessors of each transition into a ...
std::vector< path_t > paths_t
typename valueset_t::value_t value_t
auto path_monomial(const Aut &aut, const predecessors_t_of< Aut > &path, state_t_of< Aut > src=Aut::element_type::pre(), state_t_of< Aut > dst=Aut::element_type::post()) -> boost::optional< typename detail::word_polynomialset_t< context_t_of< Aut >>::monomial_t >
Given a path (typically computed by lightest_path), the corresponding monomial (label, weight).
weight_t_of< automaton_t > weight_t
auto make_word_polynomialset(const Ctx &ctx) -> word_polynomialset_t< Ctx >
The polynomialset of words of a labelset (not necessarily on words itself).
return v
Definition: multiply.hh:362
return res
Definition: multiply.hh:399
Yen&#39;s algorithm of the K lightest paths.
auto make_yen(const Aut &aut, const ValueSet &vs, Mul mul, GetValue get_value)
state_t_of< automaton_t > state_t
const automaton_t & aut_
vcsn::min_fibonacci_heap< profile > heap_t
Min heap according to the weight.
context_t_of< automaton_t > context_t
paths_t operator()(state_t src, state_t dst, unsigned k)
bool none_of(const Range &r, Predicate p)
Definition: algorithm.hh:193
yen_impl(const automaton_t &aut, const ValueSet &vs, Mul mul, GetValue get_value)
profile(const path_t &path, const valueset_t &vs, const value_t &v)
std::vector< transition_t_of< Aut > > lightest_path(const Aut &aut, state_t_of< Aut > source, state_t_of< Aut > dest, a_star_tag)
Definition: a-star.hh:151
#define Automaton
Definition: automaton.hh:23
Definition: a-star.hh:8
Yen implementation.
predecessors_t_of< AnyAut > compute_lightest_path(const AnyAut &aut, state_t_of< AnyAut > src=Aut::element_type::pre(), state_t_of< AnyAut > dst=Aut::element_type::post())
Compute a lightest path on a part of the automaton.
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:41
boost::heap::fibonacci_heap< Elt, detail::comparator_t< Elt > > min_fibonacci_heap
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
path_t_of< automaton_t > path_t
std::vector< path_t_of< Aut > > k_lightest_path(const Aut &aut, state_t_of< Aut > src, state_t_of< Aut > dst, unsigned k)
Explicit path representation.
Definition: path.hh:16
mutable_automaton< Context > u(const Context &ctx, unsigned n)
The Brzozowski universal witness.
Definition: u.hh:15
transition_t_of< automaton_t > transition_t
bool operator<(const profile &rhs) const
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Definition: traits.hh:65
auto make_dijkstra_impl(const Aut &aut, const ValueSet &vs, Mul mul)
Definition: dijkstra.hh:132
std::vector< transition_t_of< Aut > > path_t_of
A list of transitions representing a path.
Definition: automaton.hh:28
predecessors_t_of< Aut > format_lightest(const Aut &aut, const std::vector< transition_t_of< Aut >> &path)
A state-indexed vector of predecessor transitions from the path path.
std::vector< transition_t_of< Aut > > predecessors_t_of
A state-indexed vector of predecessor transitions from the path path.
Definition: automaton.hh:18