From 2e370e39efbf5bb26b6f8778630fe116058a02ed Mon Sep 17 00:00:00 2001 From: Alinson Xavier Date: Mon, 30 Mar 2015 16:27:13 -0400 Subject: [PATCH] Armin's heuristics --- src/branch_and_cut.c | 135 +++++++++++++++++++++++- src/branch_and_cut.h | 11 ++ src/geometry.c | 15 +++ src/geometry.h | 4 + src/gtsp.c | 242 +++++++++++++++++++++++++++++++++++++++++-- src/gtsp.h | 16 +++ src/util.h | 2 +- 7 files changed, 417 insertions(+), 8 deletions(-) diff --git a/src/branch_and_cut.c b/src/branch_and_cut.c index ef4baad..4198b70 100644 --- a/src/branch_and_cut.c +++ b/src/branch_and_cut.c @@ -4,6 +4,8 @@ #include "lp.h" #include "branch_and_cut.h" #include "util.h" +#include "gtsp.h" + int BNC_NODE_COUNT = 0; @@ -15,6 +17,8 @@ static int BNC_is_integral(double *x, int num_cols); static int BNC_find_best_branching_var(double *x, int num_cols); +//int optimize_vertex_in_cluster(struct BNC *bnc, double best_val); + int BNC_init(struct BNC *bnc) { int rval = 0; @@ -144,7 +148,9 @@ static int BNC_solve_node(struct BNC *bnc, int depth) *best_val = objval; bnc->best_x = x; x = 0; - + + + log_info("Found a better integral solution:\n"); log_info(" obj val = %.2lf **\n", objval); @@ -227,3 +233,130 @@ static int BNC_find_best_branching_var(double *x, int num_cols) return best_index; } + + +/* +int re_optimize_integral(struct BNC *bnc){ + int i = 0 , current_vertex = 0, rval = 0; + struct GTSP* data; + data = bnc->problem_data; + int node_count = data->graph->node_count; + int cluster_count = data->cluster_count; + int edge_count = data->graph->edge_count; + struct TOUR * tour = (struct TOUR*) NULL; + + //intialize the tour + tour = (struct TOUR *) malloc( cluster_count * sizeof(struct TOUR)); + for (i = 0; i < edge_count; i++){ + tour[i].vertex = -1; + tour[i].next = -1; + tour[i].prev = -1; + } + + //Constructing the tour with vertices + for (i = 0; i < edge_count; i++){ + if (bnc->best_x[i + node_count] > LP_EPSILON) { + tour[current_vertex].vertex = data->graph->edges[i].from->index; + current_vertex += 1; + printf("From node %d \t", data->graph->edges[i].from->index); + printf("TO node %d \n", data->graph->edges[i].to->index); + } + } + //printf("Edgese in solution %d \n", current_vertex); + + + return rval; + CLEANUP: + if (data) free(data); + +} +*/ +/* +int optimize_vertex_in_cluster(struct BNC *bnc, double best_val) +{ + + int i = 0 , j, current_vertex = 0, rval = 0; + int tour_cost = 0; + struct GTSP* data; + data = bnc->problem_data; + //rval = GTSP_init_data(&data); + //data = bnc->problem_data; + //data = (struct GTSP) malloc(sizeof(struct GTSP)); + + //data = &bnc->problem_data; + int node_count = data->graph->node_count; + int cluster_count = data->cluster_count; + int edge_count = data->graph->edge_count; + int * tour = (int*) NULL; + tour = (int *) malloc( cluster_count * sizeof(int)); + //Constructing the tour with vertices + for (i = 0; i < edge_count; i++) + { //printf(" edge %lf **\n", bnc->best_x[i]); + + if ((bnc->best_x[i] > 1 - LP_EPSILON)){ + //printf(" x[i] = %lf **\n", bnc->best_x[i]); + tour[current_vertex] = (data->graph->edges[i].from)->index; + current_vertex += 1; + //printf(" Edge No = %d **\n", i); + printf(" FROM No = %d **\n", (data->graph->edges[i].from)->index); + printf(" TO No = %d **\n", (data->graph->edges[i].to)->index); + + //printf(" current vertex = %d **\n", current_vertex); + } + } + + //reoptmizing the your with two-opt + //rval = two_opt(cluster_count, tour, data->dist_matrix); + //Optimizing the vertices inside the clusters + int current_cluster = 0; + int insertion_cost = 0; + + //printf(" o-- val = %.2lf **\n", best_val); + for(i = 1; i < cluster_count - 2; i++){ + //printf(" vertex in tour = %d **\n", tour[current_vertex]); + current_cluster = data->clusters[tour[i]]; + //printf(" o-- val = %.2lf **\n", best_val); + insertion_cost = data->dist_matrix[tour[i-1]][tour[i]] + + data->dist_matrix[tour[i]][tour[i+1]]; + //printf(" o-- val = %.2lf **\n", best_val); + for(j = 0; j < node_count; j++) + if (current_cluster == data->clusters[j]) + if (insertion_cost > data->dist_matrix[j][tour[i]] + + data->dist_matrix[j][tour[i+1]]){ + log_info("Optmize vertex in cluster improved the bound\n"); + insertion_cost = data->dist_matrix[j][tour[i]] + + data->dist_matrix[j][tour[i+1]]; + tour[i] = j; + } + } + printf(" o-- val = %.2lf **\n", best_val); + for(i = 0; i< cluster_count ; i++){ + if (i == cluster_count - 1) + tour_cost += data->dist_matrix[tour[i]][tour[0]]; + else + tour_cost += data->dist_matrix[tour[i]][tour[i+1]]; + if(tour_cost < bnc->best_obj_val) + bnc->best_obj_val = tour_cost; + } + return rval; +} +*/ + +/* +static int two_opt(int tour_length, int*tour, int** dist_matrix){ + int rval = 0, i; + for (i = 1; i < tour_length - 2; i++){ + int current_cost = dist_matrix[tour[i-1]][tour[i]] + + dist_matrix[tour[i+1]][tour[i+2]]; + int temp_cost = dist_matrix[tour[i-1]][tour[i+1]] + + dist_matrix[tour[i]][tour[i+2]]; + if(current_cost > temp_cost){ + log_info("Two opt improved the bound\n"); + int temp_vertex = tour[i]; + tour[i] = tour[i+1]; + tour[i+1] = temp_vertex; + } + } + return rval; +} +*/ diff --git a/src/branch_and_cut.h b/src/branch_and_cut.h index 02f3b69..b5e2400 100644 --- a/src/branch_and_cut.h +++ b/src/branch_and_cut.h @@ -3,6 +3,12 @@ #include "lp.h" +struct TOUR { + int vertex; + int next; + int prev; + }; + struct BNC { struct LP *lp; @@ -29,6 +35,11 @@ int BNC_init_lp(struct BNC *bnc); void BNC_free(struct BNC *bnc); +int re_optimize_integral(struct BNC *bnc); + +//int optimize_vertex_in_cluster(struct BNC *bnc, double best_val); + extern int BNC_NODE_COUNT; + #endif //_PROJECT_BRANCH_AND_CUT_H_ diff --git a/src/geometry.c b/src/geometry.c index bb5a83b..227a1dc 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -111,6 +111,21 @@ int generate_random_clusters_2d( return rval; } +int generate_dist_matrix( + int node_count, + double *x_coordinates, + double *y_coordinates, int** dist_matrix) +{ + int i,j; + for (i = 0; i < node_count; i++){ + for (j = 0; j < node_count; j++){ + dist_matrix[i][j] = + get_euclidean_distance(x_coordinates, y_coordinates, i, j); + } + } + return 0; +} + int get_euclidean_distance( double *x_coordinates, double *y_coordinates, diff --git a/src/geometry.h b/src/geometry.h index 8628d21..3026af7 100644 --- a/src/geometry.h +++ b/src/geometry.h @@ -21,4 +21,8 @@ int get_euclidean_distance( int p1_index, int p2_index); +int generate_dist_matrix( + int node_count, + double *x_coordinates, + double *y_coordinates, int** dist_matrix); #endif //_PROJECT_GEOMETRY_H_ diff --git a/src/gtsp.c b/src/gtsp.c index c98ba56..f5ec533 100644 --- a/src/gtsp.c +++ b/src/gtsp.c @@ -36,6 +36,8 @@ int GTSP_init_data(struct GTSP *data) data->graph = (struct Graph *) malloc(sizeof(struct Graph)); abort_if(!data->graph, "could not allocate data->graph"); + data->vertex_set = (struct CLUSTER *) malloc(sizeof(struct CLUSTER)); + graph_init(data->graph); CLEANUP: @@ -58,10 +60,12 @@ int GTSP_create_random_problem( int node_count, int cluster_count, int grid_size, struct GTSP *data) { int rval = 0; - + int i = 0; int *edges = 0; int *weights = 0; int *clusters = 0; + + int ** dist_matrix = 0; double *x_coords = 0; double *y_coords = 0; @@ -78,7 +82,7 @@ int GTSP_create_random_problem( edges = (int *) malloc(2 * edge_count * sizeof(int)); weights = (int *) malloc(edge_count * sizeof(int)); clusters = (int *) malloc(node_count * sizeof(int)); - +abort_if(!data->graph, "could not allocate data->graph"); abort_if(!edges, "could not allocate data->edges\n"); abort_if(!weights, "could not allocate weights\n"); abort_if(!clusters, "could not allocate clusters\n"); @@ -89,16 +93,50 @@ int GTSP_create_random_problem( abort_if(!x_coords, "could not allocate x_coords\n"); abort_if(!y_coords, "could not allocate y_coords\n"); + dist_matrix = (int **) malloc(node_count * sizeof(int*)); + for(i=0; icluster_count = cluster_count; data->x_coordinates = x_coords; data->y_coordinates = y_coords; - + data->dist_matrix = dist_matrix; + data->vertex_set = cluster_member; + CLEANUP: if (weights) free(weights); if (edges) free(edges); @@ -487,12 +527,14 @@ int GTSP_main(int argc, char **argv) rval = GTSP_create_random_problem(input_node_count, input_cluster_count, grid_size, &data); abort_if(rval, "GTSP_create_random_problem failed"); - + int init_val ; + + init_val = inital_tour_value(&data); log_info("Writing random instance to file gtsp.in\n"); rval = GTSP_write_problem(&data, "gtsp.in"); abort_if(rval, "GTSP_write_problem failed"); - bnc.best_obj_val = DBL_MAX; + bnc.best_obj_val = init_val; bnc.problem_data = (void *) &data; bnc.problem_init_lp = (int (*)(struct LP *, void *)) GTSP_init_lp; bnc.problem_add_cutting_planes = (int (*)( @@ -543,3 +585,191 @@ int GTSP_main(int argc, char **argv) BNC_free(&bnc); return rval; } + +int inital_tour_value(struct GTSP *data) +{ + int cluster_count = data->cluster_count; + int * tour; + int * uncovered_sets; + int min_vertex = -1; + int min_cost = 100000000; + int tour_cost = 0; + + int* cluster_in_tour; + cluster_in_tour = (int *) malloc(cluster_count*sizeof(int)); + + tour = (int *) malloc(cluster_count*sizeof(int)); + uncovered_sets = (int *) malloc((cluster_count-1)*sizeof(int)); + + int cluster_num = 0; + for(int i =0; i< cluster_count; i++){ + cluster_in_tour[i] = 0; + if(data->clusters[0] != i){ + uncovered_sets[cluster_num] = i; + cluster_num += 1; + } + } + int new_vertex = 1; + tour[0] = 0; + cluster_in_tour[0] = 1; + while(new_vertex <= data->cluster_count){ + min_vertex = -1; + min_cost = 100000000; + for (int i = 1; i < data->graph->node_count; i++) { + if (cluster_in_tour[data->clusters[i]] == 0){ + 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; + } + } + } + } + tour[new_vertex] = min_vertex; + cluster_in_tour[data->clusters[min_vertex]] = 1; + new_vertex += 1; + } + + + tour_cost = optimize_vertex_in_cluster(tour, data); + log_info("Initial upper-bound: %d \n", tour_cost); + return tour_cost; +} + + + +int optimize_vertex_in_cluster(int* tour, struct GTSP *data) +{ + + int i = 0 , j, current_cluster; + int insertion_cost = 0; + int rval = 0; + rval = two_opt(tour, data); + if(rval) + printf("Two opt local search stopped unexpectedly"); + //rval = K_opt(tour, data); + + for(i = 1; i < data->cluster_count - 2; i++){ + current_cluster = data->clusters[tour[i]]; + insertion_cost = data->dist_matrix[tour[i-1]][tour[i]] + + data->dist_matrix[tour[i]][tour[i+1]]; + current_cluster = data->clusters[i]; + for(j = 0; j < data->vertex_set[current_cluster].size; j++){ + int vertex = data->vertex_set[current_cluster].set[j]; + if (insertion_cost > data->dist_matrix[vertex][tour[i]] + + data->dist_matrix[vertex][tour[i+1]]){ + insertion_cost = data->dist_matrix[vertex][tour[i]] + + data->dist_matrix[vertex][tour[i+1]]; + tour[i] = vertex; + } + } + } + int tour_cost = 0; + for(i = 0; i< data->cluster_count ; i++){ + if (i == data->cluster_count - 1) + tour_cost += data->dist_matrix[tour[i]][tour[0]]; + else + tour_cost += data->dist_matrix[tour[i]][tour[i+1]]; + } + return tour_cost; +} + +int two_opt(int* tour, struct GTSP *data){ + int rval = 0, i; + for (i = 0; i < data->cluster_count; i++){ + int vertex1 = i; + int vertex2 = i - 1; + int vertex3 = i + 1; + int vertex4 = i + 2; + if(i == 0) + vertex2 = data->cluster_count - 1; + + if(i == data->cluster_count-2) + vertex4 = 0; + + if(i == data->cluster_count-1){ + vertex3 = 0; + vertex4 = 1; + } + + int current_cost = data->dist_matrix[tour[vertex2]][tour[vertex1]] + + data->dist_matrix[tour[vertex3]][tour[vertex4]]; + int temp_cost = data->dist_matrix[tour[vertex2]][tour[vertex3]] + + data->dist_matrix[tour[vertex1]][tour[vertex4]]; + if(current_cost > temp_cost){ + int temp_vertex = tour[vertex1]; + tour[vertex1] = tour[vertex3]; + tour[vertex3] = temp_vertex; + } + } + return rval; +} +/* +int K_opt(int* tour, struct GTSP *data){ + int rval = 0, i, k, I, j; + int current_cost, temp_cost, J, temp_vertex; + int tour_length = data->cluster_count; + + for (i = 1; i < tour_length - 2; i++){ + I = (i+k)%(tour_length); + if (I == tour_length - 1){ + current_cost = data->dist_matrix[tour[i-1]][tour[i]] + + data->dist_matrix[tour[I]][tour[0]]; + temp_cost = data->dist_matrix[tour[i-1]][tour[I]] + + data->dist_matrix[tour[i]][tour[0]]; + }else{ + current_cost = data->dist_matrix[tour[i-1]][tour[i]] + + data->dist_matrix[tour[I]][tour[I+1]]; + temp_cost = data->dist_matrix[tour[i-1]][tour[I]] + + data->dist_matrix[tour[i]][tour[I+1]]; + } + + if(current_cost > temp_cost){ + log_info("K_opt improved the bound\n"); + for(j = k; j > 0 ; j--){ + if(i + j > tour_length - 1) + J = i + j - tour_length; + temp_vertex = tour[i + k - j]; + tour[i + k - j] = tour[J]; + tour[J] = temp_vertex; + } + } + } + return rval; +}*/ +/* +int Larg_neighborhood_search(int* tour, struct GTSP *data){ + int i ; + struct TOUR* vertex_seq; + vertex_seq = (struct TOUR*) malloc(data->cluster_count*sizeof(struct TOUR)); + for(i = 0; icluster_count; i++){ + vertex_seq[i].vertex = tour[i]; + if ( i == 0){ + vertex_seq[i].prev = tour[data->cluster_count-1]; + }else{ + vertex_seq[i].prev = tour[i - 1]; + } + if ( i == data->cluster_count-1){ + vertex_seq[i].next = tour[0]; + }else{ + vertex_seq[i].next = tour[i+1]; + } + } + //Delete a vertex + int delete_vertex = rand()%(data->cluster_count - 1) + 1; + int prev_vertex = vertex_seq[delete_vertex].prev; + int next_vertex = vertex_seq[delete_vertex].next; + vertex_seq[prev_vertex].next = next_vertex; + vertex_seq[next_vertex].prev = prev_vertex; + int cluster_to_insert = data->clusters[vertex_seq[delete_vertex].vertex]; + int min_cost = 10000000; + for(i =0 ; i < data->vertex_set[cluster_to_insert].size ; i++){ + int current_vertex = data->vertex_set[cluster_to_insert].set[i]; + for(int j = 0; j < data->cluster_count - 1; j++){ + + //int insert_cost = + } + } + +}*/ diff --git a/src/gtsp.h b/src/gtsp.h index 96397ab..272b6e5 100644 --- a/src/gtsp.h +++ b/src/gtsp.h @@ -8,6 +8,12 @@ #include "lp.h" #include "graph.h" +struct CLUSTER +{ + int size; + int* set; +}; + struct GTSP { struct Graph *graph; @@ -17,11 +23,15 @@ struct GTSP double *x_coordinates; double *y_coordinates; + int** dist_matrix; + struct CLUSTER *vertex_set; }; int GTSP_create_random_problem( int node_count, int cluster_count, int grid_size, struct GTSP *data); +int inital_tour_value(struct GTSP *data); + void GTSP_free(struct GTSP *data); int GTSP_init_data(struct GTSP *data); @@ -36,6 +46,12 @@ int GTSP_write_solution(struct GTSP *data, char *filename, double *x); int GTSP_main(int argc, char **argv); +int optimize_vertex_in_cluster(int* tour, struct GTSP *data); + +int two_opt(int* tour, struct GTSP *data); + +int K_opt(int* tour, struct GTSP *data); + extern double *OPTIMAL_X; extern double FLOW_CPU_TIME; diff --git a/src/util.h b/src/util.h index 61552cb..f0ca093 100644 --- a/src/util.h +++ b/src/util.h @@ -9,7 +9,7 @@ #define LOG_LEVEL_DEBUG 40 #define LOG_LEVEL_VERBOSE 50 -#define LOG_LEVEL LOG_LEVEL_INFO +#define LOG_LEVEL LOG_LEVEL_DEBUG #if LOG_LEVEL < LOG_LEVEL_VERBOSE #define log_verbose(...)