Refactoring

master
Alinson S. Xavier 11 years ago
parent f2b788665f
commit e2c6dafb33

@ -2,7 +2,7 @@
#include <stdlib.h>
#include <math.h>
#include "lp.h"
#include "branch_and_cut.h"
#include "branch-and-cut.h"
#include "util.h"
#include "gtsp.h"
@ -58,8 +58,11 @@ int BNC_init_lp(struct BNC *bnc)
rval = bnc->problem_init_lp(bnc->lp, bnc->problem_data);
abort_if(rval, "problem_init_lp failed");
rval = LP_write(bnc->lp, "subtour.lp");
abort_if(rval, "LP_write failed");
if(strlen(LP_FILENAME) > 0)
{
rval = LP_write(bnc->lp, LP_FILENAME);
abort_if(rval, "LP_write failed");
}
CLEANUP:
return rval;

@ -78,8 +78,6 @@ int graph_build(
int b = edges[2 * i + 1];
n = &graph->nodes[a];
n->adj[n->degree].neighbor_index = b;
n->adj[n->degree].edge_index = i;
n->adj[n->degree].neighbor = &graph->nodes[b];
n->adj[n->degree].edge = &graph->edges[i];
n->degree++;
@ -87,8 +85,6 @@ int graph_build(
if (!is_directed)
{
n = &graph->nodes[b];
n->adj[n->degree].neighbor_index = a;
n->adj[n->degree].edge_index = i;
n->adj[n->degree].neighbor = &graph->nodes[a];
n->adj[n->degree].edge = &graph->edges[i];
n->degree++;

@ -5,9 +5,6 @@
struct Adjacency
{
int edge_index;
int neighbor_index;
struct Edge *edge;
struct Node *neighbor;
};

@ -67,7 +67,7 @@ static int add_comb_cut(
nz++;
}
#if LOG_LEVEL >= LOG_LEVEL_DEBUG
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
log_verbose("Generated cut:\n");
if (OPTIMAL_X)
{
@ -341,49 +341,6 @@ static int shrink_clusters(
return rval;
}
static int write_shrunken_graph(
double *shrunken_x,
struct Graph *shrunken_graph,
int const cluster_count)
{
int rval = 0;
FILE *file = 0;
file = fopen("gtsp-shrunken.in", "w");
abort_if(!file, "could not open file");
fprintf(file, "%d %d\n", (*shrunken_graph).node_count, cluster_count);
for (int i = 0; i < (*shrunken_graph).node_count; i++)
fprintf(file, "%.2lf %.2lf %d\n", (*shrunken_graph).x_coordinates[i],
(*shrunken_graph).y_coordinates[i], i);
fclose(file);
file = fopen("gtsp-shrunken.out", "w");
abort_if(!file, "could not open file");
int positive_edge_count = 0;
for (int i = 0; i < (*shrunken_graph).edge_count; i++)
if (shrunken_x[i] > EPSILON)
positive_edge_count++;
fprintf(file, "%d %d\n", (*shrunken_graph).node_count,
(*shrunken_graph).edge_count);
fprintf(file, "%d\n", positive_edge_count);
for (int i = 0; i < (*shrunken_graph).edge_count; i++)
if (shrunken_x[i] > EPSILON)
fprintf(file, "%d %d %.4lf\n",
(*shrunken_graph).edges[i].from->index,
(*shrunken_graph).edges[i].to->index, shrunken_x[i]);
fclose(file);
CLEANUP:
return rval;
}
int GTSP_find_comb_cuts(struct LP *lp, struct GTSP *data)
{
int rval = 0;
@ -415,13 +372,6 @@ int GTSP_find_comb_cuts(struct LP *lp, struct GTSP *data)
rval = shrink_clusters(data, x, &shrunken_graph, shrunken_x);
abort_if(rval, "shrink_clusters failed");
#if LOG_LEVEL >= LOG_LEVEL_DEBUG
rval = write_shrunken_graph(shrunken_x, &shrunken_graph, cluster_count);
abort_if(rval, "write_shrunken_graph failed");
#else
UNUSED(write_shrunken_graph);
#endif
teeth = (int *) malloc(cluster_count * sizeof(int));
components = (int *) malloc(cluster_count * sizeof(int));
component_sizes = (int *) malloc(cluster_count * sizeof(int));

@ -187,8 +187,11 @@ int GTSP_find_exact_subtour_cuts(struct LP *lp, struct GTSP *data)
abort_if(rval, "LP_get_x failed");
#if LOG_LEVEL >= LOG_LEVEL_DEBUG
rval = GTSP_write_solution(data, "gtsp-frac.out", x);
abort_if(rval, "GTSP_write_solution failed");
if(strlen(FRAC_SOLUTION_FILENAME) > 0)
{
rval = GTSP_write_solution(data, FRAC_SOLUTION_FILENAME, x);
abort_if(rval, "GTSP_write_solution failed");
}
#endif
struct Graph digraph;

@ -8,9 +8,7 @@
#include "gtsp-comb.h"
int large_neighborhood_search(
struct Tour *tour,
struct GTSP *data,
int *tour_cost);
struct Tour *tour, struct GTSP *data, int *tour_cost);
int build_edge_map(struct GTSP *gtsp, int *edge_map);
@ -274,7 +272,8 @@ int GTSP_write_problem(struct GTSP *data, char *filename)
const struct Graph *graph = data->graph;
fprintf(file, "%d %d\n", graph->node_count, data->cluster_count);
fprintf(file, "%d %d %d\n", graph->node_count, data->cluster_count,
graph->edge_count);
for (int i = 0; i < graph->node_count; i++)
{
@ -287,15 +286,28 @@ int GTSP_write_problem(struct GTSP *data, char *filename)
return rval;
}
int GTSP_print_solution(struct GTSP *data, double *x)
{
struct Edge *edges = data->graph->edges;
int edge_count = data->graph->edge_count;
for (int i = 0; i < edge_count; i++)
if (x[i] > EPSILON)
log_info(" %-3d %-3d %8.4lf\n", edges[i].from->index,
edges[i].to->index, x[i]);
return 0;
}
int GTSP_write_solution(struct GTSP *data, char *filename, double *x)
{
int rval = 0;
struct Edge *edges = data->graph->edges;
int node_count = data->graph->node_count;
int edge_count = data->graph->edge_count;
FILE *file;
file = fopen(filename, "w");
abort_if(!file, "could not open file");
@ -304,8 +316,6 @@ int GTSP_write_solution(struct GTSP *data, char *filename, double *x)
if (x[i] > EPSILON)
positive_edge_count++;
fprintf(file, "%d %d\n", node_count, edge_count);
fprintf(file, "%d\n", positive_edge_count);
for (int i = 0; i < edge_count; i++)
@ -478,18 +488,17 @@ int GTSP_solution_found(struct BNC *bnc, struct GTSP *data, double *x)
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");
if (strlen(SOLUTION_FILENAME) > 0)
{
log_info("Writing solution to file %s\n", SOLUTION_FILENAME);
rval = GTSP_write_solution(data, SOLUTION_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");
@ -747,9 +756,7 @@ int two_opt(struct Tour *tour, struct GTSP *data)
}
int large_neighborhood_search(
struct Tour *tour,
struct GTSP *data,
int *tour_cost)
struct Tour *tour, struct GTSP *data, int *tour_cost)
{
int rval = 0;

@ -3,7 +3,7 @@
#include "lp.h"
#include "graph.h"
#include "branch_and_cut.h"
#include "branch-and-cut.h"
struct Tour
{
@ -60,6 +60,10 @@ int list_length(struct Tour * tour, struct GTSP* data);
void print_list(struct Tour * tour, struct GTSP* data);
int GTSP_print_solution(struct GTSP *data, double *x);
int build_tour_from_x(struct GTSP *data, struct Tour *tour, double *x);
int GTSP_solution_found(struct BNC *bnc, struct GTSP *data, double *x);

@ -384,11 +384,16 @@ int LP_get_num_cols(struct LP *lp)
int LP_write(struct LP *lp, const char *fname)
{
int rval = 0;
char nambuf[MAX_NAME_LENGTH];
FILE *f = fopen(fname, "w");
abort_iff(!f, "could not open file %s", fname);
fclose(f);
strncpy(nambuf, fname, MAX_NAME_LENGTH);
nambuf[MAX_NAME_LENGTH - 1] = '\0';
log_info("Writing LP to file %s...\n", fname);
rval = CPXwriteprob(lp->cplex_env, lp->cplex_lp, nambuf, "RLP");
abort_if(rval, "CPXwriteprob failed");

@ -30,6 +30,12 @@ double INITIAL_TIME = 0;
int BNC_NODE_COUNT = 0;
char LP_FILENAME[100] = {0};
char SOLUTION_FILENAME[100] = {0};
char FRAC_SOLUTION_FILENAME[100] = {0};
char WRITE_GRAPH_FILENAME[100] = {0};
char STATS_FILENAME[100] = {0};
static int input_node_count = -1;
static int input_cluster_count = -1;
static int grid_size = 100;
@ -39,24 +45,36 @@ static const struct option options_tab[] = {{"help", no_argument, 0, 'h'},
{"clusters", required_argument, 0, 'm'},
{"grid-size", required_argument, 0, 'g'},
{"optimal", required_argument, 0, 'x'},
{"seed", required_argument, 0, 's'},
{"seed", required_argument, 0, 's'}, {"out", required_argument, 0, 'o'},
{"stats", required_argument, 0, 't'}, {"lp", required_argument, 0, 'l'},
{"write-graph", required_argument, 0, 'w'},
{(char *) 0, (int) 0, (int *) 0, (int) 0}};
static char input_x_filename[1000] = {0};
static void print_usage(int argc, char **argv)
static void print_usage(char **argv)
{
printf("Usage: %s [OPTION]...\n", argv[0]);
printf("Solves the Generalized Traveling Salesman problem for the input graph.\n\n");
printf("Parameters:\n");
printf("%4s %-13s %s\n", "-n", "--nodes", "number of nodes");
printf("%4s %-13s %s\n", "-m", "--clusters", "number of clusters");
printf("%4s %-13s %s\n", "-s", "--seed", "random seed");
printf("%4s %-13s %s\n", "-g", "--grid-size",
printf("%4s %-20s %s\n", "-n", "--nodes=NUM", "number of nodes");
printf("%4s %-20s %s\n", "-m", "--clusters=NUM", "number of clusters");
printf("%4s %-20s %s\n", "-s", "--seed=NUM", "random seed");
printf("%4s %-20s %s\n", "-g", "--grid-size=NUM",
"size of the box used for generating random points");
printf("%4s %-13s %s\n", "-x", "--optimal",
"file containg valid solution (used to assert validity of cuts)");
printf("%4s %-20s %s\n", "-x", "--optimal=FILE",
"file containg optimal solution (used to assert validity of cuts)");
printf("%4s %-20s %s\n", "-o", "--out=FILE",
"write optimal solution to this file");
printf("%4s %-20s %s\n", "-f", "--frac=FILE",
"write current fractional solution to this file");
printf("%4s %-20s %s\n", "-l", "--lp=FILE",
"write initial LP to this file");
printf("%4s %-20s %s\n", "-w", "--write-graph=FILE",
"write the randomly generated input graph to this file");
printf("%4s %-20s %s\n", "-t", "--stats=FILE",
"write statistics to this file (append if file exists)");
}
static int parse_args(int argc, char **argv)
@ -69,7 +87,8 @@ static int parse_args(int argc, char **argv)
{
int c = 0;
int option_index = 0;
c = getopt_long(argc, argv, "n:m:g:x:s:h:", options_tab, &option_index);
c = getopt_long(argc, argv, "n:m:g:x:s:h:o:t:l:w:", options_tab,
&option_index);
if (c < 0) break;
@ -91,12 +110,28 @@ static int parse_args(int argc, char **argv)
strcpy(input_x_filename, optarg);
break;
case 'o':
strcpy(SOLUTION_FILENAME, optarg);
break;
case 's':
SEED = (unsigned) atoi(optarg);
break;
case 't':
strcpy(STATS_FILENAME, optarg);
break;
case 'l':
strcpy(LP_FILENAME, optarg);
break;
case 'w':
strcpy(WRITE_GRAPH_FILENAME, optarg);
break;
case 'h':
print_usage(argc, argv);
print_usage(argv);
exit(0);
case ':':
@ -175,16 +210,12 @@ int main(int argc, char **argv)
grid_size, &data);
abort_if(rval, "GTSP_create_random_problem failed");
char filename[100];
sprintf(filename, "input/%s.in", instance_name);
log_info("Writing random instance to file %s\n", filename);
rval = GTSP_write_problem(&data, filename);
abort_if(rval, "GTSP_write_problem failed");
#if LOG_LEVEL >= LOG_LEVEL_DEBUG
log_info("Writing random instance to file gtsp.in\n");
rval = GTSP_write_problem(&data, "gtsp.in");
#endif
if (strlen(WRITE_GRAPH_FILENAME) > 0)
{
log_info("Writing random instance to file %s\n", WRITE_GRAPH_FILENAME);
rval = GTSP_write_problem(&data, WRITE_GRAPH_FILENAME);
abort_if(rval, "GTSP_write_problem failed");
}
int init_val = 0;
@ -212,7 +243,6 @@ int main(int argc, char **argv)
if (strlen(input_x_filename) == 0)
{
sprintf(input_x_filename, "optimal/%s.out", instance_name);
FILE *file = fopen(input_x_filename, "r");
if (!file)
@ -241,19 +271,12 @@ int main(int argc, char **argv)
rval = BNC_init_lp(&bnc);
abort_if(rval, "BNC_init_lp failed");
// log_info("Writing LP to file gtsp.lp...\n");
// rval = LP_write(bnc.lp, "gtsp.lp");
// abort_if(rval, "LP_write failed");
log_info("Starting branch-and-cut solver...\n");
rval = BNC_solve(&bnc);
abort_if(rval, "BNC_solve_node failed");
abort_if(!bnc.best_x, "problem has no feasible solution");
log_info("Optimal integral solution:\n");
log_info(" obj value = %.2lf **\n", bnc.best_obj_val);
if (OPTIMAL_X)
{
abort_iff(bnc.best_obj_val - EPSILON > opt_val,
@ -263,60 +286,69 @@ int main(int argc, char **argv)
TOTAL_TIME = get_user_time() - initial_time;
log_info("Branch-and-bound nodes: %d\n", BNC_NODE_COUNT);
log_info("LP optimize calls: %d\n", LP_SOLVE_COUNT);
log_info("LP solving time: %.2lf\n", LP_SOLVE_TIME);
log_info("LP cut pool management time: %.2lf\n", CUT_POOL_TIME);
// Write statistics to a file
FILE *file = fopen("stats.tab", "a");
abort_if(!file, "could not open stats.tab");
if (strlen(STATS_FILENAME) > 0)
{
log_info("Writing statistics to file %s...\n", STATS_FILENAME);
FILE *file = fopen(STATS_FILENAME, "a");
abort_if(!file, "could not open stats.tab");
struct stat st;
stat("stats.tab", &st);
struct stat st;
stat(STATS_FILENAME, &st);
if (st.st_size == 0)
{
fprintf(file, "%-20s ", "instance");
fprintf(file, "%-8s ", "time");
fprintf(file, "%-8s ", "subt-t");
fprintf(file, "%-8s ", "combs-t");
fprintf(file, "%-8s ", "pool-t");
fprintf(file, "%-8s ", "pool-m");
fprintf(file, "%-8s ", "lp-count");
fprintf(file, "%-8s ", "lp-time");
fprintf(file, "%-8s ", "lp-rows");
fprintf(file, "%-8s ", "lp-cols");
fprintf(file, "%-8s ", "init-v");
fprintf(file, "%-8s ", "opt-v");
fprintf(file, "%-8s ", "root-v");
fprintf(file, "%-8s ", "nodes");
fprintf(file, "%-8s ", "subt-cc");
fprintf(file, "%-8s ", "subt-nc");
fprintf(file, "%-8s ", "subt-nn");
fprintf(file, "%-8s ", "combs");
if (st.st_size == 0)
{
fprintf(file, "%-20s ", "instance");
fprintf(file, "%-8s ", "time");
fprintf(file, "%-8s ", "subt-t");
fprintf(file, "%-8s ", "combs-t");
fprintf(file, "%-8s ", "pool-t");
fprintf(file, "%-8s ", "pool-m");
fprintf(file, "%-8s ", "lp-count");
fprintf(file, "%-8s ", "lp-time");
fprintf(file, "%-8s ", "lp-rows");
fprintf(file, "%-8s ", "lp-cols");
fprintf(file, "%-8s ", "init-v");
fprintf(file, "%-8s ", "opt-v");
fprintf(file, "%-8s ", "root-v");
fprintf(file, "%-8s ", "nodes");
fprintf(file, "%-8s ", "subt-cc");
fprintf(file, "%-8s ", "subt-nc");
fprintf(file, "%-8s ", "subt-nn");
fprintf(file, "%-8s ", "combs");
fprintf(file, "\n");
}
fprintf(file, "%-20s ", instance_name);
fprintf(file, "%-8.2lf ", TOTAL_TIME);
fprintf(file, "%-8.2lf ", SUBTOUR_TIME);
fprintf(file, "%-8.2lf ", COMBS_TIME);
fprintf(file, "%-8.2lf ", CUT_POOL_TIME);
fprintf(file, "%-8ld ", CUT_POOL_MAX_MEMORY / 1024 / 1024);
fprintf(file, "%-8d ", LP_SOLVE_COUNT);
fprintf(file, "%-8.2lf ", LP_SOLVE_TIME);
fprintf(file, "%-8d ", LP_MAX_ROWS);
fprintf(file, "%-8d ", LP_MAX_COLS);
fprintf(file, "%-8d ", init_val);
fprintf(file, "%-8.0lf ", bnc.best_obj_val);
fprintf(file, "%-8.0lf ", ROOT_VALUE);
fprintf(file, "%-8d ", BNC_NODE_COUNT);
fprintf(file, "%-8d ", SUBTOUR_COUNT);
fprintf(file, "%-8d ", COMBS_COUNT);
fprintf(file, "\n");
fclose(file);
}
if(strlen(SOLUTION_FILENAME) == 0)
{
log_info("Optimal solution:\n");
rval = GTSP_print_solution(&data, bnc.best_x);
abort_if(rval, "GTSP_print_solution failed");
}
fprintf(file, "%-20s ", instance_name);
fprintf(file, "%-8.2lf ", TOTAL_TIME);
fprintf(file, "%-8.2lf ", SUBTOUR_TIME);
fprintf(file, "%-8.2lf ", COMBS_TIME);
fprintf(file, "%-8.2lf ", CUT_POOL_TIME);
fprintf(file, "%-8ld ", CUT_POOL_MAX_MEMORY / 1024 / 1024);
fprintf(file, "%-8d ", LP_SOLVE_COUNT);
fprintf(file, "%-8.2lf ", LP_SOLVE_TIME);
fprintf(file, "%-8d ", LP_MAX_ROWS);
fprintf(file, "%-8d ", LP_MAX_COLS);
fprintf(file, "%-8d ", init_val);
fprintf(file, "%-8.0lf ", bnc.best_obj_val);
fprintf(file, "%-8.0lf ", ROOT_VALUE);
fprintf(file, "%-8d ", BNC_NODE_COUNT);
fprintf(file, "%-8d ", SUBTOUR_COUNT);
fprintf(file, "%-8d ", COMBS_COUNT);
fprintf(file, "\n");
fclose(file);
log_info("Optimal solution value:\n");
log_info(" %.4lf\n", bnc.best_obj_val);
CLEANUP:
if (OPTIMAL_X) free(OPTIMAL_X);

@ -24,4 +24,8 @@ extern double ROOT_VALUE;
extern int SUBTOUR_COUNT;
extern int COMBS_COUNT;
extern char LP_FILENAME[100];
extern char SOLUTION_FILENAME[100];
extern char FRAC_SOLUTION_FILENAME[100];
#endif

@ -41,11 +41,11 @@
#endif
#define abort_if(cond, msg) if(cond) { \
fprintf(stderr, "%28s:%d " msg "\n", __FILE__, __LINE__); \
fprintf(stderr, msg " (%s:%d)\n", __FILE__, __LINE__); \
rval = 1; goto CLEANUP; }
#define abort_iff(cond, msg, ...) if(cond) { \
fprintf(stderr, "%28s:%d " msg "\n", __FILE__, __LINE__, __VA_ARGS__); \
fprintf(stderr, msg " (%s:%d)\n", __VA_ARGS__, __FILE__, __LINE__); \
rval = 1; goto CLEANUP; }
#define UNUSED(x) (void)(x)