First version of the GTSP branch-and-bound solver

master
Alinson S. Xavier 11 years ago
parent c6d3dee71c
commit 6891c0d0be

@ -0,0 +1,183 @@
#include <stdio.h>
#include <stdlib.h>
#include "gtsp.h"
#include "geometry.h"
#include "util.h"
int GTSP_init_data(struct GTSP *data)
{
data->node_count = 0;
data->edge_count = 0;
data->edges = 0;
data->clusters = 0;
data->cluster_count = 0;
data->x_coordinates = 0;
data->y_coordinates = 0;
return 0;
}
void GTSP_free(struct GTSP *data)
{
if (!data) return;
if (data->edges) free(data->edges);
if (data->clusters) free(data->clusters);
if (data->x_coordinates) free(data->x_coordinates);
if (data->y_coordinates) free(data->y_coordinates);
}
int GTSP_create_random_problem(
int node_count, int cluster_count, int grid_size, struct GTSP *data)
{
int rval = 0;
struct Edge *edges = 0;
int *clusters = 0;
double *x_coords = 0;
double *y_coords = 0;
int edge_count = (node_count * (node_count - 1)) / 2;
edges = (struct Edge *) malloc(edge_count * sizeof(struct Edge));
clusters = (int *) malloc(node_count * sizeof(int));
ABORT_IF (!edges, "could not allocate data->edges\n");
ABORT_IF (!clusters, "could not allocate clusters\n");
x_coords = (double *) malloc(node_count * sizeof(double));
y_coords = (double *) malloc(node_count * sizeof(double));
ABORT_IF (!x_coords, "could not allocate x_coords\n");
ABORT_IF (!y_coords, "could not allocate y_coords\n");
rval = generate_random_clusters_2d(node_count, cluster_count, grid_size,
x_coords, y_coords, clusters);
ABORT_IF(rval, "generate_random_clusters_2d failed");
int current_edge = 0;
for (int i = 0; i < edge_count; i++)
for (int j = i + 1; j < node_count; j++)
{
edges[current_edge].from = i;
edges[current_edge].to = j;
edges[current_edge].weight =
get_euclidean_distance(x_coords, y_coords, i, j);
current_edge++;
}
data->node_count = node_count;
data->edge_count = edge_count;
data->edges = edges;
data->clusters = clusters;
data->cluster_count = cluster_count;
data->x_coordinates = x_coords;
data->y_coordinates = y_coords;
CLEANUP:
if (rval)
{
if (edges) free(edges);
if (clusters) free(clusters);
}
return rval;
}
int GTSP_init_lp(struct LP *lp, struct GTSP *data)
{
int rval = 0;
int node_count = data->node_count;
int edge_count = data->edge_count;
int cluster_count = data->cluster_count;
int *clusters = data->clusters;
struct Edge *edges = data->edges;
for (int i = 0; i < node_count; i++)
{
rval = LP_new_row(lp, 'E', 0.0);
ABORT_IF(rval, "LP_new_row failed");
}
for (int i = 0; i < cluster_count; i++)
{
rval = LP_new_row(lp, 'E', 1.0);
ABORT_IF(rval, "LP_new_row failed");
}
double lb = 0.0;
double ub = 1.0;
int cmatbeg = 0;
for (int i = 0; i < node_count; i++)
{
double obj = 0.0;
double cmatval[] = {-2.0, 1.0};
int cmatind[] = {i, node_count + clusters[i]};
rval = LP_add_cols(lp, 1, 2, &obj, &cmatbeg, cmatind, cmatval, &lb,
&ub);
ABORT_IF(rval, "LP_add_cols failed");
}
for (int i = 0; i < edge_count; i++)
{
double obj = (double) edges[i].weight;
double cmatval[] = {1.0, 1.0};
int cmatind[] = {edges[i].from, edges[i].to};
rval = LP_add_cols(lp, 1, 2, &obj, &cmatbeg, cmatind, cmatval, &lb,
&ub);
ABORT_IF(rval, "LP_add_cols failed");
}
CLEANUP:
return rval;
}
int GTSP_write_data(struct GTSP *data, char *filename)
{
int rval = 0;
FILE *file;
file = fopen(filename, "w");
ABORT_IF(!file, "could not open file");
fprintf(file, "%d %d\n", data->node_count, data->cluster_count);
for (int i = 0; i < data->node_count; i++)
{
fprintf(file, "%.2lf %.2lf %d\n", data->x_coordinates[i],
data->y_coordinates[i], data->clusters[i]);
}
CLEANUP:
if (file) fclose(file);
return rval;
}
int GTSP_write_solution(struct GTSP *data, char *filename, double *x)
{
int rval = 0;
struct Edge *edges = data->edges;
int node_count = data->node_count;
FILE *file;
file = fopen(filename, "w");
ABORT_IF(!file, "could not open file");
int positive_edge_count = 0;
for (int i = 0; i < data->edge_count; i++)
if (x[i + node_count] > 0.5)
positive_edge_count++;
fprintf(file, "%d\n", positive_edge_count);
for (int i = 0; i < data->edge_count; i++)
if (x[i + node_count] > 0.5)
fprintf(file, "%d %d\n", edges[i].from, edges[i].to);
CLEANUP:
if (file) fclose(file);
return rval;
}

