Heuristics included

This commit is contained in:
Armin_Sadeghi
2015-04-01 04:17:13 -04:00
parent 7a65894692
commit f5e15f1385
8 changed files with 923 additions and 83 deletions

View File

@@ -10,7 +10,7 @@
#include "gtsp-subtour.h"
#include "gtsp-comb.h"
int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost);
int large_neighborhood_search(struct Tour *tour, struct GTSP *data, int *tour_cost);
int build_edge_map(struct GTSP *gtsp, int *edge_map);
@@ -497,16 +497,34 @@ int GTSP_solution_found(struct BNC *bnc, struct GTSP *data, double *x)
UNUSED(bnc);
int rval = 0;
int tour_cost;
char filename[100];
double *best_val = &bnc->best_obj_val;
struct Tour* tour;
tour = (struct Tour*) malloc(data->cluster_count*sizeof(struct Tour));
sprintf(filename, "tmp/gtsp-m%d-n%d-s%d.out", data->cluster_count,
data->graph->node_count, SEED);
log_info("Writting solution to file %s\n", filename);
rval = GTSP_write_solution(data, filename, x);
abort_if(rval, "GTSP_write_solution failed");
rval = build_tour_from_x(data,tour,x);
abort_if(rval, "build_tour_from_x failed");
rval = large_neighborhood_search(tour, data, &tour_cost);
abort_if(rval, "large_neighborhood_search failed");
if(tour_cost + LP_EPSILON < *best_val){
log_info("Local search improve the integral solution\n");
log_info(" obj val = %f\n",*best_val );
log_info(" after LNS = %d\n",tour_cost );
*best_val = tour_cost;
}
log_info("Checking solution...\n");
rval = GTSP_check_solution(data, x);
abort_if(rval, "GTSP_check_solution failed");
@@ -807,7 +825,7 @@ int GTSP_main(int argc, char **argv)
return rval;
}
int build_x_from_tour(struct GTSP *data, int *tour, double *x)
int build_x_from_tour(struct GTSP *data, struct Tour *tour, double *x)
{
int rval = 0;
int *edge_map = 0;
@@ -824,10 +842,14 @@ int build_x_from_tour(struct GTSP *data, int *tour, double *x)
for (int i = 0; i < node_count + edge_count; i++)
x[i] = 0.0;
int next_vertex = tour[0].next;
int current_vertex = tour[0].vertex;
for (int i = 0; i < data->cluster_count; i++)
{
int from = tour[i];
int to = tour[i + 1];
int from = current_vertex;
int to = tour[next_vertex].vertex;
current_vertex = tour[next_vertex].vertex;
next_vertex = tour[next_vertex].next;
x[from] = 1.0;
x[to] = 1.0;
@@ -842,14 +864,14 @@ int build_x_from_tour(struct GTSP *data, int *tour, double *x)
int inital_tour_value(struct GTSP *data, int *tour_cost, double *x)
{
int rval = 0;
int cluster_count = data->cluster_count;
int *tour = 0;
struct Tour *tour = 0;
int *uncovered_sets = 0;
int *cluster_in_tour = 0;
tour = (int *) malloc((cluster_count + 1) * sizeof(int));
tour = (struct Tour *) malloc((cluster_count + 1) * sizeof(struct Tour));
uncovered_sets = (int *) malloc((cluster_count - 1) * sizeof(int));
cluster_in_tour = (int *) malloc(cluster_count * sizeof(int));
abort_if(!tour, "could not allocate tour");
@@ -863,49 +885,86 @@ int inital_tour_value(struct GTSP *data, int *tour_cost, double *x)
if (data->node_to_cluster[0] != i)
{
uncovered_sets[cluster_num] = i;
cluster_num += 1;
cluster_num ++;
}
}
int new_vertex = 1;
tour[0] = 0;
int new_vertex = 1, cost;
tour[0].vertex = 0;
cluster_in_tour[0] = 1;
while (new_vertex < data->cluster_count)
{
int min_vertex = -1;
int min_dist_vertex = -1;
int min_cost = INT_MAX;
for (int i = 1; i < data->graph->node_count; i++)
{
if (!cluster_in_tour[data->node_to_cluster[i]])
{
for (int k = 0; k < new_vertex; k++)
{
int cost = data->dist_matrix[i][tour[k]];
if (cost < min_cost)
{
min_cost = cost;
min_vertex = i;
}
}
}
if (cluster_in_tour[data->node_to_cluster[i]]) continue;
for (int k = 0; k < new_vertex; k++)
{
cost = data->dist_matrix[i][tour[k].vertex];
if (cost < min_cost)
{ min_cost = cost;
min_dist_vertex = i;
}
}
}
assert(min_vertex >= 0);
tour[new_vertex] = min_vertex;
cluster_in_tour[data->node_to_cluster[min_vertex]] = 1;
assert(min_dist_vertex >= 0);
int cluster_to_insert = data->node_to_cluster[min_dist_vertex];
cluster_in_tour[cluster_to_insert] = 1;
min_cost = INT_MAX;
int insertion_cost = -1, best_pose = -1, best_vertex = -1;
for (int k=0 ; k < data->clusters[cluster_to_insert].size; k++){
for(int j = 0; j < new_vertex; j++){
int vertex_to_insert = data->clusters[cluster_to_insert].nodes[k];
if (new_vertex ==1){
int vertex1 = tour[0].vertex;
insertion_cost = data->dist_matrix[vertex_to_insert][vertex1]
+ data->dist_matrix[vertex1][vertex_to_insert];
}else{
int vertex1 = tour[j].vertex;
int vertex2 = tour[tour[j].next].vertex;
insertion_cost = data->dist_matrix[vertex1][vertex_to_insert]
+ data->dist_matrix[vertex_to_insert][vertex2] -
data->dist_matrix[vertex1][vertex2];
}
if(insertion_cost < min_cost){
min_cost = insertion_cost;
best_pose = j;
best_vertex = vertex_to_insert;
}
}
}
tour[new_vertex].vertex = best_vertex;
tour[new_vertex].prev = best_pose;
if (new_vertex ==1){
tour[new_vertex].next = best_pose;
tour[best_pose].prev = new_vertex;
}else{
int temp_vertex = tour[best_pose].next;
tour[new_vertex].next = temp_vertex;
tour[temp_vertex].prev = new_vertex;
}
tour[best_pose].next = new_vertex;
new_vertex += 1;
}
tour[data->cluster_count] = 0;
tour[data->cluster_count].vertex = 0;
rval = large_neighborhood_search(tour, data, tour_cost);
abort_if(rval, "large_neighborhood_search failed");
//tour_cost = optimize_vertex_in_cluster(tour, data);
log_info("Initial upper-bound: %d \n", *tour_cost);
rval = build_x_from_tour(data, tour, x);
@@ -989,47 +1048,30 @@ int two_opt(struct Tour *tour, struct GTSP *data)
return 0;
}
int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost)
int large_neighborhood_search(struct Tour *tour, struct GTSP *data, int *tour_cost)
{
int rval = 0;
struct Tour *vertex_seq = 0;
int cluster_count = data->cluster_count;
int *clusters = data->node_to_cluster;
int **dist_matrix = data->dist_matrix;
struct Cluster *vertex_set = data->clusters;
vertex_seq = (struct Tour *) malloc(cluster_count * sizeof(struct Tour));
abort_if(!vertex_seq, "could not allocate vertex_seq");
//Construct the list
for (int i = 0; i < cluster_count; i++)
{
vertex_seq[i].vertex = tour[i];
if (i == 0)
vertex_seq[i].prev = cluster_count - 1;
else
vertex_seq[i].prev = i - 1;
if (i == cluster_count - 1)
vertex_seq[i].next = 0;
else
vertex_seq[i].next = i + 1;
}
//LNS starts
for (int iter = 0; iter < 1000; iter++)
for (int iter = 0; iter < 2000; iter++)
{
//Delete a vertex
//Delete a random vertex
int delete_vertex = rand() % (cluster_count - 1) + 1;
int prev_vertex = tour[delete_vertex].prev;
int next_vertex = tour[delete_vertex].next;
int prev_vertex = vertex_seq[delete_vertex].prev;
int next_vertex = vertex_seq[delete_vertex].next;
tour[prev_vertex].next = next_vertex;
tour[next_vertex].prev = prev_vertex;
vertex_seq[prev_vertex].next = next_vertex;
vertex_seq[next_vertex].prev = prev_vertex;
int cluster_to_insert = clusters[vertex_seq[delete_vertex].vertex];
int cluster_to_insert = clusters[tour[delete_vertex].vertex];
int best_pose = -1;
int best_vertex = -1;
@@ -1039,11 +1081,11 @@ int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost)
{
int vertex_to_insert = vertex_set[cluster_to_insert].nodes[i];
int next_edge = vertex_seq[0].next;
int next_edge = tour[0].next;
for (int j = 1; j < cluster_count; j++)
{
int vertex1 = vertex_seq[next_edge].vertex;
int vertex2 = vertex_seq[vertex_seq[next_edge].next].vertex;
int vertex1 = tour[next_edge].vertex;
int vertex2 = tour[tour[next_edge].next].vertex;
int insert_cost = dist_matrix[vertex1][vertex_to_insert] +
dist_matrix[vertex_to_insert][vertex2] -
@@ -1056,31 +1098,34 @@ int large_neighborhood_search(int *tour, struct GTSP *data, int *tour_cost)
best_vertex = vertex_to_insert;
}
next_edge = vertex_seq[next_edge].next;
next_edge = tour[next_edge].next;
}
}
assert(best_pose >= 0);
assert(best_vertex >= 0);
next_vertex = vertex_seq[best_pose].next;
vertex_seq[delete_vertex].prev = best_pose;
vertex_seq[delete_vertex].vertex = best_vertex;
vertex_seq[delete_vertex].next = next_vertex;
vertex_seq[best_pose].next = delete_vertex;
vertex_seq[next_vertex].prev = delete_vertex;
rval = optimize_vertex_in_cluster(vertex_seq, data);
next_vertex = tour[best_pose].next;
tour[delete_vertex].prev = best_pose;
tour[delete_vertex].vertex = best_vertex;
tour[delete_vertex].next = next_vertex;
tour[best_pose].next = delete_vertex;
tour[next_vertex].prev = delete_vertex;
rval = optimize_vertex_in_cluster(tour, data);
abort_if(rval, "optimize_vertex_in_cluster failed");
}
rval = two_opt(vertex_seq, data);
rval = K_opt(tour, data);
abort_if(rval, "two_opt failed");
*tour_cost = list_length(vertex_seq, data);
rval = two_opt(tour, data);
abort_if(rval, "two_opt failed");
*tour_cost = list_length(tour, data);
CLEANUP:
if (vertex_seq) free(vertex_seq);
//if (vertex_seq) free(vertex_seq);
return rval;
}
@@ -1134,4 +1179,138 @@ void print_list(struct Tour *tour, struct GTSP *data)
printf("\n");
}
int K_opt(struct Tour* tour, struct GTSP *data)
{
int cluster_count = data->cluster_count;
int l;
for(int i = 0 ; i < cluster_count - 3; i++){
int location_in_path = 0;
for(int k = 0; k < i; k++)
location_in_path = tour[location_in_path].next;
int current_vertex = tour[location_in_path].vertex;
for(int k = 3; k < cluster_count - i - 2; k++){
int first_next_location = tour[location_in_path].next;
int first_next_vertex = tour[tour[location_in_path].next].vertex;
int next_location = tour[location_in_path].next;
for(l = 0; l < k; l++){
next_location = tour[next_location].next;
}
int next_vertex = tour[next_location].vertex;
int next_next_location = tour[next_location].next;
int next_next_vertex = tour[next_next_location].vertex;
if(next_next_vertex == current_vertex) break;
int cost1 = data->dist_matrix[current_vertex][first_next_vertex] +
data->dist_matrix[next_vertex][next_next_vertex];
int cost2 = data->dist_matrix[current_vertex][next_vertex] +
data->dist_matrix[first_next_vertex][next_next_vertex];
if(cost2 < cost1)
{
int tmp_location = next_location;
for(int m =0 ; m < l + 1; m++)
{
int tmp_vertex = tour[tmp_location].next;
tour[tmp_location].next = tour[tmp_location].prev;
tour[tmp_location].prev = tmp_vertex;
tmp_location = tour[tmp_location].next;
}
tour[location_in_path].next = next_location;
tour[next_location].prev = location_in_path;
tour[first_next_location].next = next_next_location;
tour[next_next_location].prev = first_next_location;
}
}
}
return 0;
}
int build_tour_from_x(struct GTSP *data, struct Tour *tour, double *x)
{
int rval = 0;
int *cluster_mark = 0;
struct Node **stack = 0;
int stack_top = 0;
struct Graph *graph = data->graph;
const int node_count = graph->node_count;
cluster_mark = (int *) malloc(data->cluster_count * sizeof(int));
abort_if(!cluster_mark, "could not allocate cluster_mark");
stack = (struct Node **) malloc(graph->node_count * sizeof(struct Node *));
abort_if(!stack, "could not allocate stack");
for (int i = 0; i < node_count; i++)
graph->nodes[i].mark = 0;
for (int i = 0; i < data->cluster_count; i++)
cluster_mark[i] = 0;
int initial;
for (initial = 0; initial < node_count; initial++)
if (x[initial] > 1.0 - LP_EPSILON) break;
abort_if(initial == node_count, "no initial node");
stack[stack_top++] = &graph->nodes[initial];
graph->nodes[initial].mark = 1;
tour[0].vertex = graph->nodes[initial].index;
int next_vertex = 1;
while (stack_top > 0)
{
struct Node *n = stack[--stack_top];
cluster_mark[data->node_to_cluster[n->index]]++;
for (int i = 0; i < n->degree; i++)
{
struct Adjacency *adj = &n->adj[i];
struct Node *neighbor = adj->neighbor;
if (neighbor->mark) continue;
if (x[node_count + adj->edge->index] < LP_EPSILON) continue;
stack[stack_top++] = neighbor;
tour[next_vertex].vertex = neighbor->index;
next_vertex++;
neighbor->mark = 1;
}
}
for(int i =0; i < data->cluster_count; i++){
if(i == 0){
tour[i].prev = data->cluster_count - 1;
}else{
tour[i].prev = i-1;
}
if(i == data->cluster_count - 1){
tour[i].next = 0;
}else{
tour[i].next = i+1;
}
}
CLEANUP:
if (stack) free(stack);
if (cluster_mark) free(cluster_mark);
return rval;
}

View File

@@ -52,7 +52,7 @@ int optimize_vertex_in_cluster(struct Tour * tour, struct GTSP *data);
int two_opt(struct Tour * tour, struct GTSP *data);
int K_opt(int* tour, struct GTSP *data);
int K_opt(struct Tour* tour, struct GTSP *data);
int tour_length(int* tour, struct GTSP* data);
@@ -62,5 +62,6 @@ int list_length(struct Tour * tour, struct GTSP* data);
void print_list(struct Tour * tour, struct GTSP* data);
int build_tour_from_x(struct GTSP *data, struct Tour *tour, double *x);
#endif //_PROJECT_GTSP_H_