15 template<
typename Graph,
typename InitialList,
typename Visitor = DoNothingGraphVisitor<VertexID>>
18 const InitialList& initial_list,
19 Visitor&& visitor = {}
23 bool put_in_queue =
false;
26 auto data = makeVertexMap<VertexData>();
28 std::list<VertexID> to_visit;
29 for (
const auto& vertex : initial_list) {
30 to_visit.push_back(vertex);
31 data[vertex].put_in_queue =
true;
34 while (!to_visit.empty() && !visitor.shouldStop()) {
35 const auto explore_curr = to_visit.front();
38 if (visitor.shouldIgnore(explore_curr)) {
39 visitor.onSkipped(explore_curr);
43 visitor.onExamine(explore_curr);
44 for (
const auto& fanout : graph.fanout(explore_curr)) {
45 auto& fanout_data = data[fanout];
46 if (!fanout_data.put_in_queue && !visitor.shouldIgnore(fanout)) {
47 fanout_data.put_in_queue =
true;
48 to_visit.push_back(fanout);
49 visitor.onExamineEdge(explore_curr, fanout);
51 visitor.onSkippedEdge(explore_curr, fanout);
63 template<
typename Graph,
typename InitialList,
typename VertexCoster,
typename Visitor = DoNothingGraphVisitor<VertexID>>
66 const InitialList& initial_list,
67 VertexCoster&& vertex_coster,
68 Visitor&& visitor = {}
70 using Cost = decltype(vertex_coster(std::declval<VertexID>()));
73 std::array<VertexID,1> fanin;
74 Cost lowest_known_cost;
76 return this->lowest_known_cost == rhs.lowest_known_cost && this->fanin == rhs.fanin; }
81 struct VertexAndCost {
85 bool operator<(
const VertexAndCost& rhs)
const {
86 return cost_to_here > rhs.cost_to_here;
90 auto data = makeVertexMap<VertexData>();
91 std::priority_queue<VertexAndCost> to_visit;
93 for (
const auto& vertex : initial_list) {
94 if (visitor.shouldIgnore(vertex)) {
95 visitor.onSkipped(vertex);
97 to_visit.push({vertex, 0});
98 data.insert({vertex, {{vertex}, 0}});
102 while (!to_visit.empty() && !visitor.shouldStop()) {
103 const auto queue_top = to_visit.top();
104 const auto& explore_curr = queue_top.vid;
111 if (visitor.shouldIgnore(explore_curr) || queue_top.cost_to_here > data.at(explore_curr).lowest_known_cost) {
112 visitor.onSkipped(explore_curr);
117 visitor.onExamine(explore_curr);
118 for (
const auto& fanout : graph.fanout(explore_curr)) {
119 if (visitor.shouldIgnore(fanout) || visitor.shouldIgnoreEdge(explore_curr, fanout)) {
120 visitor.onSkippedEdge(explore_curr, fanout);
123 const auto cost = queue_top.cost_to_here + vertex_coster(fanout);
124 auto fanout_data_insert = data.insert({fanout, {{explore_curr}, cost}});
125 auto& fanout_data = fanout_data_insert.first->second;
126 bool worse = not fanout_data_insert.second && cost >= fanout_data.lowest_known_cost;
128 visitor.onSkippedEdge(explore_curr, fanout);
131 fanout_data.lowest_known_cost = cost;
132 fanout_data.fanin = {explore_curr};
133 to_visit.push({fanout, cost});
134 visitor.onExamineEdge(explore_curr, fanout);
174 template<
typename Graph,
typename IsTarget,
typename Visitor = DoNothingGraphVisitor<VertexID>,
typename InitialList = std::vector<VertexID>>
177 const InitialList& initial_list,
178 IsTarget&& is_target,
179 Visitor&& visitor = {}
183 std::vector<VertexID> fanin = {};
192 std::vector<ExploreData> next_wave = {};
198 auto data = makeVertexMap<VertexData>();
201 std::vector<ExploreData> explorations_to_new_nodes;
202 auto in_next_wave = makeVertexSet();
203 std::vector<WaveData> waveData(num_threads);
204 std::vector<VertexID> curr_wave = {};
206 for (
const auto& vertex : initial_list) {
207 curr_wave.push_back(vertex);
212 const auto expand_wave_code = [&](
int ithread) {
213 const auto& num_data_per_thread = 1 + ((curr_wave.size()-1)/num_threads);
214 const auto& my_curr_wave_begin_index = ithread*num_data_per_thread;
215 const auto& my_curr_wave_end_index = (ithread + 1)*num_data_per_thread + 1;
217 std::next(
begin(curr_wave), std::min(curr_wave.size(), my_curr_wave_begin_index)),
218 std::next(
begin(curr_wave), std::min(curr_wave.size(), my_curr_wave_end_index))
220 auto& my_next_wave = waveData.at(ithread).next_wave;
222 for (
const auto&
id : my_curr_wave) {
223 if (visitor.shouldIgnore(
id)) {
224 visitor.onSkipped(
id);
227 visitor.onExamine(
id);
229 for (
const auto& fanout : graph.fanout(
id)) {
230 if (not visitor.shouldIgnore(fanout) && not visitor.shouldIgnoreEdge(
id, fanout)) {
231 my_next_wave.emplace_back(ExploreData{id, fanout});
233 visitor.onSkippedEdge(
id, fanout);
239 if (num_threads == 1) {
242 std::vector<std::thread> threads;
244 for (
int ithread = 0; ithread < num_threads; ++ithread) {
245 threads.emplace_back(expand_wave_code, ithread);
248 for (
auto& thread : threads) {
253 bool found_target =
false;
254 explorations_to_new_nodes.clear();
255 in_next_wave.clear();
257 for (
auto& waveDatum : waveData) {
258 for (
auto& exploreData : waveDatum.next_wave) {
261 if (data.find(exploreData.fanout) ==
end(data)
262 && in_next_wave.emplace(exploreData.fanout).second
264 curr_wave.push_back(exploreData.fanout);
265 visitor.onExamineEdge(exploreData.parent, exploreData.fanout);
267 visitor.onSkippedEdge(exploreData.parent, exploreData.fanout);
270 if (is_target(exploreData.fanout)) {
279 for (
auto& waveDatum : waveData) {
280 for (
auto& exploreData : waveDatum.next_wave) {
281 data[exploreData.fanout].fanin.emplace_back(exploreData.parent);
287 if (found_target || curr_wave.empty() || visitor.shouldStop()) {
319 template<
typename Graph,
typename Source,
typename IsTarget,
typename Visitor = DoNothingGraphVisitor<VertexID>>
322 const Source& source,
323 IsTarget&& is_target,
324 Visitor&& visitor = {}
327 std::array<VertexID,1> fanin;
328 bool expanded =
false;
331 auto data = makeVertexMap<VertexData>();
338 std::vector<ExploreData> edges_to_visit;
339 edges_to_visit.emplace_back(ExploreData{source, source});
340 data.emplace(source, VertexData{{source}});
342 while (not edges_to_visit.empty() && not visitor.shouldStop()) {
343 const auto edata = std::move(edges_to_visit.back());
344 edges_to_visit.pop_back();
345 const auto& v = edata.fanout;
346 auto& data_for_v = data.emplace(v, VertexData{{edata.driver}}).first->second;
350 || visitor.shouldIgnore(v)
351 || visitor.shouldIgnoreEdge(edata.driver, v)
353 visitor.onSkipped(v);
357 data_for_v.fanin.at(0) = edata.driver;
358 data_for_v.expanded =
true;
359 visitor.onExamine(v);
365 const auto insertion_point = edges_to_visit.size();
366 for (
const auto& fanout : graph.fanout(v)) {
367 const auto fanout_data_search = data.find(fanout);
369 not visitor.shouldIgnore(fanout)
370 && not visitor.shouldIgnoreEdge(v, fanout)
371 && ( fanout_data_search ==
end(data) || fanout_data_search->second.expanded )
373 visitor.onExamineEdge(v, fanout);
374 edges_to_visit.push_back(ExploreData{v, fanout});
376 visitor.onSkippedEdge(v, fanout);
381 std::reverse(
begin(edges_to_visit) + insertion_point,
end(edges_to_visit));