Vcsn  2.3
Be Rational
k-lightest-path.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 
5 #include <boost/heap/fibonacci_heap.hpp>
6 
8 #include <vcsn/algos/dijkstra.hh>
10 #include <vcsn/algos/filter.hh>
11 
12 namespace vcsn
13 {
17  struct yen_tag {};
18 
19  namespace detail
20  {
33  template <Automaton Aut, typename ValueSet, typename Mul, typename GetValue>
34  struct yen_impl
35  {
36  using automaton_t = Aut;
41  using path_t = std::vector<transition_t>;
42  using paths_t = std::vector<path_t>;
43 
44  using valueset_t = ValueSet;
45  using value_t = typename valueset_t::value_t;
46 
47  yen_impl(const automaton_t& aut, const ValueSet& vs, Mul mul, GetValue get_value)
48  : aut_{aut}
49  , vs_{vs}
50  , mul_{mul}
51  , get_value_(get_value)
52  {}
53 
54  struct profile
55  {
56  profile(const path_t& path, const value_t& v, const valueset_t& vs)
57  : path_{path}
58  , v_{v}
59  , vs_{vs}
60  {}
61 
62  bool operator<(const profile& rhs) const
63  {
64  return vs_.less(rhs.v_, v_);
65  }
66 
69  const valueset_t& vs_;
70  };
71 
72  using heap_t = boost::heap::fibonacci_heap<profile>;
73 
74  template <Automaton AnyAut>
75  path_t
76  path(const AnyAut& aut,
77  const path_t& path,
78  state_t_of<Aut> src = Aut::element_type::pre(),
79  state_t_of<Aut> dst = Aut::element_type::post())
80  {
81  path_t res;
82  for (auto t = path[dst];
83  t != aut->null_transition();
84  t = path[aut->src_of(t)])
85  {
86  res.emplace_back(t);
87  if (aut->src_of(t) == src)
88  break;
89  }
90  std::reverse(res.begin(), res.end());
91  return res;
92  }
93 
94  template <Automaton AnyAut>
95  path_t
96  compute_lightest_path(const AnyAut& aut,
97  state_t_of<Aut> src = Aut::element_type::pre(),
98  state_t_of<Aut> dst = Aut::element_type::post())
99  {
100  auto algo = detail::make_dijkstra_impl(aut, vs_, mul_);
101  return std::move(algo(src, dst));
102  }
103 
104  paths_t
105  operator()(state_t src, state_t dst, unsigned k)
106  {
107  auto first = compute_lightest_path(aut_, src, dst);
108  auto res = paths_t{path(aut_, first, src, dst)};
109  auto ps = make_word_polynomialset(aut_->context());
110 
111  auto heap = heap_t();
112 
113  for (unsigned i = 1u; i < k; i++)
114  {
115  const auto& prev = res[i - 1];
116  for (unsigned j = 0u; j < prev.size(); j++)
117  {
118  auto filter_aut = filter<automaton_t, true>(aut_);
119  filter_aut->unhide_all_states();
120  filter_aut->unhide_all_transition();
121  auto spur_node = filter_aut->src_of(prev[j]);
122  auto root_path = path_t(prev.begin(), prev.begin() + j);
123 
124  for (const auto& selected_path: res)
125  if (j < selected_path.size())
126  {
127  auto diff = std::mismatch(root_path.begin(), root_path.end(),
128  selected_path.begin(), selected_path.begin() + j);
129  if (diff.first == root_path.end()
130  && filter_aut->has_transition(selected_path[j]))
131  filter_aut->hide_transition(selected_path[j]);
132  }
133 
134  for (auto t: root_path)
135  if (t != filter_aut->null_transition()
136  && filter_aut->src_of(t) != spur_node
137  && filter_aut->src_of(t) != aut_->pre()
138  && filter_aut->has_state(filter_aut->src_of(t)))
139  filter_aut->hide_state(filter_aut->src_of(t));
140 
141  auto shortest_path = compute_lightest_path(filter_aut, spur_node, dst);
142  auto spur_path = path(filter_aut, shortest_path, spur_node, dst);
143  root_path.insert(root_path.end(), spur_path.begin(), spur_path.end());
144  if (!root_path.empty()
145  && filter_aut->src_of(root_path.front()) == src
146  && filter_aut->dst_of(root_path.back()) == dst)
147  {
148  bool already_found = false;
149  for (const auto& profile: heap)
150  {
151  auto& selected_path = profile.path_;
152  if (root_path.size() == selected_path.size())
153  {
154  auto diff = std::mismatch(root_path.begin(), root_path.end(),
155  selected_path.begin(), selected_path.end());
156  if (diff.first == root_path.end())
157  {
158  already_found = true;
159  break;
160  }
161  }
162  }
163  if (!already_found)
164  {
165  auto m = *path_monomial(filter_aut, format_lightest(filter_aut, root_path), src, dst);
166  heap.emplace(std::move(root_path), get_value_(m), vs_);
167  }
168  }
169  }
170  if (heap.empty())
171  break;
172  res.push_back(heap.top().path_);
173  heap.pop();
174  }
175  return res;
176  }
177 
179  const ValueSet& vs_;
180  Mul mul_;
181  GetValue get_value_;
182  };
183 
184  template <Automaton Aut, typename ValueSet, typename Mul, typename GetValue>
185  auto
186  make_yen(const Aut& aut, const ValueSet& vs, Mul mul, GetValue get_value)
187  {
188  return detail::yen_impl<Aut, ValueSet, Mul, GetValue>(aut, vs, mul, get_value);
189  }
190  }
191 
192  template <Automaton Aut>
193  std::vector<std::vector<transition_t_of<Aut>>>
194  k_lightest_path(const Aut& aut, state_t_of<Aut> source, state_t_of<Aut> dest, unsigned k)
195  {
196  auto mul = [&aut](auto lhs, transition_t_of<Aut> t)
197  {
198  return aut->weightset()->mul(lhs, aut->weight_of(t));
199  };
200  auto get_value = [](auto m) { return m.second; };
201  auto yen = detail::make_yen(aut, *aut->weightset(), mul, get_value);
202  return yen(source, dest, k);
203  }
204 
205  template <Automaton Aut>
206  std::vector<transition_t_of<Aut>>
207  format_lightest(const Aut& aut, const std::vector<transition_t_of<Aut>>& path)
208  {
209  auto res = std::vector<transition_t_of<Aut>>(states_size(aut),
210  aut->null_transition());
211  for (auto t : path)
212  if (t != aut->null_transition())
213  res[aut->dst_of(t)] = t;
214  return res;
215  }
216 
217  template <Automaton Aut>
218  std::vector<transition_t_of<Aut>>
219  lightest_path(const Aut& aut, state_t_of<Aut> source, state_t_of<Aut> dest,
220  yen_tag)
221  {
222  auto paths = k_lightest_path(aut, source, dest, 1);
223  auto res = paths.empty() ? std::vector<transition_t_of<Aut>>() : paths.front();
224  return format_lightest(aut, res);
225  }
226 }
context_t_of< automaton_t > context_t
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:66
auto make_yen(const Aut &aut, const ValueSet &vs, Mul mul, GetValue get_value)
boost::heap::fibonacci_heap< profile > heap_t
std::vector< transition_t > path_t
bool operator<(const profile &rhs) const
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:65
weight_t_of< automaton_t > weight_t
mutable_automaton< Context > u(const Context &ctx, unsigned n)
The Brzozowski universal witness.
Definition: u.hh:15
Yen implementation.
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:19
state_t_of< automaton_t > state_t
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:61
std::vector< path_t > paths_t
transition_t_of< automaton_t > transition_t
std::vector< std::vector< transition_t_of< Aut > > > k_lightest_path(const Aut &aut, state_t_of< Aut > source, state_t_of< Aut > dest, unsigned k)
profile(const path_t &path, const value_t &v, const valueset_t &vs)
return res
Definition: multiply.hh:398
Yen implementation of the K lightest automaton algorithm.
std::vector< transition_t_of< Aut > > format_lightest(const Aut &aut, const std::vector< transition_t_of< Aut >> &path)
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:64
yen_impl(const automaton_t &aut, const ValueSet &vs, Mul mul, GetValue get_value)
Paths in filesystems, i.e., file names.
Definition: path.hh:21
Definition: a-star.hh:8
const automaton_t & aut_
auto make_word_polynomialset(const Ctx &ctx) -> word_polynomialset_t< Ctx >
The polynomialset of words of a labelset (not necessarily on words itself).
auto path_monomial(const Aut &aut, const std::vector< transition_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).
path_t path(const AnyAut &aut, const path_t &path, state_t_of< Aut > src=Aut::element_type::pre(), state_t_of< Aut > dst=Aut::element_type::post())
typename valueset_t::value_t value_t
paths_t operator()(state_t src, state_t dst, unsigned k)
path_t compute_lightest_path(const AnyAut &aut, state_t_of< Aut > src=Aut::element_type::pre(), state_t_of< Aut > dst=Aut::element_type::post())
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
auto make_dijkstra_impl(const Aut &aut, const ValueSet &vs, Mul mul)
Definition: dijkstra.hh:129