@ -0,0 +1,43 @@
//
// Created by isoron on 18/03/15.
//
#ifndef _PROJECT_GTSP_H_
#define _PROJECT_GTSP_H_
#include "lp.h"
struct Edge
{
int from;
int to;
int weight;
};
struct GTSP
{
int node_count;
int edge_count;
struct Edge *edges;
int *clusters;
int cluster_count;
double *x_coordinates;
double *y_coordinates;
};
int GTSP_create_random_problem(
int node_count, int cluster_count, int grid_size, struct GTSP *data);
void GTSP_free(struct GTSP *data);
int GTSP_init_data(struct GTSP *data);
int GTSP_init_lp(struct LP *lp, struct GTSP *data);
int GTSP_write_data(struct GTSP *data, char *filename);
int GTSP_write_solution(struct GTSP *data, char *filename, double *x);
#endif //_PROJECT_GTSP_H_

@ -1,11 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <getopt.h> #include <getopt.h>
#include <float.h>
#include "lp.h" #include "lp.h"
#include "util.h" #include "util.h"
#include "main.h" #include "main.h"
#include "tsp.h" #include "tsp.h"
#include "branch_and_cut.h" #include "branch_and_cut.h"
#include "gtsp.h"
char *INPUT_FILENAME = 0; char *INPUT_FILENAME = 0;
unsigned int SEED = 0; unsigned int SEED = 0;
@ -13,34 +15,35 @@ int GEOMETRIC_DATA = 0;
int NODE_COUNT_RAND = 0; int NODE_COUNT_RAND = 0;
int GRID_SIZE_RAND = 100; int GRID_SIZE_RAND = 100;
static int parse_arguments(int ac, char **av); static int parse_arguments_tsp(int ac, char **av);
static void print_usage(char *f); static void print_usage_tsp(char *f);
int main(int ac, char **av) int main_tsp(int ac, char **av)
{ {
int rval = 0; int rval = 0;
SEED = (unsigned int) get_current_time(); SEED = (unsigned int) get_real_time();
struct BNC bnc;
struct TSPData data;
rval = parse_arguments(ac, av); rval = TSP_init_data(&data);
ABORT_IF(rval, "TSP_init_data failed");
rval = BNC_init(&bnc);
ABORT_IF(rval, "BNC_init failed");
rval = parse_arguments_tsp(ac, av);
ABORT_IF(rval, "Failed to parse arguments.\n"); ABORT_IF(rval, "Failed to parse arguments.\n");
printf("Seed = %d\n", SEED); printf("Seed = %d\n", SEED);
srand(SEED); srand(SEED);
struct BNC bnc;
struct TSPData data;
TSP_init_data(&data);
rval = TSP_read_problem(INPUT_FILENAME, &data); rval = TSP_read_problem(INPUT_FILENAME, &data);
ABORT_IF(rval, "TSP_read_problem failed\n"); ABORT_IF(rval, "TSP_read_problem failed\n");
rval = BNC_init(&bnc); bnc.best_obj_val = TSP_find_initial_solution(&data);
ABORT_IF(rval, "BNC_init failed");
bnc.best_val = TSP_find_initial_solution(&data);
bnc.problem_data = (void *) &data; bnc.problem_data = (void *) &data;
bnc.problem_init_lp = (int (*)(struct LP *, void *)) TSP_init_lp; bnc.problem_init_lp = (int (*)(struct LP *, void *)) TSP_init_lp;
bnc.problem_add_cutting_planes = bnc.problem_add_cutting_planes =
@ -53,7 +56,7 @@ int main(int ac, char **av)
ABORT_IF(rval, "BNC_solve_node failed\n"); ABORT_IF(rval, "BNC_solve_node failed\n");
time_printf("Optimal integral solution:\n"); time_printf("Optimal integral solution:\n");
time_printf(" obj value = %.2lf **\n", bnc.best_val); time_printf(" obj value = %.2lf **\n", bnc.best_obj_val);
CLEANUP: CLEANUP:
BNC_free(&bnc); BNC_free(&bnc);
@ -61,7 +64,60 @@ int main(int ac, char **av)
return rval; return rval;
} }
static int parse_arguments(int ac, char **av) int main_gtsp(int ac, char **av)
{
int rval = 0;
SEED = (unsigned int) get_real_time();
srand(SEED);
int node_count = 50;
int cluster_count = node_count / 5;
int grid_size = 100;
struct BNC bnc;
struct GTSP data;
rval = GTSP_init_data(&data);
ABORT_IF(rval, "GTSP_init_data failed");
rval = GTSP_create_random_problem(node_count, cluster_count, grid_size,
&data);
ABORT_IF(rval, "GTSP_create_random_problem failed");
rval = GTSP_write_data(&data, "gtsp.in");
ABORT_IF(rval, "GTSP_write_problem failed\n");
rval = BNC_init(&bnc);
ABORT_IF(rval, "BNC_init failed\n");
printf("Seed = %d\n", SEED);
srand(SEED);
bnc.best_obj_val = DBL_MAX;
bnc.problem_data = (void *) &data;
bnc.problem_init_lp = (int (*)(struct LP *, void *)) GTSP_init_lp;
rval = BNC_init_lp(&bnc);
ABORT_IF(rval, "BNC_init_lp failed\n");
rval = BNC_solve(&bnc);
ABORT_IF(rval, "BNC_solve_node failed\n");
time_printf("Optimal integral solution:\n");
time_printf(" obj value = %.2lf **\n", bnc.best_obj_val);
rval = GTSP_write_solution(&data, "gtsp.out", bnc.best_x);
ABORT_IF(rval, "GTSP_write_solution failed");
CLEANUP:
GTSP_free(&data);
BNC_free(&bnc);
return rval;
}
static int parse_arguments_tsp(int ac, char **av)
{ {
int rval = 0; int rval = 0;
@ -69,7 +125,7 @@ static int parse_arguments(int ac, char **av)
if (ac == 1) if (ac == 1)
{ {
print_usage(av[0]); print_usage_tsp(av[0]);
return 1; return 1;
} }
@ -93,7 +149,7 @@ static int parse_arguments(int ac, char **av)
break; break;
case '?': case '?':
default: default:
print_usage(av[0]); print_usage_tsp(av[0]);
return 1; return 1;
} }
} }
@ -102,7 +158,7 @@ static int parse_arguments(int ac, char **av)
if (optind != ac) if (optind != ac)
{ {
print_usage(av[0]); print_usage_tsp(av[0]);
return 1; return 1;
} }
@ -113,7 +169,13 @@ static int parse_arguments(int ac, char **av)
return rval; return rval;
} }
static void print_usage(char *f) int main(int ac, char **av)
{
return main_gtsp(ac, av);
// return main_tsp(ac, av);
}
static void print_usage_tsp(char *f)
{ {
fprintf(stderr, "Usage: %s [-see below-] [prob_file]\n" fprintf(stderr, "Usage: %s [-see below-] [prob_file]\n"
" -a add all subtours cuts at once\n" " -a add all subtours cuts at once\n"