20 template<
typename VertexDataMap,
typename Visitor = DoNothingGraphVisitor<VertexID>,
typename SourceList = std::vector<VertexID>>
22 const SourceList& sources,
24 const VertexDataMap& vertex_data,
25 Visitor&& visitor = {}
29 auto nodes_in_path = makeVertexSet();
30 std::vector<VertexID> path;
34 bool left_source =
false;
35 auto traceback_curr = sink;
36 while (success && not done) {
38 visitor.onExamine(traceback_curr);
39 path.push_back(traceback_curr);
41 nodes_in_path.insert(traceback_curr);
43 if (sources.find(traceback_curr) !=
end(sources) && left_source) {
47 const auto& data_search = vertex_data.find(traceback_curr);
48 if (data_search !=
end(vertex_data)) {
49 auto& found_data = data_search->second;
50 for (
auto& fanin : found_data.fanin) {
51 if (not visitor.shouldIgnore(fanin) && nodes_in_path.find(fanin) ==
end(nodes_in_path)) {
52 traceback_curr = fanin;
57 if (not success && not found_data.fanin.empty()) {
58 traceback_curr = found_data.fanin.front();
61 if (success && nodes_in_path.find(traceback_curr) !=
end(nodes_in_path)) {
69 std::reverse(
begin(path),
end(path));
96 template<
typename Graph,
typename IsTarget,
typename AcceptPath =
AlwaysTrue,
99 std::ptrdiff_t max_paths,
101 const InitialList& initial_list,
102 IsTarget&& is_target,
103 Visitor&& visitor = {},
104 AcceptPath&& acceptPath = {}
107 int expansion_count = 0;
108 bool operator==(
const VertexData& rhs)
const {
return this->expansion_count == rhs.expansion_count; }
111 auto vdata = makeVertexMap<VertexData>();
116 std::set<std::pair<std::ptrdiff_t, VertexPath>> paths_to_explore;
119 std::set<std::pair<std::ptrdiff_t, VertexPath>> paths_skipped;
121 int skipped_paths = 0;
123 const auto cost_and_add_path = [&](
const auto& base_path,
const auto& new_vertex) {
124 auto new_path = base_path;
125 new_path.push_back(new_vertex);
126 auto new_path_cost = new_path.size();
127 paths_to_explore.emplace(new_path_cost, std::move(new_path));
131 for (
const auto& vertex : initial_list) {
132 if (visitor.shouldIgnore(vertex)) {
133 visitor.onSkippedEdge(vertex, vertex);
continue; }
135 visitor.onExamine(vertex);
136 for (
const auto& fanout : graph.fanout(vertex)) {
137 if (visitor.shouldIgnore(fanout) || visitor.shouldIgnoreEdge(vertex,fanout)) {
138 visitor.onSkippedEdge(vertex, fanout);
continue; }
140 visitor.onExamineEdge(vertex,fanout);
141 cost_and_add_path(VertexPath{vertex}, fanout);
145 while (!paths_to_explore.empty() && ((std::ptrdiff_t)result.size() + skipped_paths) != max_paths) {
147 auto cost_and_path_mutable = std::move(*paths_to_explore.begin());
148 const auto& p = cost_and_path_mutable.second;
149 paths_to_explore.erase(
begin(paths_to_explore));
151 const auto& tip = p.back();
153 if (visitor.shouldIgnore(tip)) {
154 visitor.onSkipped(tip);
158 if (vdata[tip].expansion_count == max_paths) {
159 visitor.onSkipped(tip);
161 paths_skipped.insert(std::move(cost_and_path_mutable));
165 visitor.onExamine(tip);
168 vdata[tip].expansion_count += 1;
171 for (
const auto& fanout : graph.fanout(tip)) {
173 not visitor.shouldIgnore(fanout)
174 && not visitor.shouldIgnoreEdge(tip,fanout)
175 && p.front() != p.back()
176 && find(std::next(
begin(p)),
end(p), fanout) ==
end(p)
178 cost_and_add_path(p, fanout);
180 visitor.onExamineEdge(tip, fanout);
182 visitor.onSkippedEdge(tip, fanout);
187 if (is_target(tip)) {
189 result.emplace_back(std::move(cost_and_path_mutable.second));
194 std::move(paths_skipped.begin(), paths_skipped.end(),
195 std::inserter(paths_to_explore, paths_to_explore.end()));
196 paths_skipped.clear();
204 template<
typename Graph,
typename IsTarget,
typename Visitor = DoNothingGraphVisitor<VertexID>,
typename InitialList = std::vector<VertexID>>
206 std::ptrdiff_t max_paths,
208 const InitialList& initial_list,
209 IsTarget&& is_target,
212 auto initial_path =
findNShortestPaths(1, graph, initial_list, is_target, visitor).at(0);
213 std::set<std::pair<int,VertexPath>> potential_paths {};
216 if (max_paths == 0) {
return result; }
217 result.push_back(initial_path);
218 for (
int k = 1; k != max_paths; ++k) {
219 const auto& prev_path = result.back();
221 for (
int i = 0; i < (std::ptrdiff_t)prev_path.size() - 1; ++i) {
222 const auto pp_spurNode = std::next(prev_path.begin(), i);
226 VertexSet<> vertices_to_ignore = {};
227 EdgeSet edges_to_ignore = {};
229 V(
typename Base::VisitorPtr fwd) : Base(fwd) { }
232 return Base::shouldIgnore(v)
233 || vertices_to_ignore.find(v) !=
end(vertices_to_ignore);
236 return Base::shouldIgnoreEdge(v1,v2)
237 || edges_to_ignore.find(std::make_pair(v1, v2)) !=
end(edges_to_ignore);
241 for (
const auto& p : result) {
243 prev_path.begin(), std::next(pp_spurNode),
245 ).first == std::next(pp_spurNode)
247 v.edges_to_ignore.emplace(p.at(i), p.at(i+1));
250 for (
auto it = prev_path.begin(); it != pp_spurNode; ++it) {
251 v.vertices_to_ignore.insert(*it);
254 const auto spurpath_search =
findNShortestPaths(1, graph, {*pp_spurNode}, is_target, v);
255 if (spurpath_search.size() == 0) {
258 const auto& spur_path = spurpath_search.at(0);
260 VertexPath totalPath;
261 std::copy(prev_path.begin(), pp_spurNode, std::back_inserter(totalPath));
262 std::copy(spur_path.begin(), spur_path.end(), std::back_inserter(totalPath));
264 potential_paths.emplace(totalPath.size(), totalPath);
267 if (potential_paths.empty()) {
271 auto best_path_it = potential_paths.begin();
272 result.push_back(best_path_it->second);
273 potential_paths.erase(best_path_it);