Vcsn  2.5
Be Rational
k-lightest-path.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 
5 #include <boost/range/algorithm/mismatch.hpp>
6 
9 #include <vcsn/algos/dijkstra.hh>
11 #include <vcsn/algos/filter.hh>
12 
13 namespace vcsn
14 {
18  struct yen_tag {};
19 
20  namespace detail
21  {
39  template <Automaton Aut, typename ValueSet,
40  typename Mul, typename GetValue>
41  struct yen_impl
42  {
43  using automaton_t = Aut;
49  using paths_t = std::vector<path_t>;
50 
51  using valueset_t = ValueSet;
52  using value_t = typename valueset_t::value_t;
53 
54  yen_impl(const automaton_t& aut, const ValueSet& vs,
55  Mul mul, GetValue get_value)
56  : aut_{aut}
57  , vs_{vs}
58  , mul_{mul}
59  , get_value_(get_value)
60  {}
61 
62  struct profile
63  {
64  profile(const path_t& path, const valueset_t& vs,
65  const value_t& v)
66  : path_{path}
67  , vs_{vs}
68  , v_{v}
69  {}
70 
71  bool operator<(const profile& rhs) const
72  {
73  return vs_.less(v_, rhs.v_);
74  }
75 
77  const valueset_t& vs_;
79  };
80 
82 
91  template <Automaton AnyAut>
93  path(const AnyAut& aut,
95  state_t_of<AnyAut> src = AnyAut::element_type::pre(),
96  state_t_of<AnyAut> dst = AnyAut::element_type::post())
97  {
99  for (auto t = path[dst];
100  t != aut->null_transition();
101  t = path[aut->src_of(t)])
102  {
103  res.emplace_back(t);
104  if (aut->src_of(t) == src)
105  break;
106  }
107  std::reverse(res.begin(), res.end());
108  return res;
109  }
110 
117  template <Automaton AnyAut>
119  compute_lightest_path(const AnyAut& aut,
120  state_t_of<AnyAut> src = Aut::element_type::pre(),
121  state_t_of<AnyAut> dst = Aut::element_type::post())
122  {
123  auto algo = detail::make_dijkstra_impl(aut, vs_, mul_);
124  return algo(src, dst);
125  }
126 
127  paths_t
128  operator()(state_t src, state_t dst, unsigned k)
129  {
130  auto first = compute_lightest_path(aut_, src, dst);
131  auto res = paths_t{path(aut_, first, src, dst)};
132  auto ps = make_word_polynomialset(aut_->context());
133 
134  auto heap = heap_t();
135 
136  for (unsigned i = 1u; i < k; i++)
137  {
138  const auto& prev = res[i - 1];
139  for (unsigned j = 0u; j < prev.size(); j++)
140  {
141  auto filter_aut = filter<automaton_t, true>(aut_);
142  filter_aut->unhide_all_states();
143  filter_aut->unhide_all_transition();
144  auto spur_node = filter_aut->src_of(prev[j]);
145  auto root_path = path_t(prev.begin(), prev.begin() + j);
146 
147  for (const auto& selected_path: res)
148  if (j < selected_path.size())
149  {
150  auto diff = std::mismatch(root_path.begin(),
151  root_path.end(),
152  selected_path.begin(),
153  selected_path.begin() + j);
154  if (diff.first == root_path.end()
155  && filter_aut->has_transition(selected_path[j]))
156  filter_aut->hide_transition(selected_path[j]);
157  }
158 
159  for (auto t: root_path)
160  if (t != filter_aut->null_transition()
161  && filter_aut->src_of(t) != spur_node
162  && filter_aut->src_of(t) != aut_->pre()
163  && filter_aut->has_state(filter_aut->src_of(t)))
164  filter_aut->hide_state(filter_aut->src_of(t));
165 
166  auto shortest_path
167  = compute_lightest_path(filter_aut, spur_node, dst);
168  auto spur_path
169  = path(filter_aut, shortest_path, spur_node, dst);
170  root_path.insert(root_path.end(),
171  spur_path.begin(), spur_path.end());
172  if (!root_path.empty()
173  && filter_aut->src_of(root_path.front()) == src
174  && filter_aut->dst_of(root_path.back()) == dst)
175  {
176  bool already_found = false;
177  for (const auto& profile: heap)
178  {
179  const auto& selected_path = profile.path_;
180  if (root_path.size() == selected_path.size())
181  {
182  auto diff = boost::mismatch(root_path,
183  selected_path);
184  if (diff.first == root_path.end())
185  {
186  already_found = true;
187  break;
188  }
189  }
190  }
191  if (!already_found)
192  {
193  auto m = *path_monomial(filter_aut,
194  format_lightest(filter_aut, root_path),
195  src, dst);
196  heap.emplace(std::move(root_path), vs_, get_value_(m));
197  }
198  }
199  }
200  if (heap.empty())
201  break;
202  res.push_back(heap.top().path_);
203  heap.pop();
204  }
205  return res;
206  }
207 
209  const ValueSet& vs_;
210  Mul mul_;
211  GetValue get_value_;
212  };
213 
214  template <Automaton Aut, typename ValueSet, typename Mul, typename GetValue>
215  auto
216  make_yen(const Aut& aut, const ValueSet& vs, Mul mul, GetValue get_value)
217  {
219  (aut, vs, mul, get_value));
220  }
221  }
222 
223 
224  template <Automaton Aut>
225  std::vector<path_t_of<Aut>>
227  unsigned k)
228  {
229  auto mul = [&aut](auto lhs, transition_t_of<Aut> t)
230  {
231  return aut->weightset()->mul(lhs, aut->weight_of(t));
232  };
233  auto get_value = [](auto m) { return m.second; };
234  auto yen = detail::make_yen(aut, *aut->weightset(), mul, get_value);
235  return yen(src, dst, k);
236  }
237 
244  template <Automaton Aut>
246  format_lightest(const Aut& aut, const std::vector<transition_t_of<Aut>>& path)
247  {
248  auto res = predecessors_t_of<Aut>(states_size(aut), aut->null_transition());
249  for (auto t : path)
250  if (t != aut->null_transition())
251  res[aut->dst_of(t)] = t;
252  return res;
253  }
254 
255  template <Automaton Aut>
258  yen_tag)
259  {
260  auto paths = k_lightest_path(aut, src, dst, 1);
261  auto res = paths.empty() ? predecessors_t_of<Aut>() : paths.front();
262  return format_lightest(aut, res);
263  }
264 }
std::vector< transition_t_of< Aut > > predecessors_t_of
A state-indexed vector of predecessor transitions from the path path.
Definition: automaton.hh:18
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).
yen_impl(const automaton_t &aut, const ValueSet &vs, Mul mul, GetValue get_value)
std::vector< transition_t_of< Aut > > path_t_of
A list of transitions representing a path.
Definition: automaton.hh:28
return v
Definition: multiply.hh:361
Definition: a-star.hh:8
const automaton_t & aut_
return res
Definition: multiply.hh:398
std::vector< path_t > paths_t
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
std::vector< path_t_of< Aut > > k_lightest_path(const Aut &aut, state_t_of< Aut > src, state_t_of< Aut > dst, unsigned k)
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:41
Yen implementation.
state_t_of< automaton_t > state_t
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 ...
paths_t operator()(state_t src, state_t dst, unsigned k)
mutable_automaton< Context > u(const Context &ctx, unsigned n)
The Brzozowski universal witness.
Definition: u.hh:15
path_t_of< automaton_t > path_t
vcsn::min_fibonacci_heap< profile > heap_t
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
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.
auto make_word_polynomialset(const Ctx &ctx) -> word_polynomialset_t< Ctx >
The polynomialset of words of a labelset (not necessarily on words itself).
bool operator<(const profile &rhs) const
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.
auto make_yen(const Aut &aut, const ValueSet &vs, Mul mul, GetValue get_value)
transition_t_of< automaton_t > transition_t
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
Explicit path representation.
Definition: path.hh:16
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Definition: traits.hh:65
weight_t_of< automaton_t > weight_t
#define Automaton
Definition: automaton.hh:23
boost::heap::fibonacci_heap< Elt, detail::comparator_t< Elt > > min_fibonacci_heap
auto make_dijkstra_impl(const Aut &aut, const ValueSet &vs, Mul mul)
Definition: dijkstra.hh:128
Yen&#39;s algorithm of the K lightest paths.
typename valueset_t::value_t value_t
profile(const path_t &path, const valueset_t &vs, const value_t &v)
context_t_of< automaton_t > context_t
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61