Vcsn  2.8
Be Rational
eppstein.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 
7 #include <vcsn/algos/path.hh>
10 
11 namespace vcsn
12 {
13  namespace detail
14  {
18  template <Automaton Aut>
19  class eppstein
20  {
21  using automaton_t = Aut;
26  using sidetrack_costs_t = std::unordered_map<transition_t, weight_t>;
27 
28  public:
29  eppstein(const automaton_t& aut)
30  : aut_{aut}
31  {}
32 
34 
37  std::vector<path<automaton_t>>
38  k_shortest_path(state_t src, state_t dst, int K)
39  {
40  auto tree = make_shortest_path_tree(aut_, dst);
41  auto sidetrack_edge_costs_map = sidetrack_costs_t();
42  auto res = std::vector<path<automaton_t>>{};
43  auto queue = queue_t{};
44  queue.emplace(aut_, aut_->null_transition(),
45  // This `int()` hardly makes sense, as
46  // `null_parent_path` is an `int`. But actually
47  // it's a `static constexpr int`, and clang-3.5
48  // behaves incorrectly on this regard. Remove
49  // this `int()` once we drop support for clang
50  // 3.5.
52  tree.get_weight_of(src));
53 
54  for (int k = 0; k < K && !queue.empty(); k++)
55  {
56  auto k_path_implicit = std::move(queue.top());
57  queue.pop();
58 
59  auto k_path = k_path_implicit.explicit_path(res, tree, src);
60  if (k_path.get_path().empty())
61  return res;
62 
63  res.emplace_back(std::move(k_path));
64 
65  add_children_to_queue_(sidetrack_edge_costs_map, src,
66  k_path_implicit, k,
67  queue, tree);
68  }
69 
70  return res;
71  }
72 
73  private:
78  void
80  const implicit_path_t& k_path_implicit, int k,
81  queue_t& queue,
83  {
84  const auto& ws = *aut_->weightset();
85  const auto& k_path_cost = k_path_implicit.get_weight();
86  auto transition_stack = std::vector<transition_t>{};
87  auto s = k == 0 ? src : aut_->dst_of(k_path_implicit.get_sidetrack());
88  for (auto tr : all_out(aut_, s))
89  transition_stack.push_back(tr);
90 
91  while (!transition_stack.empty())
92  {
93  transition_t curr = transition_stack.back();
94  transition_stack.pop_back();
95 
96  bool has_curr = has(sidetracks, curr);
97  if (!has_curr)
98  {
99  state_t parent = tree.get_parent_of(aut_->src_of(curr));
100  if (parent == aut_->null_state() || parent != aut_->dst_of(curr))
101  {
102  // Use (weight_of(curr) + weight_of(dst)) - weight_of(src) to
103  // avoid underflow of unsigned value (2+(3-4) gives 4294967295).
104  sidetracks[curr]
105  = ws.rdivide(ws.mul(aut_->weight_of(curr),
106  tree.get_weight_of(aut_->dst_of(curr))),
107  tree.get_weight_of(aut_->src_of(curr)));
108  has_curr = true;
109  }
110  }
111 
112  if (has_curr)
113  queue.emplace(aut_, curr, k,
114  ws.mul(k_path_cost, sidetracks[curr]));
115  else
116  for (auto tr : all_out(aut_, aut_->dst_of(curr)))
117  transition_stack.push_back(tr);
118  }
119  }
120 
122  };
123  }
124 
127  template <Automaton Aut>
128  std::vector<detail::path<Aut>>
129  compute_eppstein(const Aut& aut,
131  unsigned num)
132  {
133  auto ksp = detail::eppstein<Aut>(aut);
134  return ksp.k_shortest_path(src, dst, num);
135  }
136 }
ATTRIBUTE_PURE bool has(const boost::container::flat_set< Key, Compare, Allocator > &s, const Key &e)
Whether e is member of s.
Definition: setalpha.hh:26
weight_t_of< automaton_t > weight_t
Definition: eppstein.hh:24
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Definition: traits.hh:65
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
transition_t_of< automaton_t > transition_t
Definition: eppstein.hh:23
Implicit Path representation.
Eppstein implementation of the K shortest path problem adapted to Vcsn.
Definition: eppstein.hh:19
std::vector< detail::path< Aut > > compute_eppstein(const Aut &aut, state_t_of< Aut > src, state_t_of< Aut > dst, unsigned num)
Compute the num lightest paths in the automaton aut from src to dst.
Definition: eppstein.hh:129
transition_t get_sidetrack() const
void add_children_to_queue_(sidetrack_costs_t &sidetracks, state_t src, const implicit_path_t &k_path_implicit, int k, queue_t &queue, shortest_path_tree< automaton_t > &tree)
Update queue with children of the first state in the sidetrack path.
Definition: eppstein.hh:79
eppstein(const automaton_t &aut)
Definition: eppstein.hh:29
weight_t get_weight_of(state_t s) const
const weight_t & get_weight() const
const automaton_t & aut_
Definition: eppstein.hh:121
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:67
shortest_path_tree< Aut > make_shortest_path_tree(const Aut &aut, state_t_of< Aut > root)
state_t_of< automaton_t > state_t
Definition: eppstein.hh:22
Definition: a-star.hh:8
static constexpr int null_parent_path
vcsn::min_fibonacci_heap< implicit_path_t > queue_t
Definition: eppstein.hh:33
std::unordered_map< transition_t, weight_t > sidetrack_costs_t
Definition: eppstein.hh:26
state_t get_parent_of(state_t s) const
std::vector< path< automaton_t > > k_shortest_path(state_t src, state_t dst, int K)
Compute the K shortest paths in the automaton from src to dst.
Definition: eppstein.hh:38
boost::heap::fibonacci_heap< Elt, detail::comparator_t< Elt > > min_fibonacci_heap
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
return res
Definition: multiply.hh:399