Newer
Older
#include <cassert>
#include <iostream>
#include <time.h>
static constexpr bool verbose = false;
int visited_nodes = 0;
namespace gp_bnb {
// --------------------------------------------------------------------------------------
// trail_state implementation.
// --------------------------------------------------------------------------------------
void trail_state::push_node(node_id node, subgraph alt) {
stack_.push_back({node, alt});
}
void trail_state::pop() {
stack_.pop_back();
}
// --------------------------------------------------------------------------------------
// solver implementation.
// --------------------------------------------------------------------------------------
solver::solver(graph& g, lb lb_algorithm) : graph_(g), partition_(partition{g}), lb_algorithm_(lb_algorithm), i_bfs_(incremental_bfs(g)) {
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()) {
return partition_.current_objective();
}
auto ek = edmonds_karp(graph_, sources, sinks);
ek.run();
return ek.get_max_flow();
i_bfs_.reset(sources, sinks);
i_bfs_.run();
return i_bfs_.get_max_flow();
auto pr = push_relabel(graph_, sources, sinks);
pr.run();
return pr.get_max_flow();
bool with_flow = true;
auto g_p = greedy_packing(graph_, sources, sinks, i_bfs_, with_flow);
if(with_flow)
return g_p.get_max_flow();
return g_p.get_max_flow() + partition_.current_objective();
return partition_.current_objective();

Florian Heinrichs
committed
//anfangs lower bound?
clock_t begin = clock();
// builds a vector of node ids with descending degree
for (node_id i = 1; i <= graph_.num_nodes(); ++i) {
std::sort(sorted_nodes.begin(), sorted_nodes.end(), [this](node_id a, node_id b) {
return graph_.get_adjacency(a).size() > graph_.get_adjacency(b).size();
});

Florian Heinrichs
committed
//falls current sol schlechter als bisher beste lösung:
//zähle schritte bis zur nächsten alternative und

Florian Heinrichs
committed
if(get_lower() >= best_objective_) {
int i = trail_.length() - 1;
while(true) {
if(i < 0){
std::cerr << "visited nodes: " << visited_nodes << std::endl;
// Only backtrack to assignments that have an alternative.
break;
i--;
}
auto node = trail_.node_at(i);
auto alt = trail_.alternative_at(i);
//backtracke soviele schritte und

Florian Heinrichs
committed
while((int)trail_.length() > i){
backtrack();
}
//wende dann die entsprechende alternative an
expand(node, alt);
//falls wir an einem blatt im suchbaum sind
// Memorize the new solution.
best_solution_.resize(graph_.num_nodes());
for(node_id node = 0; node < graph_.num_nodes(); node++){

Florian Heinrichs
committed
best_solution_[node] = partition_.assigned_subgraph_of(node+1);
clock_t end = clock();
double time = (double)(end -begin) / CLOCKS_PER_SEC;
std::cerr << "Solution improved to k = " << best_objective_ << " after : " << time << " seconds and: " << visited_nodes << " besuchten knoten" << std::endl;
}else{
//sonst expandiere suchbaum weiter
int next_node;
//sort after degree
/*int node_deg = 0;
for(node_id node = 1; node <= graph_.num_nodes(); node++){
if(partition_.assigned_subgraph_of(node) == subgraph::none){
if(graph_.get_adjacency(node).size() > node_deg){
node_deg = graph_.get_adjacency(node).size();
next_node = node;
}
}
}
*/
expand(next_node, next_possible_subgraph(next_node, subgraph::sg_a));

Florian Heinrichs
committed
assert(sg == subgraph::sg_a || sg == subgraph::sg_b);
// Search for an alternative BEFORE assigning the node.
// Because the node is not assigned, this calculation is easy.

Florian Heinrichs
committed
subgraph alt;
visited_nodes++;

Florian Heinrichs
committed
if(partition_.num_nodes_of(subgraph::sg_a) == 0 && partition_.num_nodes_of(subgraph::sg_b)){
alt = subgraph::none;
}else{
alt = next_possible_subgraph(node, static_cast<subgraph>(sg+1));

Florian Heinrichs
committed
}
std::cerr << "Assign node " << node << " to subgraph " << sg << std::endl;
std::cerr << " Alternative " << alt << std::endl;
}
trail_.push_node(node, alt);
}
void solver::backtrack() {
assert(trail_.length());
auto node = trail_.node_at(trail_.length() - 1);
if(verbose)
std::cout << "Unassign node " << node << std::endl;
}
// Finds the next partition in which the given node can be placed.
subgraph solver::next_possible_subgraph(node_id node, subgraph m) {
// This function is only correct if the node is not assigned yet.
assert(partition_.assigned_subgraph_of(node) == subgraph::none);

Florian Heinrichs
committed
while(sg <= 1){
if((partition_.num_nodes_of(sg) * 2) < graph_.num_nodes())
return sg;
else
{

Florian Heinrichs
committed
}

Florian Heinrichs
committed
return subgraph::none;