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

Refactor bnb

parent d49018a6
Branches
No related merge requests found
......@@ -7,46 +7,11 @@ static constexpr bool verbose = false;
namespace gp_bnb {
// --------------------------------------------------------------------------------------
// assignment_state implementation.
// --------------------------------------------------------------------------------------
void assignment_state::resize_nodes(size_t count) {
assigned_partition_.resize(count, illegal_partition);
//fill_state_.resize(count);
}
void assignment_state::assign(vertex_id node, partition_index p, std::vector<unsigned int> neighbors) {
assert(assigned_partition_[node] == illegal_partition);
assert(p >= 0);
assigned_partition_[node] = p;
//for each neighbor of node in other partitions: current_objective++
for(auto neighbor: neighbors){
if(assigned_partition_[neighbor] == (p xor 1))
current_objective_++;
}
node_count[p]++;
}
void assignment_state::unassign(vertex_id node, std::vector<unsigned int> neighbors) {
assert(assigned_partition_[node] != illegal_partition);
auto p = assigned_partition_[node];
assigned_partition_[node] = illegal_partition;
//for each neighbor of node in other partitions: current_objective--
for(vertex_id neighbor : neighbors){
if(assigned_partition_[neighbor] == (p xor 1))
current_objective_--;
}
node_count[p]--;
}
// --------------------------------------------------------------------------------------
// trail_state implementation.
// --------------------------------------------------------------------------------------
void trail_state::push_node(vertex_id node, partition_index alt) {
void trail_state::push_node(vertex_id node, subgraph alt) {
stack_.push_back({node, alt});
}
......@@ -58,14 +23,7 @@ void trail_state::pop() {
// solver implementation.
// --------------------------------------------------------------------------------------
void solver::resize_nodes(size_t count) {
//nodes_.resize_nodes(count);
assignment_.resize_nodes(count);
}
void solver::define_graph(graph& g){
nodes_ = g;
solver::solver(graph& g) : nodes_(g), partition_(partition{g}) {
}
void solver::solve() {
......@@ -79,13 +37,13 @@ void solver::solve() {
while(true) {
//falls current sol schlechter als obere grenze:
//zähle schritte bis zur nächsten alternative und
if(assignment_.current_objective() >= best_objective_) {
if(partition_.current_objective() >= best_objective_) {
int i = trail_.length() - 1;
while(true) {
if(i < 0)
return;
// Only backtrack to assignments that have an alternative.
if(trail_.alternative_at(i) != illegal_partition)
if(trail_.alternative_at(i) != subgraph::none)
break;
i--;
}
......@@ -103,30 +61,30 @@ void solver::solve() {
// Memorize the new solution.
best_solution_.resize(nodes_.num_vertices());
for(vertex_id node = 0; node < nodes_.num_vertices(); node++){
best_solution_[node] = assignment_.assigned_partition_of(node);
best_solution_[node] = partition_.assigned_subgraph_of(node);
}
best_objective_ = assignment_.current_objective();
best_objective_ = partition_.current_objective();
std::cerr << "Solution improved to k = " << best_objective_ << std::endl;
}else{
//sonst expandiere suchbaum weiter
int node = trail_.length();
expand(node, next_possible_partition(node, 0));
expand(node, next_possible_subgraph(node, subgraph::sg_a));
}
}
}
void solver::expand(vertex_id node, partition_index p) {
void solver::expand(vertex_id node, subgraph sg) {
// Search for an alternative BEFORE assigning the node.
// Because the node is not assigned, this calculation is easy.
auto alt = next_possible_partition(node, p + 1);
auto alt = next_possible_subgraph(node, static_cast<subgraph>(-sg));
if(verbose) {
std::cerr << "Assign node " << node << " to partition " << p << std::endl;
std::cerr << "Assign node " << node << " to subgraph " << sg << std::endl;
std::cerr << " Alternative " << alt << std::endl;
}
std::vector<unsigned int> neighbors = nodes_.get_adjacency(node);
assignment_.assign(node, p, neighbors);
partition_.assign_vertex(node, sg);
trail_.push_node(node, alt);
}
......@@ -138,23 +96,23 @@ void solver::backtrack() {
std::cout << "Unassign node " << node << std::endl;
trail_.pop();
assignment_.unassign(node, nodes_.get_adjacency(node));
partition_.unassign_vertex(node);
}
// Finds the next partition in which the given node can be placed.
partition_index solver::next_possible_partition(vertex_id node, partition_index m) {
subgraph solver::next_possible_subgraph(vertex_id node, subgraph m) {
// This function is only correct if the node is not assigned yet.
assert(assignment_.assigned_partition_of(node) == illegal_partition);
assert(partition_.assigned_subgraph_of(node) == subgraph::none);
// partition_count_: Index+1 of last partition that we will try.
partition_index p = m;
subgraph sg = m;
//falls in einer partition schon die hälfte der knoten: nicht als alt wählen
if((assignment_.node_count_of(p) * 2) < nodes_.num_vertices()){
return p;
if((partition_.num_vertices_of(sg) * 2) < nodes_.num_vertices()){
return sg;
}
else{
return (p xor 1);
return subgraph::none;
}
}
......
......@@ -5,53 +5,11 @@
#pragma once
#include <gp-bnb/graph.hpp>
#include <gp-bnb/partition.hpp>
namespace gp_bnb {
using partition_index = unsigned int;
// We use (-1) as an indicator for non-existing (or otherwise illegal) partition.
// Note that because this is cast to unsigned int, it becomes 0xFFFF... (i.e., the highest
// possible number). We do not use zero as that is a valid partition index.
static constexpr partition_index illegal_partition = static_cast<partition_index>(-1);
// Represents a partial assignment.
struct assignment_state {
// Change the number of existing nodes.
void resize_nodes(size_t count);
// Assigns an node to a partition.
void assign(vertex_id node, partition_index p, std::vector<unsigned int> neighbors);
// Unassigns an node from its partition.
void unassign(vertex_id node, std::vector<unsigned int> neigbors);
partition_index assigned_partition_of(vertex_id node) const {
return assigned_partition_[node];
}
unsigned int node_count_of(partition_index p) const {
return node_count[p];
}
int current_objective() const {
return current_objective_;
}
private:
// For each node: index of the partition it is placed into.
std::vector<partition_index> assigned_partition_;
// Value of objective function for current partial solution.
int current_objective_ = 0;
//for each partition: fill count
std::vector<unsigned int> node_count;
//number of partitions
int partition_count_ = 2;
};
using subgraph = partition::subgraph;
// Represents the current path throught the search tree.
struct trail_state {
......@@ -60,18 +18,18 @@ private:
// Index of node that is assigned at a certain level of the search tree.
vertex_id node;
// Next alternative (or illegal_partition if no alternative exists).
partition_index alt;
// Next alternative (or none if no alternative exists).
subgraph alt;
};
public:
// Extends the current path by adding another node.
void push_node(vertex_id node, partition_index alt);
void push_node(vertex_id node, subgraph alt);
// Reduces the current path by removing the last node.
void pop();
int length() const {
unsigned int length() const {
return stack_.size();
}
......@@ -79,7 +37,7 @@ public:
return stack_[n].node;
}
partition_index alternative_at(size_t n) const {
subgraph alternative_at(size_t n) const {
return stack_[n].alt;
}
......@@ -90,24 +48,22 @@ private:
// Main solver structure. Puts everything together.
struct solver {
// Constructor
solver(graph& g);
// Read-only access to the nodes.
const graph &nodes() const {
return nodes_;
}
// Read-only access to the optimal solution.
const std::vector<partition_index> &best_solution() const {
const std::vector<subgraph> &best_solution() const {
return best_solution_;
}
// Change the number of existing nodes.
void resize_nodes(size_t count);
// Expand a search tree node, i.e., assigns an node to a partition and update all data structures.
void expand(vertex_id node, partition_index p);
//associates graph with the solver
void define_graph(graph& g);
void expand(vertex_id node, subgraph sg);
// Performs backtracking after the solver ran into a dead end,
// i.e., the current branch has been pruned.
......@@ -117,15 +73,16 @@ struct solver {
void solve();
private:
partition_index next_possible_partition(vertex_id node, partition_index p);
subgraph next_possible_subgraph(vertex_id node, subgraph sg);
graph nodes_;
assignment_state assignment_;
partition partition_;
trail_state trail_;
// Value of best solution seen so far.
std::vector<partition_index> best_solution_;
int best_objective_ = 0;
std::vector<subgraph> best_solution_;
unsigned int best_objective_ = 0;
};
} // namespace gp_bnb
......
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