Unify add_cut; organize functions

master
Alinson S. Xavier 11 years ago
parent 882739c378
commit 64351aae34

@ -11,6 +11,18 @@
static double *OPTIMAL_X = 0; static double *OPTIMAL_X = 0;
static int get_edge_num(int node_count, int from, int to)
{
int idx = node_count;
for (int k = 0; k < from; k++)
idx += node_count - k - 1;
idx += to - from - 1;
return idx;
}
int GTSP_init_data(struct GTSP *data) int GTSP_init_data(struct GTSP *data)
{ {
int rval = 0; int rval = 0;
@ -166,7 +178,7 @@ int GTSP_init_lp(struct LP *lp, struct GTSP *data)
return rval; return rval;
} }
int GTSP_add_subcluster_cut( static int add_subcluster_cut(
struct LP *lp, struct LP *lp,
struct Graph *graph, struct Graph *graph,
struct Edge *e, struct Edge *e,
@ -220,19 +232,19 @@ int GTSP_add_subcluster_cut(
return rval; return rval;
} }
int GTSP_add_subtour_elimination_cut_1( static int add_subtour_elimination_cut(
struct LP *lp, struct LP *lp,
struct Graph *graph, struct Graph *graph,
struct Node *from, struct Node *from,
struct Node *to, struct Node *to,
struct Edge **cut_edges, struct Edge **cut_edges,
int cut_edges_count) int cut_edges_count, int type)
{ {
int rval = 0; int rval = 0;
char sense = 'G'; char sense = 'G';
double rhs = -2.0; double rhs = 2.0 - 2.0 * type;
int newnz = cut_edges_count + 2; int newnz = cut_edges_count + type;
int rmatbeg = 0; int rmatbeg = 0;
int *rmatind = 0; int *rmatind = 0;
@ -250,67 +262,18 @@ int GTSP_add_subtour_elimination_cut_1(
rmatval[i] = 1.0; rmatval[i] = 1.0;
} }
rmatind[cut_edges_count] = from->index; if(type >= 1)
rmatval[cut_edges_count] = -2.0;
rmatind[cut_edges_count + 1] = to->index;
rmatval[cut_edges_count + 1] = -2.0;
log_verbose("Generated cut:\n");
for (int i = 0; i < newnz; i++)
log_verbose("%8.2f x%d\n", rmatval[i], rmatind[i]);
log_verbose(" %c %.2lf\n", sense, rhs);
if (OPTIMAL_X)
{ {
double sum = 0; rmatind[cut_edges_count] = from->index;
for (int i = 0; i < newnz; i++) rmatval[cut_edges_count] = -2.0;
sum += rmatval[i] * OPTIMAL_X[rmatind[i]];
abort_if(sum <= rhs - LP_EPSILON, "cannot add invalid cut");
} }
rval = LP_add_rows(lp, 1, newnz, &rhs, &sense, &rmatbeg, rmatind, rmatval); if(type >= 2)
abort_if(rval, "LP_add_rows failed");
CLEANUP:
if (rmatval) free(rmatval);
if (rmatind) free(rmatind);
return rval;
}
int GTSP_add_subtour_elimination_cut_2(
struct LP *lp,
struct Graph *graph,
struct Node *from,
struct Node *to,
struct Edge **cut_edges,
int cut_edges_count)
{
int rval = 0;
char sense = 'G';
double rhs = 0.0;
int newnz = cut_edges_count + 1;
int rmatbeg = 0;
int *rmatind = 0;
double *rmatval = 0;
rmatind = (int *) malloc(newnz * sizeof(int));
abort_if(!rmatind, "could not allocate rmatind");
rmatval = (double *) malloc(newnz * sizeof(double));
abort_if(!rmatval, "could not allocate rmatval");
for (int i = 0; i < cut_edges_count; i++)
{ {
rmatind[i] = cut_edges[i]->index + graph->node_count; rmatind[cut_edges_count + 1] = to->index;
rmatval[i] = 1.0; rmatval[cut_edges_count + 1] = -2.0;
} }
rmatind[cut_edges_count] = from->index;
rmatval[cut_edges_count] = -2.0;
log_verbose("Generated cut:\n"); log_verbose("Generated cut:\n");
for (int i = 0; i < newnz; i++) for (int i = 0; i < newnz; i++)
log_verbose("%8.2f x%d\n", rmatval[i], rmatind[i]); log_verbose("%8.2f x%d\n", rmatval[i], rmatind[i]);
@ -333,59 +296,7 @@ int GTSP_add_subtour_elimination_cut_2(
return rval; return rval;
} }
int GTSP_add_subtour_elimination_cut_3( static int build_flow_digraph(
struct LP *lp,
struct Graph *graph,
struct Node *from,
struct Node *to,
struct Edge **cut_edges,
int cut_edges_count)
{
int rval = 0;
char sense = 'G';
double rhs = 2.0;
int newnz = cut_edges_count;
int rmatbeg = 0;
int *rmatind = 0;
double *rmatval = 0;
rmatind = (int *) malloc(newnz * sizeof(int));
abort_if(!rmatind, "could not allocate rmatind");
rmatval = (double *) malloc(newnz * sizeof(double));
abort_if(!rmatval, "could not allocate rmatval");
for (int i = 0; i < cut_edges_count; i++)
{
rmatind[i] = cut_edges[i]->index + graph->node_count;
rmatval[i] = 1.0;
}
log_verbose("Generated cut:\n");
for (int i = 0; i < newnz; i++)
log_verbose("%8.2f x%d\n", rmatval[i], rmatind[i]);
log_verbose(" %c %.2lf\n", sense, rhs);
if (OPTIMAL_X)
{
double sum = 0;
for (int i = 0; i < newnz; i++)
sum += rmatval[i] * OPTIMAL_X[rmatind[i]];
abort_if(sum <= rhs - LP_EPSILON, "cannot add invalid cut");
}
rval = LP_add_rows(lp, 1, newnz, &rhs, &sense, &rmatbeg, rmatind, rmatval);
abort_if(rval, "LP_add_rows failed");
CLEANUP:
if (rmatval) free(rmatval);
if (rmatind) free(rmatind);
return rval;
}
int GTSP_build_flow_digraph(
struct GTSP *data, double *x, struct Graph *digraph, double *capacities) struct GTSP *data, double *x, struct Graph *digraph, double *capacities)
{ {
int rval = 0; int rval = 0;
@ -475,7 +386,7 @@ int GTSP_build_flow_digraph(
return rval; return rval;
} }
int map_cut_edges_from_digraph_to_graph( static int map_cut_edges_from_digraph_to_graph(
struct Graph *graph, int *cut_edges_count, struct Edge **cut_edges) struct Graph *graph, int *cut_edges_count, struct Edge **cut_edges)
{ {
int c = 0; int c = 0;
@ -492,10 +403,9 @@ int map_cut_edges_from_digraph_to_graph(
return 0; return 0;
} }
int GTSP_find_exact_subtour_elimination_cuts_1( int find_exact_subtour_elimination_cuts_0(
struct LP *lp, struct LP *lp,
struct GTSP *data, struct GTSP *data,
double *x,
struct Graph *digraph, struct Graph *digraph,
double *capacities, double *capacities,
int *added_cuts_count) int *added_cuts_count)
@ -506,70 +416,52 @@ int GTSP_find_exact_subtour_elimination_cuts_1(
double *flow = 0; double *flow = 0;
struct Graph *graph = data->graph; struct Graph *graph = data->graph;
int *clusters = data->clusters;
cut_edges = (struct Edge **) malloc( cut_edges = (struct Edge **) malloc(
digraph->edge_count * sizeof(struct Edge *)); digraph->edge_count * sizeof(struct Edge *));
flow = (double *) malloc(digraph->edge_count * sizeof(double)); flow = (double *) malloc(digraph->edge_count * sizeof(double));
abort_if(!cut_edges, "could not allocate cut_edges"); abort_if(!cut_edges, "could not allocate cut_edges");
abort_if(!flow, "could not allocate flow"); abort_if(!flow, "could not allocate flow");
int max_x_index = 0; for (int i = 0; i < data->cluster_count; i++)
double max_x = DBL_MIN;
for (int i = 0; i < graph->node_count; i++)
{ {
struct Node *n = &graph->nodes[i]; for (int j = i + 1; j < data->cluster_count; j++)
if (x[n->index] > max_x)
{ {
max_x = x[n->index]; struct Node *from = &digraph->nodes[graph->node_count + i];
max_x_index = i; struct Node *to = &digraph->nodes[graph->node_count + j];
}
}
int i = max_x_index;
for (int j = 0; j < graph->node_count; j++)
{
if (i == j) continue;
if (clusters[i] == clusters[j]) continue;
if (x[i] + x[j] - 1 <= LP_EPSILON) continue;
struct Node *from = &digraph->nodes[i];
struct Node *to = &digraph->nodes[j];
int cut_edges_count; double flow_value;
double flow_value; int cut_edges_count;
rval = flow_find_max_flow(digraph, capacities, from, to, flow, rval = flow_find_max_flow(digraph, capacities, from, to, flow,
&flow_value); &flow_value);
abort_if(rval, "flow_find_max_flow failed"); abort_if(rval, "flow_find_max_flow failed");
if (flow_value >= 2 * (x[i] + x[j] - 1) - LP_EPSILON) if (flow_value >= 2 - LP_EPSILON) continue;
continue;
rval = get_cut_edges_from_marks(digraph, &cut_edges_count, cut_edges); rval = get_cut_edges_from_marks(digraph, &cut_edges_count,
abort_if(rval, "get_cut_edges_from_marks failed"); cut_edges);
abort_if(rval, "get_cut_edges_from_marks failed");
rval = map_cut_edges_from_digraph_to_graph(graph, &cut_edges_count, rval = map_cut_edges_from_digraph_to_graph(graph, &cut_edges_count,
cut_edges); cut_edges);
abort_if(rval, "map_cut_edges_from_digraph_to_graph failed"); abort_if(rval, "map_cut_edges_from_digraph_to_graph failed");
rval = GTSP_add_subtour_elimination_cut_1(lp, graph, from, to, rval = add_subtour_elimination_cut(lp, graph, 0, 0, cut_edges,
cut_edges, cut_edges_count); cut_edges_count, 0);
abort_if(rval, "GTSP_add_subtour_elimination_cut_1 failed"); abort_if(rval, "GTSP_add_subtour_elimination_cut3 failed");
(*added_cuts_count)++; (*added_cuts_count)++;
}
} }
CLEANUP: CLEANUP:
if (flow) free(flow);
if (cut_edges) free(cut_edges); if (cut_edges) free(cut_edges);
if (flow) free(flow);
return rval; return rval;
} }
int GTSP_find_exact_subtour_elimination_cuts_2( int find_exact_subtour_elimination_cuts_1(
struct LP *lp, struct LP *lp,
struct GTSP *data, struct GTSP *data,
double *x, double *x,
@ -619,8 +511,8 @@ int GTSP_find_exact_subtour_elimination_cuts_2(
cut_edges); cut_edges);
abort_if(rval, "map_cut_edges_from_digraph_to_graph failed"); abort_if(rval, "map_cut_edges_from_digraph_to_graph failed");
rval = GTSP_add_subtour_elimination_cut_2(lp, graph, from, to, rval = add_subtour_elimination_cut(lp, graph, from, 0, cut_edges,
cut_edges, cut_edges_count); cut_edges_count, 1);
abort_if(rval, "GTSP_add_subtour_elimination_cut_1 failed"); abort_if(rval, "GTSP_add_subtour_elimination_cut_1 failed");
(*added_cuts_count)++; (*added_cuts_count)++;
@ -633,9 +525,10 @@ int GTSP_find_exact_subtour_elimination_cuts_2(
return rval; return rval;
} }
int GTSP_find_exact_subtour_elimination_cuts_3( int find_exact_subtour_elimination_cuts_2(
struct LP *lp, struct LP *lp,
struct GTSP *data, struct GTSP *data,
double *x,
struct Graph *digraph, struct Graph *digraph,
double *capacities, double *capacities,
int *added_cuts_count) int *added_cuts_count)
@ -651,48 +544,65 @@ int GTSP_find_exact_subtour_elimination_cuts_3(
cut_edges = (struct Edge **) malloc( cut_edges = (struct Edge **) malloc(
digraph->edge_count * sizeof(struct Edge *)); digraph->edge_count * sizeof(struct Edge *));
flow = (double *) malloc(digraph->edge_count * sizeof(double)); flow = (double *) malloc(digraph->edge_count * sizeof(double));
abort_if(!cut_edges, "could not allocate cut_edges"); abort_if(!cut_edges, "could not allocate cut_edges");
abort_if(!flow, "could not allocate flow"); abort_if(!flow, "could not allocate flow");
for (int i = 0; i < data->cluster_count; i++) int max_x_index = 0;
double max_x = DBL_MIN;
for (int i = 0; i < graph->node_count; i++)
{ {
for (int j = i + 1; j < data->cluster_count; j++) struct Node *n = &graph->nodes[i];
if (x[n->index] > max_x)
{ {
struct Node *from = &digraph->nodes[graph->node_count + i]; max_x = x[n->index];
struct Node *to = &digraph->nodes[graph->node_count + j]; max_x_index = i;
}
}
double flow_value; int i = max_x_index;
int cut_edges_count;
rval = flow_find_max_flow(digraph, capacities, from, to, flow, for (int j = 0; j < graph->node_count; j++)
&flow_value); {
abort_if(rval, "flow_find_max_flow failed"); if (i == j) continue;
if (clusters[i] == clusters[j]) continue;
if (x[i] + x[j] - 1 <= LP_EPSILON) continue;
if (flow_value >= 2 - LP_EPSILON) continue; struct Node *from = &digraph->nodes[i];
struct Node *to = &digraph->nodes[j];
rval = get_cut_edges_from_marks(digraph, &cut_edges_count, int cut_edges_count;
cut_edges); double flow_value;
abort_if(rval, "get_cut_edges_from_marks failed");
rval = map_cut_edges_from_digraph_to_graph(graph, &cut_edges_count, rval = flow_find_max_flow(digraph, capacities, from, to, flow,
cut_edges); &flow_value);
abort_if(rval, "map_cut_edges_from_digraph_to_graph failed"); abort_if(rval, "flow_find_max_flow failed");
rval = GTSP_add_subtour_elimination_cut_3(lp, graph, from, to, if (flow_value >= 2 * (x[i] + x[j] - 1) - LP_EPSILON)
cut_edges, cut_edges_count); continue;
abort_if(rval, "GTSP_add_subtour_elimination_cut3 failed");
(*added_cuts_count)++; rval = get_cut_edges_from_marks(digraph, &cut_edges_count, cut_edges);
} abort_if(rval, "get_cut_edges_from_marks failed");
rval = map_cut_edges_from_digraph_to_graph(graph, &cut_edges_count,
cut_edges);
abort_if(rval, "map_cut_edges_from_digraph_to_graph failed");
rval = add_subtour_elimination_cut(lp, graph, from, to, cut_edges,
cut_edges_count, 2);
abort_if(rval, "GTSP_add_subtour_elimination_cut_1 failed");
(*added_cuts_count)++;
} }
CLEANUP: CLEANUP:
if (cut_edges) free(cut_edges);
if (flow) free(flow); if (flow) free(flow);
if (cut_edges) free(cut_edges);
return rval; return rval;
} }
int GTSP_find_exact_subtour_elimination_cuts( int find_exact_subtour_elimination_cuts(
struct LP *lp, struct GTSP *data, int *added_cuts_count) struct LP *lp, struct GTSP *data, int *added_cuts_count)
{ {
int rval = 0; int rval = 0;
@ -718,24 +628,24 @@ int GTSP_find_exact_subtour_elimination_cuts(
capacities = (double *) malloc(digraph_edge_count * sizeof(double)); capacities = (double *) malloc(digraph_edge_count * sizeof(double));
abort_if(!capacities, "could not allocate capacities"); abort_if(!capacities, "could not allocate capacities");
rval = GTSP_build_flow_digraph(data, x, &digraph, capacities); rval = build_flow_digraph(data, x, &digraph, capacities);
abort_if(rval, "GTSP_build_flow_digraph failed"); abort_if(rval, "build_flow_digraph failed");
// Constraints (2.3) // Constraints (2.3)
rval = GTSP_find_exact_subtour_elimination_cuts_1(lp, data, x, &digraph, rval = find_exact_subtour_elimination_cuts_2(lp, data, x, &digraph,
capacities, added_cuts_count); capacities, added_cuts_count);
abort_if(rval, "GTSP_find_exact_subtour_elimination_cuts_1 failed"); abort_if(rval, "find_exact_subtour_elimination_cuts_2 failed");
// Constraints (2.2) // Constraints (2.2)
rval = GTSP_find_exact_subtour_elimination_cuts_2(lp, data, x, &digraph, rval = find_exact_subtour_elimination_cuts_1(lp, data, x, &digraph,
capacities, added_cuts_count); capacities, added_cuts_count);
abort_if(rval, "GTSP_find_exact_subtour_elimination_cuts_2 failed"); abort_if(rval, "find_exact_subtour_elimination_cuts_1 failed");
// Constraints (2.1) // Constraints (2.1)
rval = GTSP_find_exact_subtour_elimination_cuts_3(lp, data, &digraph, rval = find_exact_subtour_elimination_cuts_0(lp, data, &digraph, capacities,
capacities, added_cuts_count); added_cuts_count);
abort_if(rval, "GTSP_find_exact_subtour_elimination_cuts_3 failed"); abort_if(rval, "find_exact_subtour_elimination_cuts_0 failed");
// // subcluster // // subcluster
// struct Node *root = &digraph.nodes[digraph.node_count - 1]; // struct Node *root = &digraph.nodes[digraph.node_count - 1];
@ -810,8 +720,8 @@ int GTSP_find_exact_subtour_elimination_cuts(
// cut_edges[c - 1]->to->index); // cut_edges[c - 1]->to->index);
// } // }
// //
// rval = GTSP_add_subcluster_cut(lp, graph, e, cut_edges, c); // rval = add_subcluster_cut(lp, graph, e, cut_edges, c);
// abort_if(rval, "GTSP_add_subcluster_cut failed"); // abort_if(rval, "add_subcluster_cut failed");
// //
// (*added_cuts_count)++; // (*added_cuts_count)++;
// if (*added_cuts_count > 10) goto CLEANUP; // if (*added_cuts_count > 10) goto CLEANUP;
@ -850,8 +760,8 @@ int GTSP_find_exact_subtour_elimination_cuts(
// cut_edges[c - 1]->to->index); // cut_edges[c - 1]->to->index);
// } // }
// //
// rval = GTSP_add_subcluster_cut(lp, graph, e, cut_edges, c); // rval = add_subcluster_cut(lp, graph, e, cut_edges, c);
// abort_if(rval, "GTSP_add_subcluster_cut failed"); // abort_if(rval, "add_subcluster_cut failed");
// //
// (*added_cuts_count)++; // (*added_cuts_count)++;
// if (*added_cuts_count > 10) goto CLEANUP; // if (*added_cuts_count > 10) goto CLEANUP;
@ -898,9 +808,8 @@ int GTSP_add_cutting_planes(struct LP *lp, struct GTSP *data)
log_debug("Finding subtour cuts...\n"); log_debug("Finding subtour cuts...\n");
rval = GTSP_find_exact_subtour_elimination_cuts(lp, data, rval = find_exact_subtour_elimination_cuts(lp, data, &added_cuts_count);
&added_cuts_count); abort_if(rval, "find_exact_subtour_elimination_cuts failed");
abort_if(rval, "GTSP_find_exact_subtour_elimination_cuts failed");
if (added_cuts_count > 0) if (added_cuts_count > 0)
{ {
@ -945,7 +854,7 @@ int GTSP_add_cutting_planes(struct LP *lp, struct GTSP *data)
return rval; return rval;
} }
int GTSP_write_input_data(struct GTSP *data, char *filename) int GTSP_write_problem(struct GTSP *data, char *filename)
{ {
int rval = 0; int rval = 0;
@ -998,19 +907,7 @@ int GTSP_write_solution(struct GTSP *data, char *filename, double *x)
return rval; return rval;
} }
int get_edge_num(int node_count, int from, int to) int GTSP_read_solution(char *filename, double **p_x)
{
int idx = node_count;
for (int k = 0; k < from; k++)
idx += node_count - k - 1;
idx += to - from - 1;
return idx;
}
int GTSP_read_x(char *filename, double **p_x)
{ {
int rval = 0; int rval = 0;
@ -1114,8 +1011,8 @@ static int GTSP_parse_args(int argc, char **argv)
break; break;
case 'x': case 'x':
rval = GTSP_read_x(optarg, &OPTIMAL_X); rval = GTSP_read_solution(optarg, &OPTIMAL_X);
abort_if(rval, "GTSP_read_x failed"); abort_if(rval, "GTSP_read_solution failed");
break; break;
case 's': case 's':
@ -1181,7 +1078,7 @@ int GTSP_main(int argc, char **argv)
abort_if(rval, "GTSP_create_random_problem failed"); abort_if(rval, "GTSP_create_random_problem failed");
log_info("Writing random instance to file gtsp.in\n"); log_info("Writing random instance to file gtsp.in\n");
rval = GTSP_write_input_data(&data, "gtsp.in"); rval = GTSP_write_problem(&data, "gtsp.in");
abort_if(rval, "GTSP_write_problem failed"); abort_if(rval, "GTSP_write_problem failed");
bnc.best_obj_val = DBL_MAX; bnc.best_obj_val = DBL_MAX;

@ -28,11 +28,11 @@ int GTSP_init_data(struct GTSP *data);
int GTSP_init_lp(struct LP *lp, struct GTSP *data); int GTSP_init_lp(struct LP *lp, struct GTSP *data);
int GTSP_write_input_data(struct GTSP *data, char *filename); int GTSP_add_cutting_planes(struct LP *lp, struct GTSP *data);
int GTSP_write_solution(struct GTSP *data, char *filename, double *x); int GTSP_write_problem(struct GTSP *data, char *filename);
int GTSP_add_cutting_planes(struct LP *lp, struct GTSP *data); int GTSP_write_solution(struct GTSP *data, char *filename, double *x);
int GTSP_main(int argc, char **argv); int GTSP_main(int argc, char **argv);