|
|
@ -385,56 +385,26 @@ int GTSP_add_subtour_elimination_cut_3(
|
|
|
|
return rval;
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int GTSP_find_exact_subtour_elimination_cuts(
|
|
|
|
int GTSP_build_flow_digraph(struct GTSP *data, double *x, struct Graph *digraph, double *capacities)
|
|
|
|
struct LP *lp, struct GTSP *data, int *added_cuts_count)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int rval = 0;
|
|
|
|
int rval = 0;
|
|
|
|
|
|
|
|
|
|
|
|
int *clusters = data->clusters;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double *x = 0;
|
|
|
|
|
|
|
|
double *capacities = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double *flow = 0;
|
|
|
|
|
|
|
|
struct Edge **cut_edges = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int *digraph_edges = 0;
|
|
|
|
int *digraph_edges = 0;
|
|
|
|
|
|
|
|
|
|
|
|
struct Graph *graph = data->graph;
|
|
|
|
struct Graph *graph = data->graph;
|
|
|
|
int node_count = graph->node_count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int num_cols = LP_get_num_cols(lp);
|
|
|
|
|
|
|
|
x = (double *) malloc(num_cols * sizeof(double));
|
|
|
|
|
|
|
|
abort_if(!x, "could not allocate x");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rval = LP_get_x(lp, x);
|
|
|
|
int node_count = graph->node_count;
|
|
|
|
abort_if(rval, "LP_get_x failed");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Graph digraph;
|
|
|
|
|
|
|
|
graph_init(&digraph);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int digraph_edge_count = 4 * graph->edge_count + 2 * graph->node_count +
|
|
|
|
int digraph_edge_count = 4 * graph->edge_count + 2 * graph->node_count +
|
|
|
|
2 * data->cluster_count;
|
|
|
|
2 * data->cluster_count;
|
|
|
|
int digraph_node_count = node_count + data->cluster_count + 1;
|
|
|
|
int digraph_node_count = node_count + data->cluster_count + 1;
|
|
|
|
|
|
|
|
|
|
|
|
digraph_edges = (int *) malloc(2 * digraph_edge_count * sizeof(int));
|
|
|
|
digraph_edges = (int *) malloc(2 * digraph_edge_count * sizeof(int));
|
|
|
|
flow = (double *) malloc(digraph_edge_count * sizeof(double));
|
|
|
|
|
|
|
|
capacities = (double *) malloc(digraph_edge_count * sizeof(double));
|
|
|
|
|
|
|
|
cut_edges =
|
|
|
|
|
|
|
|
(struct Edge **) malloc(digraph_edge_count * sizeof(struct Edge *));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abort_if(!digraph_edges, "could not allocate digraph_edges");
|
|
|
|
|
|
|
|
abort_if(!flow, "could not allocate flow");
|
|
|
|
|
|
|
|
abort_if(!capacities, "could not allocate capacities");
|
|
|
|
|
|
|
|
abort_if(!cut_edges, "could not allocate cut_edges");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create four directed edges for each edge of the original graph
|
|
|
|
// Create four directed edges for each edge of the original graph
|
|
|
|
int ke = 0;
|
|
|
|
int ke = 0;
|
|
|
|
int kc = 0;
|
|
|
|
int kc = 0;
|
|
|
|
for (int i = 0; i < graph->edge_count; i++)
|
|
|
|
for (int i = 0; i < graph->edge_count; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
assert(node_count + i < num_cols);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Edge *e = &graph->edges[i];
|
|
|
|
struct Edge *e = &graph->edges[i];
|
|
|
|
int from = e->from->index;
|
|
|
|
int from = e->from->index;
|
|
|
|
int to = e->to->index;
|
|
|
|
int to = e->to->index;
|
|
|
@ -489,30 +459,78 @@ int GTSP_find_exact_subtour_elimination_cuts(
|
|
|
|
assert(kc == digraph_edge_count);
|
|
|
|
assert(kc == digraph_edge_count);
|
|
|
|
|
|
|
|
|
|
|
|
rval = graph_build(digraph_node_count, digraph_edge_count, digraph_edges, 1,
|
|
|
|
rval = graph_build(digraph_node_count, digraph_edge_count, digraph_edges, 1,
|
|
|
|
&digraph);
|
|
|
|
digraph);
|
|
|
|
abort_if(rval, "graph_build failed");
|
|
|
|
abort_if(rval, "graph_build failed");
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < digraph_edge_count; i += 2)
|
|
|
|
for (int i = 0; i < digraph_edge_count; i += 2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
digraph.edges[i].reverse = &digraph.edges[i + 1];
|
|
|
|
digraph->edges[i].reverse = &digraph->edges[i + 1];
|
|
|
|
digraph.edges[i + 1].reverse = &digraph.edges[i];
|
|
|
|
digraph->edges[i + 1].reverse = &digraph->edges[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int max_x_index = 0;
|
|
|
|
|
|
|
|
double max_x = DBL_MIN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < node_count; i++)
|
|
|
|
CLEANUP:
|
|
|
|
|
|
|
|
return rval;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int GTSP_find_exact_subtour_elimination_cuts(
|
|
|
|
|
|
|
|
struct LP *lp, struct GTSP *data, int *added_cuts_count)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int rval = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double *x = 0;
|
|
|
|
|
|
|
|
double *flow = 0;
|
|
|
|
|
|
|
|
double *capacities = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Edge **cut_edges = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int *clusters = data->clusters;
|
|
|
|
|
|
|
|
struct Graph *graph = data->graph;
|
|
|
|
|
|
|
|
int node_count = graph->node_count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int num_cols = LP_get_num_cols(lp);
|
|
|
|
|
|
|
|
x = (double *) malloc(num_cols * sizeof(double));
|
|
|
|
|
|
|
|
abort_if(!x, "could not allocate x");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rval = LP_get_x(lp, x);
|
|
|
|
|
|
|
|
abort_if(rval, "LP_get_x failed");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Graph digraph;
|
|
|
|
|
|
|
|
graph_init(&digraph);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int digraph_edge_count = 4 * graph->edge_count + 2 * graph->node_count +
|
|
|
|
|
|
|
|
2 * data->cluster_count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
flow = (double *) malloc(digraph_edge_count * sizeof(double));
|
|
|
|
|
|
|
|
capacities = (double *) malloc(digraph_edge_count * sizeof(double));
|
|
|
|
|
|
|
|
cut_edges =
|
|
|
|
|
|
|
|
(struct Edge **) malloc(digraph_edge_count * sizeof(struct Edge *));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
abort_if(!flow, "could not allocate flow");
|
|
|
|
|
|
|
|
abort_if(!capacities, "could not allocate capacities");
|
|
|
|
|
|
|
|
abort_if(!cut_edges, "could not allocate cut_edges");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rval = GTSP_build_flow_digraph(data, x, &digraph, capacities);
|
|
|
|
|
|
|
|
abort_if(rval, "GTSP_build_flow_digraph failed");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Constraints (2.3)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct Node *n = &graph->nodes[i];
|
|
|
|
int max_x_index = 0;
|
|
|
|
if (x[n->index] > max_x)
|
|
|
|
double max_x = DBL_MIN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < node_count; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
max_x = x[n->index];
|
|
|
|
struct Node *n = &graph->nodes[i];
|
|
|
|
max_x_index = i;
|
|
|
|
if (x[n->index] > max_x)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
max_x = x[n->index];
|
|
|
|
|
|
|
|
max_x_index = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Constraints (2.3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i = max_x_index;
|
|
|
|
int i = max_x_index;
|
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < node_count; j++)
|
|
|
|
for (int j = 0; j < node_count; j++)
|
|
|
@ -681,7 +699,7 @@ int GTSP_find_exact_subtour_elimination_cuts(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// subcluster
|
|
|
|
// subcluster
|
|
|
|
struct Node *root = &digraph.nodes[digraph_node_count - 1];
|
|
|
|
struct Node *root = &digraph.nodes[digraph.node_count - 1];
|
|
|
|
for (int e_index = 0; e_index < graph->edge_count; e_index++)
|
|
|
|
for (int e_index = 0; e_index < graph->edge_count; e_index++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct Edge *e = &graph->edges[e_index];
|
|
|
|
struct Edge *e = &graph->edges[e_index];
|
|
|
@ -821,7 +839,6 @@ int GTSP_find_exact_subtour_elimination_cuts(
|
|
|
|
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
CLEANUP:
|
|
|
|
graph_free(&digraph);
|
|
|
|
graph_free(&digraph);
|
|
|
|
if (digraph_edges) free(digraph_edges);
|
|
|
|
|
|
|
|
if (flow) free(flow);
|
|
|
|
if (flow) free(flow);
|
|
|
|
if (cut_edges) free(cut_edges);
|
|
|
|
if (cut_edges) free(cut_edges);
|
|
|
|
if (capacities) free(capacities);
|
|
|
|
if (capacities) free(capacities);
|
|
|
|