Skip to content
Snippets Groups Projects
Commit e0048326 authored by Florian Heinrichs's avatar Florian Heinrichs
Browse files

forced assignments

parent aa444594
Branches
2 merge requests!11Forced assignments,!10Forced assignments
......@@ -26,45 +26,38 @@ void trail_state::pop() {
// solver implementation.
// --------------------------------------------------------------------------------------
solver::solver(graph& g, lb lb_algorithm) : graph_(g), partition_(partition{g}), lb_algorithm_(lb_algorithm), i_bfs_(incremental_bfs(g)) {
solver::solver(graph& g, lb lb_algorithm) : graph_(g), partition_(partition{g}), lb_algorithm_(lb_algorithm), i_bfs_(incremental_bfs(g)), gp_(greedy_packing(g, i_bfs_, true)) {
}
unsigned int solver::get_lower(){
std::vector<node_id> sources, sinks;
for(node_id node = 1; node <= graph_.num_nodes(); node++){
if(partition_.assigned_subgraph_of(node) == partition::sg_a)
sources.push_back(node);
else if(partition_.assigned_subgraph_of(node) == partition::sg_b)
sinks.push_back(node);
}
if (sources.empty() || sinks.empty()) {
if (sources_.empty() || sinks_.empty()) {
return partition_.current_objective();
}
if(lb_algorithm_ == lb::ek){
auto ek = edmonds_karp(graph_, sources, sinks);
auto ek = edmonds_karp(graph_, sources_, sinks_);
ek.run();
return ek.get_max_flow();
}
else if(lb_algorithm_ == lb::ibfs){
i_bfs_.reset(sources, sinks);
i_bfs_.reset(sources_, sinks_);
i_bfs_.run();
return i_bfs_.get_max_flow();
}
else if(lb_algorithm_ == lb::pr){
auto pr = push_relabel(graph_, sources, sinks);
auto pr = push_relabel(graph_, sources_, sinks_);
pr.run();
return pr.get_max_flow();
}
else if(lb_algorithm_ == lb::gp){
bool with_flow = true;
auto g_p = greedy_packing(graph_, sources, sinks, i_bfs_, with_flow);
g_p.run();
gp_.reset(sources_, sinks_);
gp_.run();
if(with_flow)
return g_p.get_max_flow();
return g_p.get_max_flow() + partition_.current_objective();
return gp_.get_max_flow();
return gp_.get_max_flow() + partition_.current_objective();
}
return partition_.current_objective();
}
......@@ -149,19 +142,44 @@ void solver::expand(node_id node, subgraph sg) {
// Search for an alternative BEFORE assigning the node.
// Because the node is not assigned, this calculation is easy.
subgraph alt;
bool fa = true;
visited_nodes++;
if(partition_.num_nodes_of(subgraph::sg_a) == 0 && partition_.num_nodes_of(subgraph::sg_b)){
if(partition_.num_nodes_of(subgraph::none) == graph_.num_nodes()){
alt = subgraph::none;
}else{
alt = next_possible_subgraph(node, static_cast<subgraph>(sg+1));
}
if(lb_algorithm_ == lb::gp && fa && !(sources_.empty() || sinks_.empty())){
auto x = gp_.forced_assignment(node);
if(x.second){
if(x.first > best_objective_){
sg = subgraph::sg_b;
alt = subgraph::none;
}
}
else{
if(!(x.first > best_objective_)){
sg = subgraph::sg_b;
}
//else{
//alt = subgraph::none;
//}
}
}
if(verbose) {
std::cerr << "Assign node " << node << " to subgraph " << sg << std::endl;
std::cerr << " Alternative " << alt << std::endl;
}
//std::cerr << "expand: " << node << " to: " << sg << std::endl;
partition_.assign_node(node, sg);
trail_.push_node(node, alt);
if(sg == subgraph::sg_a) sources_.push_back(node);
else sinks_.push_back(node);
}
void solver::backtrack() {
......@@ -173,6 +191,9 @@ void solver::backtrack() {
trail_.pop();
partition_.unassign_node(node);
if (sources_.back() == node) sources_.erase(sources_.begin() + sources_.size() - 1);
else if (sinks_.back() == node) sinks_.erase(sinks_.begin() + sinks_.size() - 1);
//std::cerr << "backtrack" << std::endl;
}
// Finds the next partition in which the given node can be placed.
......@@ -181,7 +202,7 @@ subgraph solver::next_possible_subgraph(node_id node, subgraph m) {
assert(partition_.assigned_subgraph_of(node) == subgraph::none);
subgraph sg = m;
while(sg <= 1){
if((partition_.num_nodes_of(sg) * 2) < graph_.num_nodes())
return sg;
......
......@@ -4,26 +4,37 @@
bool do_swap = true;
greedy_packing::greedy_packing(graph& g, std::vector<node_id> A, std::vector<node_id> B, incremental_bfs& ibfs, bool with_flow)
: graph_(g), a(A), b(B), i_bfs(ibfs), with_flow_(with_flow){
if(do_swap && A.size() > B.size()){
std::swap(a, b);
}
visited.resize(graph_.num_nodes() +1, false);
greedy_packing::greedy_packing(graph& g, incremental_bfs& ibfs, bool with_flow)
: graph_(g), i_bfs(ibfs), with_flow_(with_flow){
max_a = (graph_.num_nodes())/2;
};
void greedy_packing::reset(std::vector<node_id> a, std::vector<node_id> b){
a_ = a;
b_ = b;
x_.clear();
flow_edges.clear();
partitioning.clear();
in_part.assign(graph_.num_nodes()+1, -1);
a_count = 0;
visited.assign(graph_.num_nodes() +1, false);
if(do_swap && a.size() > b.size()){
std::swap(a_, b_);
}
}
//breadth-first-search to determine neighbors of B
void greedy_packing::bfs(){
for(node_id node : b){
for(node_id node : b_){
q.push(node);
visited[node] = true;
}
for(node_id node : a){
for(node_id node : a_){
visited[node] = true;
}
......@@ -37,7 +48,7 @@ void greedy_packing::bfs(){
if(visited[v] == false){
//falls nicht(mit_flow angegeben und knoten unter den flow_edges ist)dann push in zu x
if(!(with_flow_ && (std::find(flow_edges.begin(), flow_edges.end(), graph_.get_edge_id(node, v)) != flow_edges.end()))){
x.push_back(v);
x_.push_back(v);
visited[v] = true;
}
}
......@@ -49,29 +60,42 @@ void greedy_packing::bfs(){
};
void greedy_packing::run(){
flow_ = 0;
//std::cerr << "run gp " << std::endl;
flow_ = bound = 0;
if(with_flow_){
//get all flow edges and the flow
i_bfs.reset(a, b);
i_bfs.reset(a_, b_);
i_bfs.run();
flow_ = i_bfs.get_max_flow();
flow_edges = i_bfs.get_flow_edges();
}
a_count = a.size();
a_count = a_.size();
if(a_count >= max_a)
return;
//x per bfs konstruieren
bfs();
/*
for(auto n : a_){
std::cerr << " " << n;
}
std::cerr << std::endl;
for(auto n : b_){
std::cerr << " " << n;
}
std::cerr << std::endl;
*/
//P konstruieren
partitioning.resize(x.size());
partitioning.resize(x_.size());
//dafür für jeden nachbarn von B einen eigenen Block
for(unsigned int i = 0; i <x.size(); i++){
partitioning[i].push_back(x[i]);
for(unsigned int i = 0; i <x_.size(); i++){
partitioning[i].push_back(x_[i]);
in_part[x_[i]] = i;
}
//dann jeweils kleinsten block um einen nachbarn erweitern
......@@ -79,12 +103,13 @@ void greedy_packing::run(){
bool found_new_element = true;
while (found_new_element) {
found_new_element = false;
for (std::vector<node_id> partition : partitioning) {
node_id v = partition.back();
for (unsigned int i = 0; i < partitioning.size(); i++){
node_id v = partitioning[i].back();
for (node_id node : graph_.get_adjacency(v)) {
if (!visited[node]) {
if(!(with_flow_ && (std::find(flow_edges.begin(), flow_edges.end(), graph_.get_edge_id(node, v)) != flow_edges.end()))){
partition.push_back(node);
partitioning[i].push_back(node);
in_part[node] = i;
visited[node] = true;
found_new_element = true;
break;
......@@ -112,7 +137,7 @@ void greedy_packing::run(){
// packe greedy (erst hier wird flow erhöht)
for (std::vector<node_id> partition : partitioning) {
flow_++;
bound++;
a_count += partition.size();
if (a_count >= max_a){
return;
......@@ -122,5 +147,80 @@ void greedy_packing::run(){
return;
};
std::pair<unsigned int, bool> greedy_packing::forced_assignment(node_id node){
unsigned int new_bound, x_v, p, index;
bool case1;
x_v = p = 0;
a_count = a_.size();
/*
std::cerr << visited.size() << std::endl;
for(int i = 0; i < visited.size(); i++){
std::cerr << i << " : " << visited[i] << " ";
}
std::cerr << " node: " << node << std::endl;
for(int i = 0; i < in_part.size(); i++){
std::cerr << i << " : " << in_part[i] << " ";
}
std::cerr << std::endl;
*/
//fall 1: node in nicht trivialem block
if(visited[node]){
//für jeden nachbarn von v
for(node_id u : graph_.get_adjacency(node)){
if(in_part[u] != -1){
//falls er in einem block liegt erhöhe x_v
x_v++;
index = in_part[u];
//dieser block ist nun nicht trivial (jeden knoten nichtmehr
//als visited markieren)
for(node_id v : partitioning[in_part[u]]){
//std::cerr << v << " ";
visited[v] = false;
in_part[v] = -1;
}
partitioning[index].clear();
}
}
//neues eingeschränktes packing-bound berechnen
std::sort(partitioning.begin(), partitioning.end(), [](std::vector<node_id> a, std::vector<node_id> b) {
return a.size() > b.size();
});
// behandle von B aus unnerreichbare Knoten
for (node_id i = 1; i <= graph_.num_nodes(); i++) {
if (!visited[i]) {
a_count++;
if (a_count >= max_a){
break;
}
}
}
// packe greedy (erst hier wird flow erhöht)
for (std::vector<node_id> partition : partitioning) {
p++;
a_count += partition.size();
if (a_count >= max_a){
break;
}
}
new_bound = flow_ + x_v + p;
case1 = true;
}
else{
//fall2: v in trivialem block
//bound erhöht sich um anzahl der nachbarn von v
new_bound = flow_ + bound + graph_.get_adjacency(node).size();
case1 = false;
}
return std::make_pair(new_bound, case1);
}
......@@ -90,10 +90,12 @@ private:
lb lb_algorithm_;
incremental_bfs i_bfs_;
greedy_packing gp_;
// Value of best solution seen so far.
std::vector<subgraph> best_solution_;
unsigned int best_objective_ = 0;
std::vector<node_id> sources_, sinks_;
};
} // namespace gp_bnb
......
......@@ -5,17 +5,41 @@
#include <vector>
#include <gp-bnb/graph.hpp>
#include <gp-bnb/incremental_bfs.hpp>
#include <iostream>
class greedy_packing{
public:
greedy_packing(graph& g, std::vector<node_id> a, std::vector<node_id> b, incremental_bfs& ibfs, bool with_flow);
/** @brief Initializes a greedy-packing instance
* @param Graph to be partitioned
* @param iBFS instance to be used
* @param bool, if bound with flow should be used
*/
greedy_packing(graph& g, incremental_bfs& ibfs, bool with_flow);
/** @brief executes the GP algortihm
*/
void run();
/** @brief resets the already partitioned sets a and b
* @param vector of nodes in set a
* @param vector of nodes in set b
*/
void reset(std::vector<node_id> a, std::vector<node_id> b);
/** @brief executes the forced assignments algorithm
* @param node for which we decide the next branch
* @return pair of bool and int where bool represents if node
* was in trivial block or not
* int: new upper bound if we would branch
*/
std::pair<unsigned int, bool> forced_assignment(node_id node);
/** @brief return the bound after execution
* @return packing-bound
*/
int get_max_flow() const{
return flow_;
return flow_ + bound;
};
private:
......@@ -26,7 +50,8 @@ private:
//partial partition into blocks a and b
//x is block with the neighbors of B
std::vector<node_id> a, b, x;
std::vector<node_id> a_, b_, x_;
std::vector<int> in_part;
incremental_bfs& i_bfs;
......@@ -40,7 +65,7 @@ private:
std::vector<bool> visited;
unsigned int a_count, max_a, flow_;
unsigned int a_count, max_a, flow_, bound;
};
#endif /* GREEDY_PACKING_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