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 <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) {
}
void ibfs_subtree::reset(std::vector<node_id>& roots) {
labels_.assign(g_.num_nodes(), unassigned_);
pred_.assign(g_.num_nodes(), 0);
for (node_id n : roots) {
for (const auto& n : roots) {
labels_[n-1] = 0;
current_front_.push_back(n);
}
current_max_ = 0;
......@@ -23,13 +23,12 @@ void ibfs_subtree::add_node(label l, node_id node, node_id pred) {
assert(l == labels_[pred-1]+1);
labels_[node-1] = l;
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> front;
for (label i = 0; i < labels_.size(); ++i) {
if (labels_[i] == current_max_) front.push_back(i+1);
}
std::vector<node_id> front = current_front_;
current_front_.clear();
return front;
}
......@@ -48,7 +47,7 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) {
pred_[current-1] = 0;
assert(labels_[current-1] == labels_[pred-1]+1);
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;
}
......@@ -72,13 +71,13 @@ std::vector<node_id> ibfs_subtree::reduce_path(node_id leaf) {
std::vector<node_id> childs;
while (!parents.empty()) {
// 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)) {
if (pred_[potential_child-1] == parent) childs.push_back(potential_child);
}
}
// tries to adopt all found childs
for (node_id child : childs) {
for (auto& child : childs) {
bool is_front = false;
if (labels_[child-1] == current_max_) is_front = true;
label new_child_label = adopt(child);
......@@ -102,13 +101,16 @@ label ibfs_subtree::adopt(node_id orphan) {
label current_min = unassigned_;
node_id new_pred = 0;
for (node_id n : g_.get_adjacency(orphan)) {
if (labels_[n-1] == min-1 && !is_flow_edge(orphan, n)) {
const auto& adjacency = g_.get_adjacency(orphan);
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);
return min;
} else if (labels_[n-1]+1 < current_min
&& labels_[n-1] < max_adoption_label_
&& !is_flow_edge(orphan, n)) {
&& !flow_edges_[edge_ids[i]-1]) {
current_min = labels_[n-1]+1;
new_pred = n;
}
......@@ -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 @@
#include <gp-bnb/incremental_bfs.hpp>
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) {
assert(!sources.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);
for (node_id node : sources) {
for (const auto& node : sources) {
node_assignments_[node-1] = s_root;
}
for (node_id node : sinks) {
for (const auto& node : sinks) {
node_assignments_[node-1] = t_root;
}
flow_edges_.assign(g_.num_edges(), false);
flow_ = 0;
flow_edges_.clear();
s_.reset(sources);
t_.reset(sinks);
......@@ -32,10 +30,12 @@ void incremental_bfs::reset(std::vector<node_id>& sources, std::vector<node_id>&
void incremental_bfs::run() {
// increments the flow value to the number of pairwise neighbors of sources and sinks
for (node_id node : s_.get_front()) {
for (node_id neighbor : g_.get_adjacency(node)) {
if (node_assignments_[neighbor-1] == t_root) {
flow_edges_.push_back(g_.get_edge_id(node, neighbor));
for (const auto& node : s_.get_front()) {
const auto& adjacency = g_.get_adjacency(node);
const auto& edge_ids = g_.get_edge_ids(node);
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_++;
}
}
......@@ -57,7 +57,7 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
// creates a queue of candidate nodes for extending
std::queue<node_id> q;
for (node_id n : st.get_front()) {
for (auto& n : st.get_front()) {
q.push(n);
}
......@@ -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
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
for (node_id neighbor : g_.get_adjacency(node)) {
if (!is_flow_edge(node, neighbor)) {
for (node_id i = 0; i < adjacency.size(); ++i) {
node_id neighbor = adjacency[i];
if (!flow_edges_[edge_ids[i]-1]) {
// performs augmentation ...
if (-st.get_id() == node_assignments_[neighbor-1]) {
s_.add_flow_edge(node, neighbor);
t_.add_flow_edge(node, neighbor);
flow_edges_[edge_ids[i]-1] = true;
if (st.get_id() == subtree::s) {
if (s_.get_current_max() > 0) {
for (node_id n : s_.reduce_path(node)) {
......@@ -100,10 +102,10 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
}
// 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;
}
for (node_id n : t_.get_last_resid_orphans()) {
for (const auto& n : t_.get_last_resid_orphans()) {
node_assignments_[n-1] = none;
}
......@@ -125,11 +127,11 @@ bool incremental_bfs::grow(ibfs_subtree& st) {
return true;
}
bool incremental_bfs::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;
std::vector<unsigned int> incremental_bfs::get_flow_edges() const {
std::vector<unsigned int> result;
for (unsigned int i = 0; i < flow_edges_.size(); ++i) {
if (flow_edges_[i]) result.push_back(i+1);
}
return result;
}
......@@ -37,6 +37,14 @@ public:
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()
* @param Two Node ids (u, v)
* @return Edge id
......
......@@ -14,7 +14,7 @@ public:
/** @brief Initializes a subtree for incremental bfs
* @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
* @param List of new roots
......@@ -35,9 +35,6 @@ public:
*/
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();
label get_current_max() {
......@@ -64,10 +61,6 @@ public:
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:
int id_;
const graph& g_;
......@@ -76,16 +69,16 @@ private:
std::vector<label> labels_;
std::vector<node_id> pred_;
std::vector<node_id> current_front_;
label current_max_ = 0;
label max_adoption_label_ = 0;
std::vector<unsigned int>& flow_edges_;
std::vector<bool>& flow_edges_;
std::vector<node_id> last_resid_orphans_;
label adopt(node_id orphan);
bool is_flow_edge(node_id u, node_id v);
};
#endif /* IBFSSUBTREE_HPP_ */
......@@ -31,10 +31,7 @@ public:
/** @brief Returns edges with flow > 0
*/
std::vector<unsigned int> get_flow_edges() const {
return flow_edges_;
};
std::vector<unsigned int> get_flow_edges() const;
private:
enum subtree { s = -1, t = 1, none, s_root, t_root };
......@@ -47,11 +44,9 @@ private:
std::vector<subtree> node_assignments_;
unsigned int flow_ = 0;
std::vector<unsigned int> flow_edges_;
std::vector<bool> flow_edges_;
bool grow(ibfs_subtree& st);
bool is_flow_edge(node_id u, node_id v);
};
#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