Skip to content
Snippets Groups Projects
Commit 8644dfc6 authored by p-hamann's avatar p-hamann
Browse files

Optimize ibfs

parent 0e7ef525
Branches
1 merge request!9Perf optimization
#include <gp-bnb/ibfs_subtree.hpp> #include <gp-bnb/ibfs_subtree.hpp>
#include <cassert> #include <cassert>
#include <iostream>
ibfs_subtree::ibfs_subtree(int id, const graph& g, std::vector<unsigned int>& flow_edges) : id_(id), ibfs_subtree::ibfs_subtree(int id, const graph& g, std::vector<bool>& flow_edges) : id_(id),
g_(g), unassigned_(g.num_nodes()), labels_(std::vector<label>(g.num_nodes())), pred_(std::vector<node_id>(g.num_nodes())), flow_edges_(flow_edges) { g_(g), unassigned_(g.num_nodes()), labels_(std::vector<label>(g.num_nodes())), pred_(std::vector<node_id>(g.num_nodes())), flow_edges_(flow_edges) {
} }
void ibfs_subtree::reset(std::vector<node_id>& roots) { void ibfs_subtree::reset(std::vector<node_id>& roots) {
labels_.assign(g_.num_nodes(), unassigned_); labels_.assign(g_.num_nodes(), unassigned_);
pred_.assign(g_.num_nodes(), 0); pred_.assign(g_.num_nodes(), 0);
for (node_id n : roots) { for (const auto& n : roots) {
labels_[n-1] = 0; labels_[n-1] = 0;
current_front_.push_back(n);
} }
current_max_ = 0; current_max_ = 0;
...@@ -23,13 +23,12 @@ void ibfs_subtree::add_node(label l, node_id node, node_id pred) { ...@@ -23,13 +23,12 @@ void ibfs_subtree::add_node(label l, node_id node, node_id pred) {
assert(l == labels_[pred-1]+1); assert(l == labels_[pred-1]+1);
labels_[node-1] = l; labels_[node-1] = l;
pred_[node-1] = pred; pred_[node-1] = pred;
if (l == max_adoption_label_) current_front_.push_back(node);
} }
std::vector<node_id> ibfs_subtree::get_front() { std::vector<node_id> ibfs_subtree::get_front() {
std::vector<node_id> front; std::vector<node_id> front = current_front_;
for (label i = 0; i < labels_.size(); ++i) { current_front_.clear();
if (labels_[i] == current_max_) front.push_back(i+1);
}
return front; return front;
} }
...@@ -48,7 +47,7 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) { ...@@ -48,7 +47,7 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) {
pred_[current-1] = 0; pred_[current-1] = 0;
assert(labels_[current-1] == labels_[pred-1]+1); assert(labels_[current-1] == labels_[pred-1]+1);
flow_nodes.push_back(current); flow_nodes.push_back(current);
flow_edges_.push_back(g_.get_edge_id(current, pred)); flow_edges_[g_.get_edge_id(current, pred)-1] = true;
current = pred; current = pred;
} }
...@@ -72,13 +71,13 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) { ...@@ -72,13 +71,13 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) {
std::vector<node_id> childs; std::vector<node_id> childs;
while (!parents.empty()) { while (!parents.empty()) {
// searches all childs of the current parents // searches all childs of the current parents
for (node_id parent : parents) { for (auto& parent : parents) {
for (node_id potential_child : g_.get_adjacency(parent)) { for (node_id potential_child : g_.get_adjacency(parent)) {
if (pred_[potential_child-1] == parent) childs.push_back(potential_child); if (pred_[potential_child-1] == parent) childs.push_back(potential_child);
} }
} }
// tries to adopt all found childs // tries to adopt all found childs
for (node_id child : childs) { for (auto& child : childs) {
bool is_front = false; bool is_front = false;
if (labels_[child-1] == current_max_) is_front = true; if (labels_[child-1] == current_max_) is_front = true;
label new_child_label = adopt(child); label new_child_label = adopt(child);
...@@ -102,13 +101,16 @@ label ibfs_subtree::adopt(node_id orphan) { ...@@ -102,13 +101,16 @@ label ibfs_subtree::adopt(node_id orphan) {
label current_min = unassigned_; label current_min = unassigned_;
node_id new_pred = 0; node_id new_pred = 0;
for (node_id n : g_.get_adjacency(orphan)) { const auto& adjacency = g_.get_adjacency(orphan);
if (labels_[n-1] == min-1 && !is_flow_edge(orphan, n)) { const auto& edge_ids = g_.get_edge_ids(orphan);
for (node_id i = 0; i < adjacency.size(); ++i) {
node_id n = adjacency[i];
if (labels_[n-1] == min-1 && !flow_edges_[edge_ids[i]-1]) {
add_node(min, orphan, n); add_node(min, orphan, n);
return min; return min;
} else if (labels_[n-1]+1 < current_min } else if (labels_[n-1]+1 < current_min
&& labels_[n-1] < max_adoption_label_ && labels_[n-1] < max_adoption_label_
&& !is_flow_edge(orphan, n)) { && !flow_edges_[edge_ids[i]-1]) {
current_min = labels_[n-1]+1; current_min = labels_[n-1]+1;
new_pred = n; new_pred = n;
} }
...@@ -123,11 +125,3 @@ label ibfs_subtree::adopt(node_id orphan) { ...@@ -123,11 +125,3 @@ label ibfs_subtree::adopt(node_id orphan) {
} }
} }
bool ibfs_subtree::is_flow_edge(node_id u, node_id v) {
unsigned int eid = g_.get_edge_id(u, v);
for (unsigned int e : flow_edges_) {
if (e == eid) return true;
}
return false;
}
...@@ -5,25 +5,23 @@ ...@@ -5,25 +5,23 @@
#include <gp-bnb/incremental_bfs.hpp> #include <gp-bnb/incremental_bfs.hpp>
incremental_bfs::incremental_bfs(const graph& g) incremental_bfs::incremental_bfs(const graph& g)
: g_(g), s_(ibfs_subtree(subtree::s, g, flow_edges_)), t_(ibfs_subtree(subtree::t, g, flow_edges_)) { : g_(g), s_(ibfs_subtree(subtree::s, g, flow_edges_)), t_(ibfs_subtree(subtree::t, g, flow_edges_)), flow_edges_(std::vector<bool> (g.num_edges())) {
} }
void incremental_bfs::reset(std::vector<node_id>& sources, std::vector<node_id>& sinks) { void incremental_bfs::reset(std::vector<node_id>& sources, std::vector<node_id>& sinks) {
assert(!sources.empty()); assert(!sources.empty());
assert(!sinks.empty()); assert(!sinks.empty());
assert(sources.size() <= g_.num_nodes()/2+1);
assert(sinks.size() <= g_.num_nodes()/2+1);
node_assignments_.assign(g_.num_nodes(), none); node_assignments_.assign(g_.num_nodes(), none);
for (node_id node : sources) { for (const auto& node : sources) {
node_assignments_[node-1] = s_root; node_assignments_[node-1] = s_root;
} }
for (node_id node : sinks) { for (const auto& node : sinks) {
node_assignments_[node-1] = t_root; node_assignments_[node-1] = t_root;
} }
flow_edges_.assign(g_.num_edges(), false);
flow_ = 0; flow_ = 0;
flow_edges_.clear();
s_.reset(sources); s_.reset(sources);
t_.reset(sinks); t_.reset(sinks);
...@@ -32,10 +30,12 @@ void incremental_bfs::reset(std::vector<node_id>& sources, std::vector<node_id>& ...@@ -32,10 +30,12 @@ void incremental_bfs::reset(std::vector<node_id>& sources, std::vector<node_id>&
void incremental_bfs::run() { void incremental_bfs::run() {
// increments the flow value to the number of pairwise neighbors of sources and sinks // increments the flow value to the number of pairwise neighbors of sources and sinks
for (node_id node : s_.get_front()) { for (const auto& node : s_.get_front()) {
for (node_id neighbor : g_.get_adjacency(node)) { const auto& adjacency = g_.get_adjacency(node);
if (node_assignments_[neighbor-1] == t_root) { const auto& edge_ids = g_.get_edge_ids(node);
flow_edges_.push_back(g_.get_edge_id(node, neighbor)); for (node_id i = 0; i < adjacency.size(); ++i) {
if (node_assignments_[adjacency[i]-1] == t_root) {
flow_edges_[edge_ids[i]-1] = true;
flow_++; flow_++;
} }
} }
...@@ -57,7 +57,7 @@ bool incremental_bfs::grow(ibfs_subtree& st) { ...@@ -57,7 +57,7 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
// creates a queue of candidate nodes for extending // creates a queue of candidate nodes for extending
std::queue<node_id> q; std::queue<node_id> q;
for (node_id n : st.get_front()) { for (auto& n : st.get_front()) {
q.push(n); q.push(n);
} }
...@@ -70,13 +70,15 @@ bool incremental_bfs::grow(ibfs_subtree& st) { ...@@ -70,13 +70,15 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
// takes into account the case that node in this grow was already orphaned and not re-inserted in the front // takes into account the case that node in this grow was already orphaned and not re-inserted in the front
if (!st.is_front_element(node)) continue; if (!st.is_front_element(node)) continue;
const auto& adjacency = g_.get_adjacency(node);
const auto& edge_ids = g_.get_edge_ids(node);
// searches for neighbors of candidate nodes // searches for neighbors of candidate nodes
for (node_id neighbor : g_.get_adjacency(node)) { for (node_id i = 0; i < adjacency.size(); ++i) {
if (!is_flow_edge(node, neighbor)) { node_id neighbor = adjacency[i];
if (!flow_edges_[edge_ids[i]-1]) {
// performs augmentation ... // performs augmentation ...
if (-st.get_id() == node_assignments_[neighbor-1]) { if (-st.get_id() == node_assignments_[neighbor-1]) {
s_.add_flow_edge(node, neighbor); flow_edges_[edge_ids[i]-1] = true;
t_.add_flow_edge(node, neighbor);
if (st.get_id() == subtree::s) { if (st.get_id() == subtree::s) {
if (s_.get_current_max() > 0) { if (s_.get_current_max() > 0) {
for (node_id n : s_.reduce_path(node)) { for (node_id n : s_.reduce_path(node)) {
...@@ -100,10 +102,10 @@ bool incremental_bfs::grow(ibfs_subtree& st) { ...@@ -100,10 +102,10 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
} }
// orphan nodes can be inserted again // orphan nodes can be inserted again
for (node_id n : s_.get_last_resid_orphans()) { for (const auto& n : s_.get_last_resid_orphans()) {
node_assignments_[n-1] = none; node_assignments_[n-1] = none;
} }
for (node_id n : t_.get_last_resid_orphans()) { for (const auto& n : t_.get_last_resid_orphans()) {
node_assignments_[n-1] = none; node_assignments_[n-1] = none;
} }
...@@ -125,11 +127,11 @@ bool incremental_bfs::grow(ibfs_subtree& st) { ...@@ -125,11 +127,11 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
return true; return true;
} }
bool incremental_bfs::is_flow_edge(node_id u, node_id v) { std::vector<unsigned int> incremental_bfs::get_flow_edges() const {
unsigned int eid = g_.get_edge_id(u, v); std::vector<unsigned int> result;
for (unsigned int i = 0; i < flow_edges_.size(); ++i) {
for (unsigned int e : flow_edges_) { if (flow_edges_[i]) result.push_back(i+1);
if (e == eid) return true; }
} return result;
return false;
} }
...@@ -37,6 +37,14 @@ public: ...@@ -37,6 +37,14 @@ public:
return adjacency_list_[v-1]; return adjacency_list_[v-1];
}; };
/** @brief Provides access to the edge ids of a node
* @param Node Id
* @return Edge ids of the node
*/
const std::vector<unsigned int>& get_edge_ids(node_id v) const {
return indexed_edges_[v-1];
};
/** @brief Returns the id of an edge after calling index_edges() /** @brief Returns the id of an edge after calling index_edges()
* @param Two Node ids (u, v) * @param Two Node ids (u, v)
* @return Edge id * @return Edge id
......
...@@ -14,7 +14,7 @@ public: ...@@ -14,7 +14,7 @@ public:
/** @brief Initializes a subtree for incremental bfs /** @brief Initializes a subtree for incremental bfs
* @param List of roots (sources or sinks) * @param List of roots (sources or sinks)
*/ */
ibfs_subtree(int id, const graph& g, std::vector<unsigned int>& flow_edges); ibfs_subtree(int id, const graph& g, std::vector<bool>& flow_edges);
/** @brief Resets the subtree with new roots /** @brief Resets the subtree with new roots
* @param List of new roots * @param List of new roots
...@@ -35,9 +35,6 @@ public: ...@@ -35,9 +35,6 @@ public:
*/ */
void add_node(label l, node_id node, node_id pred); void add_node(label l, node_id node, node_id pred);
/** @brief Provides access to the nodes with the highest label
* @return Hash-Set of nodes with highest label
*/
std::vector<node_id> get_front(); std::vector<node_id> get_front();
label get_current_max() { label get_current_max() {
...@@ -64,10 +61,6 @@ public: ...@@ -64,10 +61,6 @@ public:
return labels_[node-1] == current_max_; return labels_[node-1] == current_max_;
}; };
void add_flow_edge(node_id u, node_id v) {
flow_edges_.push_back(g_.get_edge_id(u, v));
};
private: private:
int id_; int id_;
const graph& g_; const graph& g_;
...@@ -76,16 +69,16 @@ private: ...@@ -76,16 +69,16 @@ private:
std::vector<label> labels_; std::vector<label> labels_;
std::vector<node_id> pred_; std::vector<node_id> pred_;
std::vector<node_id> current_front_;
label current_max_ = 0; label current_max_ = 0;
label max_adoption_label_ = 0; label max_adoption_label_ = 0;
std::vector<unsigned int>& flow_edges_; std::vector<bool>& flow_edges_;
std::vector<node_id> last_resid_orphans_; std::vector<node_id> last_resid_orphans_;
label adopt(node_id orphan); label adopt(node_id orphan);
bool is_flow_edge(node_id u, node_id v);
}; };
#endif /* IBFSSUBTREE_HPP_ */ #endif /* IBFSSUBTREE_HPP_ */
...@@ -31,10 +31,7 @@ public: ...@@ -31,10 +31,7 @@ public:
/** @brief Returns edges with flow > 0 /** @brief Returns edges with flow > 0
*/ */
std::vector<unsigned int> get_flow_edges() const { std::vector<unsigned int> get_flow_edges() const;
return flow_edges_;
};
private: private:
enum subtree { s = -1, t = 1, none, s_root, t_root }; enum subtree { s = -1, t = 1, none, s_root, t_root };
...@@ -47,11 +44,9 @@ private: ...@@ -47,11 +44,9 @@ private:
std::vector<subtree> node_assignments_; std::vector<subtree> node_assignments_;
unsigned int flow_ = 0; unsigned int flow_ = 0;
std::vector<unsigned int> flow_edges_; std::vector<bool> flow_edges_;
bool grow(ibfs_subtree& st); bool grow(ibfs_subtree& st);
bool is_flow_edge(node_id u, node_id v);
}; };
#endif /* INCREMENTALBFS_H_ */ #endif /* INCREMENTALBFS_H_ */
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment