39#define SEPA_NAME "subtour"
40#define SEPA_DESC "separator that elininates subtours of length smaller than |NCluster|"
41#define SEPA_PRIORITY 1000
43#define SEPA_MAXBOUNDDIST 0.0
44#define SEPA_USESSUBSCIP FALSE
45#define SEPA_DELAY FALSE
62 for(
i = 0;
i < cyclelength; ++
i )
82 return adjacencymatrix[n][state1][state2];
126 for( k = 0; k < nstates; ++k )
133 for( anchor = 0; anchor < nstates; ++anchor )
139 if(
SCIPisGT(
scip,
getDist(adjacencymatrix, cyclelength - 1, anchor, anchor), cyclelength - 1.0) )
141 subtours[anchor][0] = anchor;
142 if( insubtour[anchor] == -1 )
143 insubtour[anchor] = anchor;
146 for( k = 0; k < cyclelength -1; ++k )
148 currentnode = subtours[anchor][k];
150 assert(0 <= currentnode && currentnode < nstates);
156 for( l = 0; l < nsuccessors; l++ )
158 successor = successors[l];
160 assert(0 <= successor && successor < nstates);
164 +
getDist(adjacencymatrix, cyclelength - (k + 2), successor, anchor),
165 getDist(adjacencymatrix, cyclelength - (k + 1), currentnode, anchor)) )
167 subtours[anchor][k + 1] = successor;
168 insubtour[successor] = anchor;
170 if( iscontracted[currentnode][successor] != -1 )
179 subtours[anchor][cyclelength] = anchor;
182 if( iscontracted[subtours[anchor][cyclelength - 1]][anchor] != -1 )
190 if( insubtour[anchor] != anchor )
195 while( subtours[insubtour[anchor]][
c] != anchor )
198 for( k = 0; k < cyclelength && isduplicate; ++k )
200 if( subtours[insubtour[anchor]][(k +
c) % cyclelength] != subtours[anchor][k] )
209 liftabley = cyclelength - 1;
214 cyclelength, ncontractions );
220 for( k = 0; k < cyclelength; ++k )
222 currentnode = subtours[anchor][k];
223 successor = subtours[anchor][k+1];
224 intermediate = iscontracted[currentnode][successor];
226 if( intermediate != -1 )
232 greater = intermediate > currentnode ? intermediate : currentnode;
233 smaller = intermediate < currentnode ? intermediate : currentnode;
250 > 0 && liftabley > 0 )
273 for( k = 0; k < nstates; ++k )
320 for( start = 0; start < nstates; ++start )
329 path[pathlength] = end;
336 for( k = 0; k < pathlength - 1; ++k )
338 currentnode = path[k];
340 assert(0 <= currentnode && currentnode < nstates);
345 for(
i = 0;
i < nsuccessors; ++
i )
347 successor = successors[
i];
349 assert(0 <= successor && successor < nstates);
352 +
getDist(adjacencymatrix, pathlength - (k + 2), successor, end),
353 getDist(adjacencymatrix, pathlength - (k + 1), currentnode, end)) )
355 path[k + 1] = successor;
357 if( iscontracted[currentnode][successor] != -1 )
366 if( iscontracted[path[pathlength - 1]][end] != -1 )
369 if( iscontracted[start][end] != -1 )
377 start, end, pathlength, ncontractions );
383 for( k = 0; k < pathlength; ++k )
385 currentnode = path[k];
386 successor = path[k+1];
387 intermediate = iscontracted[currentnode][successor];
389 if( intermediate != -1 )
425 intermediate = iscontracted[start][end];
427 if( iscontracted[start][end] != -1 )
481 int* succerssorsstart;
482 int nsuccessorsstart;
500 for( start = 0; start < nstates; ++start )
506 for( j = 0; j < nsuccessorsstart; ++j )
510 end = succerssorsstart[j];
511 tour[tourlength] = end;
518 for( k = 0; k < tourlength - 1; ++k )
520 currentnode = tour[k];
524 for(
i = 0;
i < nsuccessors; ++
i )
526 successor = successors[
i];
529 +
getDist(adjacencymatrix, tourlength - (k + 2), successor, end)
530 ,
getDist(adjacencymatrix, tourlength - (k + 1), currentnode, end)) )
532 tour[k + 1] = successor;
534 if( iscontracted[currentnode][successor] != -1 )
542 if( iscontracted[tour[tourlength - 1]][end] != -1 )
544 if( iscontracted[end][start] != -1 )
549 start, end, tourlength, ncontractions );
555 for( k = 0; k < tourlength; ++k )
557 currentnode = tour[k];
558 successor = tour[k+1];
559 intermediate = iscontracted[currentnode][successor];
561 if( intermediate != -1 )
574 intermediate = iscontracted[end][start];
575 if( iscontracted[end][start] != -1 )
631 foundviolation =
FALSE;
634 for( currentnode = 0; currentnode <
nnodes; ++currentnode )
639 for( l = 0; l < nintermediates; ++l )
641 intermediate = intermediates[l];
645 for( successor = 0; successor <
nnodes; ++successor )
651 +
getDist(adjacencymatrix,
narcs - 2, intermediate, successor),
652 getDist(adjacencymatrix,
narcs - 1, currentnode, successor)) )
654 adjacencymatrix[
narcs - 1][currentnode][successor] =
getDist(adjacencymatrix, 0, currentnode, intermediate)
655 +
getDist(adjacencymatrix,
narcs - 2, intermediate, successor);
663 for( currentnode = 0; currentnode <
nnodes; ++currentnode )
666 foundviolation =
TRUE;
668 return foundviolation;
727 assert(ncluster > 0 && ncluster < nstates);
734 for( k = 0; k < ncluster; ++k )
738 for( j = 0; j < nstates; ++j )
750 for(
i = 0;
i < nstates; ++
i )
754 for( j = 0; j < nstates; ++j )
756 iscontracted[
i][j] = -1;
766 for(
i = 0;
i < nstates; ++
i )
775 for( j = 0; j < nsuccessors1; ++j )
777 state2 = successors1[j];
784 for( k = 0 ; k < nsuccessors2; ++k )
786 state3 = successors2[k];
788 if( edgevars[state1][state2] ==
NULL || edgevars[state2][state3] ==
NULL || edgevars[state1][state3] ==
NULL )
798 iscontracted[state1][state3] = state2;
805 for(
i = 0;
i < nstates; ++
i )
807 for( j = 0; j < nstates; ++j )
821 while( cyclelength < ncluster )
836 if( cyclelength == ncluster - 1 )
853 for(
i = 0;
i < nstates; ++
i )
859 for(
i = 0;
i < ncluster; ++
i )
861 for( j = 0; j < nstates; ++j )
884 sepaExeclpSubtour,
NULL,
Constraint handler for linear constraints in their most general form, .
#define SCIP_STRINGEQ(name, reference, retcode)
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
#define SCIPallocMemoryArray(scip, ptr, num)
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
#define SCIPfreeMemoryArray(scip, ptr)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa,)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
int SCIPsnprintf(char *t, int len, const char *s,...)
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_VAR **** SCIPcycGetEdgevars(SCIP *scip)
int SCIPcycGetNBins(SCIP *scip)
SCIP_VAR * getEdgevar(SCIP_VAR ****edgevars, int state1, int state2, EDGETYPE edgetype)
int SCIPcycGetNCluster(SCIP *scip)
SCIP_DIGRAPH * SCIPcycGetEdgeGraph(SCIP *scip)
problem data for cycle clustering problem
public data structures and miscellaneous methods
#define SEPA_MAXBOUNDDIST
static SCIP_RETCODE addSubtourCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_Real ***adjacencymatrix, SCIP_DIGRAPH *adjacencygraph, int **iscontracted, int cyclelength, SCIP_RESULT *result, int *ncuts)
static SCIP_RETCODE addPathCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_Real ***adjacencymatrix, SCIP_DIGRAPH *adjacencygraph, int **iscontracted, int pathlength, SCIP_RESULT *result, int *ncuts)
static SCIP_Real getDist(SCIP_Real ***adjacencymatrix, int n, int state1, int state2)
static SCIP_RETCODE addTourCuts(SCIP *scip, SCIP_SEPA *sepa, SCIP_Real ***adjacencymatrix, SCIP_DIGRAPH *adjacencygraph, int **iscontracted, int tourlength, SCIP_RESULT *result, int *ncuts)
static SCIP_Bool computeNextAdjacency(SCIP *scip, SCIP_Real ***adjacencymatrix, SCIP_DIGRAPH *adjacencygraph, int narcs)
SCIP_RETCODE SCIPincludeSepaSubtour(SCIP *scip)
Separate Subtours-Elimination inequalities in Cycle-Clustering Applications.
struct SCIP_Digraph SCIP_DIGRAPH
enum SCIP_Result SCIP_RESULT
enum SCIP_Retcode SCIP_RETCODE
#define SCIP_DECL_SEPAEXECLP(x)
struct SCIP_Sepa SCIP_SEPA
#define SCIP_DECL_SEPACOPY(x)