Scippy

    SCIP

    Solving Constraint Integer Programs

    probdata_cyc.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file probdata_cyc.c
    26 * @brief problem data for cycle clustering problem
    27 * @author Leon Eifler
    28 *
    29 * This file implements the problem data for the cycle clustering problem.
    30 *
    31 * The problem data contains original transition matrix, the scaling parameter that appears in the objective function,
    32 * and all variables that appear in the problem.
    33 */
    34
    35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    36#include "probdata_cyc.h"
    37
    38#include "scip/cons_nonlinear.h"
    39#include "scip/cons_linear.h"
    40#include "scip/cons_logicor.h"
    41#include "scip/var.h"
    42#include <assert.h>
    43
    44struct SCIP_ProbData
    45{
    46 SCIP_VAR**** edgevars; /**< variables for the edges (pairs of states) inside and between consecutive clusters */
    47 SCIP_DIGRAPH* edgegraph; /**< digraph which tells us which variables are actually created */
    48 SCIP_VAR*** binvars; /**< variable-matrix belonging to the state(bin)-cluster assignment */
    49 SCIP_Real** cmatrix; /**< matrix to save the transition matrix */
    50 SCIP_Real scale; /**< the weight-factor for the coherence in the objective function */
    51 char model_variant; /**< the model that is used. w for weighted objective, e for normal edge-representation */
    52 int nbins; /**< the number of states */
    53 int ncluster; /**< the number of clusters */
    54};
    55
    56/** Check if the clustering has exactly one state in every cluster. */
    58 SCIP* scip, /**< SCIP data structure */
    59 SCIP_Real** solclustering, /**< matrix with the clustering */
    60 int nbins, /**< the number of bins */
    61 int ncluster /**< the number of clusters */
    62 )
    63{
    64 int i;
    65 int j;
    66
    67 /* check if the assignment violates paritioning, e.g. because we are in a subscip */
    68 for( i = 0; i < nbins; ++i )
    69 {
    70 SCIP_Real sum = 0.0;
    71
    72 for( j = 0; j < ncluster; ++j )
    73 {
    74 if( !SCIPisIntegral(scip, solclustering[i][j]) )
    75 return FALSE;
    76 if( !SCIPisZero(scip, solclustering[i][j]) )
    77 sum += solclustering[i][j];
    78 }
    79 if( !SCIPisEQ(scip, sum, 1.0) )
    80 return FALSE;
    81
    82 }
    83
    84 return TRUE;
    85}
    86
    87/** Assign the variables in scip according to the found clustering. */
    89 SCIP* scip, /**< SCIP data structure */
    90 SCIP_SOL* sol, /**< the SCIP solution */
    91 SCIP_Real** clustering, /**< the matrix with the clusterassignment */
    92 int nbins, /**< the number of bins */
    93 int ncluster /**< the number of cluster */
    94 )
    95{
    96 SCIP_VAR* var;
    97 SCIP_VAR*** binvars;
    98 SCIP_VAR**** edgevars;
    99 int i;
    100 int j;
    101 int c;
    102
    103 binvars = SCIPcycGetBinvars(scip);
    104 edgevars = SCIPcycGetEdgevars(scip);
    105
    106 assert(nbins > 0 && ncluster > 0);
    107 assert(binvars != NULL);
    108 assert(edgevars != NULL);
    109
    110 for ( c = 0; c < ncluster; ++c )
    111 {
    112 /* set values of state-variables */
    113 for ( i = 0; i < nbins; ++i )
    114 {
    115 if( NULL != binvars[i][c] )
    116 {
    117 if( SCIPvarIsTransformed(binvars[i][c]) )
    118 var = binvars[i][c];
    119 else
    120 var = SCIPvarGetTransVar(binvars[i][c] );
    121
    122 /* check if the clusterassignment is feasible for the variable bounds. If not do not assign the variable */
    123 if( var != NULL && SCIPisLE(scip, SCIPvarGetLbGlobal(var), clustering[i][c]) &&
    124 SCIPisGE(scip, SCIPvarGetUbGlobal(var), clustering[i][c]) &&
    126 {
    127 SCIP_CALL( SCIPsetSolVal( scip, sol, var, clustering[i][c]) );
    128 }
    129
    130 assert(SCIPisIntegral(scip, clustering[i][c]));
    131 }
    132 }
    133
    134 /* set the value for the edgevariables for each pair of states */
    135 for( i = 0; i < nbins; ++i )
    136 {
    137 for( j = 0; j < i; ++j )
    138 {
    139 if( NULL == edgevars[i][j] || NULL == edgevars[j][i])
    140 continue;
    141
    142 /* check if bins are in same cluster */
    143 if( SCIPisEQ(scip, 1.0, clustering[i][c] * clustering[j][c]) )
    144 {
    145 var = edgevars[i][j][INCLUSTER];
    146 if( var != NULL && SCIPisGE(scip, SCIPvarGetUbGlobal(var), clustering[j][c] * clustering[i][c])
    148 {
    149 SCIP_CALL( SCIPsetSolVal( scip, sol, var, 1.0 ) );
    150 }
    151 }
    152
    153 /* check if bins are in consecutive clusters */
    154 else if( SCIPisEQ(scip, 1.0, clustering[i][c] * clustering[j][phi(c, ncluster)]) )
    155 {
    156 var = edgevars[i][j][CONSECUTIVE_CLUSTER];
    157 if( var != NULL && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR &&
    158 SCIPisGE(scip, SCIPvarGetUbGlobal(var), clustering[j][phi(c, ncluster)] * clustering[i][c]) )
    159 {
    160 SCIP_CALL( SCIPsetSolVal( scip, sol, var, 1.0 ) );
    161 }
    162 }
    163
    164 else if( SCIPisEQ(scip, 1.0, clustering[j][c] * clustering[i][phi(c, ncluster)]) )
    165 {
    166 var = edgevars[j][i][CONSECUTIVE_CLUSTER];
    167 if( var != NULL && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR &&
    168 SCIPisGE(scip, SCIPvarGetUbGlobal(var), clustering[j][c] * clustering[i][phi(c, ncluster)]) )
    169 {
    170 SCIP_CALL( SCIPsetSolVal( scip, sol, var, 1.0 ) );
    171 }
    172 }
    173 }
    174 }
    175 }
    176
    177 return SCIP_OKAY;
    178}
    179
    180/** function that returns the successive cluster along the cycle */
    181int phi(
    182 int k, /**< the cluster */
    183 int ncluster /**< the number of clusters*/
    184 )
    185{
    186 assert(k < ncluster && k >= 0);
    187 assert(ncluster > 0);
    188
    189 return (k+1) % ncluster;
    190}
    191
    192/** function that returns the predecessor-cluster along the cycle */
    194 int k, /**< the cluster */
    195 int ncluster /**< the number of clusters */
    196 )
    197{
    198 assert(k < ncluster && k >= 0);
    199 assert(ncluster > 0);
    200
    201 if( k - 1 < 0 )
    202 return ncluster - 1;
    203 else
    204 return k - 1;
    205}
    206
    207/** creates all the variables for the problem. The constraints are added later, depending on the model that is used */
    208static
    210 SCIP* scip, /**< SCIP data Structure */
    211 SCIP_PROBDATA* probdata /**< the problem data */
    212 )
    213{
    214 int i;
    215 int j;
    216 int c;
    217 EDGETYPE edgetype;
    218 int nbins = probdata->nbins;
    219 int ncluster = probdata->ncluster;
    220 char varname[SCIP_MAXSTRLEN];
    221
    222 /* create variables for bins */
    224 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->binvars), nbins) );
    225
    226 for( i = 0; i < nbins; ++i )
    227 {
    228 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->binvars[i]), ncluster) ); /*lint !e866*/
    229 }
    230
    231 for( i = 0; i < nbins; ++i )
    232 {
    233 for( c = 0; c < ncluster; ++c )
    234 {
    235 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x_%d_%d", i, c);
    236 SCIP_CALL( SCIPcreateVarBasic(scip, &probdata->binvars[i][c], varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY) );
    237 SCIP_CALL( SCIPaddVar(scip, probdata->binvars[i][c]) );
    238 }
    239 }
    240
    241 /* create variables for the edges in each cluster combination.*/
    242 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->edgevars), nbins) );
    243
    244 for( i = 0; i < nbins; ++i )
    245 {
    246 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(probdata->edgevars[i]), nbins) ); /*lint !e866*/
    247
    248 for( j = 0; j < nbins; ++j )
    249 {
    250 if( i == j || (SCIPisZero(scip, (probdata->cmatrix[i][j] - probdata->cmatrix[j][i]))
    251 && SCIPisZero(scip, (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) )) )
    252 continue;
    253
    254 SCIP_CALL( SCIPdigraphAddArc(probdata->edgegraph, i, j, NULL) );
    255
    256 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(probdata->edgevars[i][j]), 3) ); /*lint !e866*/
    257
    258 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    259 {
    260 if( edgetype == INCLUSTER && i < j )
    261 continue;
    262
    263 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "y_%d_%d_%d", i, j, edgetype);
    264 SCIP_CALL( SCIPcreateVarBasic(scip, &probdata->edgevars[i][j][edgetype], varname,
    265 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY) );
    266 SCIP_CALL( SCIPaddVar(scip, probdata->edgevars[i][j][edgetype]) );
    267 }
    268 }
    269 }
    270
    271 return SCIP_OKAY;
    272}
    273
    274/** create the problem without variable amount of clusters, use simpler non-facet-defining inequalities */
    275static
    277 SCIP* scip, /**< SCIP Data Structure */
    278 SCIP_PROBDATA* probdata /**< the problem data */
    279 )
    280{
    281 int i;
    282 int j;
    283 int c1;
    284 int c2;
    285 EDGETYPE edgetype;
    286 char consname[SCIP_MAXSTRLEN];
    287 SCIP_CONS* temp;
    288 int nbins = probdata->nbins;
    289 int ncluster = probdata->ncluster;
    290 SCIP_Real scale;
    291
    292 SCIP_CALL( SCIPgetRealParam(scip, "cycleclustering/scale_coherence", &scale) );
    293 probdata->scale = scale;
    294
    295 /* create constraints */
    296
    297 /* create the set-partitioning constraints of the bins */
    298 for( i = 0; i < nbins; ++i )
    299 {
    300 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "setpart_%d", i+1 );
    302 FALSE, FALSE, FALSE) );
    303
    304 for ( c1 = 0; c1 < ncluster; ++c1 )
    305 {
    306 SCIP_CALL( SCIPaddCoefSetppc(scip, temp, probdata->binvars[i][c1]) );
    307 }
    308 SCIP_CALL( SCIPaddCons(scip, temp) );
    309 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    310 }
    311
    312 /* create constraints for the edge-cut variables */
    313 SCIPinfoMessage(scip, NULL, "Using edge-representation with simplified structure. Fixed amount of cluster. \n");
    314 for( i = 0; i < nbins; ++i )
    315 {
    316 for( j = 0; j < i; ++j )
    317 {
    318 if( probdata->edgevars[i][j] == NULL )
    319 continue;
    320
    321 /* these edges are not within a cluster */
    322 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][INCLUSTER],
    323 (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    324
    325 /* these are the edges that are between consequtive clusters */
    326 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], (probdata->cmatrix[i][j] - probdata->cmatrix[j][i])) );
    327 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], (probdata->cmatrix[j][i] - probdata->cmatrix[i][j])) );
    328
    329 /* create constraints that determine when the edge-variables have to be non-zero */
    330 for( c1 = 0; c1 < ncluster; ++c1 )
    331 {
    332 /* constraints for edges within clusters */
    333 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d", i+1, j+1, c1+1 );
    334 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    336
    337 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], -1.0) );
    338 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    339 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], 1.0) );
    340
    341 SCIP_CALL( SCIPaddCons(scip, temp) );
    342 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    343
    344 /* constraints for edges between clusters */
    345 for( c2 = 0; c2 < ncluster; ++c2 )
    346 {
    347 SCIP_VAR* var;
    348
    349 if( c2 == c1 )
    350 continue;
    351
    352 if( c2 == c1 + 1 || ( c2 == 0 && c1 == ncluster -1) )
    353 var = probdata->edgevars[i][j][CONSECUTIVE_CLUSTER];
    354 else if( c2 == c1 - 1 || ( c1 == 0 && c2 == ncluster -1) )
    355 var = probdata->edgevars[j][i][CONSECUTIVE_CLUSTER];
    356 else
    357 var = probdata->edgevars[i][j][NON_CONSECUTIVE_CLUSTER];
    358
    359 /* if two bins are in a different cluster -> the corresponding edge must be cut */
    360 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_inclusters_%d_%d", i+1, j+1, c1+1, c2+1 );
    361 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    363
    364 SCIP_CALL( SCIPaddCoefLinear(scip, temp, var, -1.0) );
    365 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    366 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c2], 1.0) );
    367
    368 SCIP_CALL( SCIPaddCons(scip, temp) );
    369 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    370 }
    371 }
    372 }
    373 }
    374
    375 /* only one cluster-pair at the same time can be active for an edge*/
    376 for( i = 0; i < nbins; ++i )
    377 {
    378 for( j = 0; j < i; ++j )
    379 {
    380 if( NULL == probdata->edgevars[i][j] )
    381 continue;
    382
    383 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "sumedge_%d_%d", i+1, j+1 );
    384 SCIP_CALL( SCIPcreateConsBasicLinear(scip, &temp, consname, 0, NULL, NULL, 1.0, 1.0 ) );
    385
    386 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    387 {
    388 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][edgetype], 1.0) );
    389 }
    390 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], 1.0) );
    391
    392 SCIP_CALL( SCIPaddCons(scip, temp) );
    393 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    394 }
    395 }
    396
    397 /* add constraint that ensures that each cluster is used */
    398 for( c1 = 0; c1 < ncluster; ++c1 )
    399 {
    400 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cluster_%d_used", c1+1 );
    401 SCIP_CALL( SCIPcreateConsBasicLogicor(scip, &temp, consname, 0, NULL) );
    402
    403 for( i = 0; i < nbins; ++i )
    404 {
    405 SCIP_CALL( SCIPaddCoefLogicor(scip, temp, probdata->binvars[i][c1]) );
    406 }
    407
    408 SCIP_CALL( SCIPaddCons(scip, temp) );
    409 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    410 }
    411
    412 return SCIP_OKAY;
    413}
    414
    415/** create the problem without variable amount of clusters, using three edge-variables for each pair of states.
    416 * This is the tested default version.
    417 */
    418static
    420 SCIP* scip, /**< SCIP Data Structure */
    421 SCIP_PROBDATA* probdata /**< The problem data */
    422 )
    423{
    424 int i;
    425 int j;
    426 int c1;
    427 EDGETYPE edgetype;
    428 int nbins = probdata->nbins;
    429 int ncluster = probdata->ncluster;
    430 char consname[SCIP_MAXSTRLEN];
    431 SCIP_CONS* temp;
    432 SCIP_Real scale;
    433
    434 SCIP_CALL( SCIPgetRealParam(scip, "cycleclustering/scale_coherence", &scale) );
    435 probdata->scale = scale;
    436
    437 /* create constraints */
    438
    439 /* create the set-partitioning constraints of the bins */
    440 for( i = 0; i < nbins; ++i )
    441 {
    442 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "setpart_%d", i+1);
    443 SCIP_CALL( SCIPcreateConsSetpart(scip, &temp, consname, 0, NULL, TRUE, TRUE, TRUE, TRUE, TRUE,
    444 FALSE, FALSE, FALSE, FALSE, FALSE) );
    445
    446 for ( c1 = 0; c1 < ncluster; ++c1 )
    447 {
    448 SCIP_CALL( SCIPaddCoefSetppc(scip, temp, probdata->binvars[i][c1]) );
    449 }
    450
    451 SCIP_CALL( SCIPaddCons(scip, temp) );
    452 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    453 }
    454
    455 /* create constraints for the edge-variables */
    457 "Using edge-representation with simplified structure. No variable amount of cluster. \n");
    458
    459 for( i = 0; i < nbins; ++i )
    460 {
    461 for( j = 0; j < i; ++j )
    462 {
    463 if( NULL == probdata->edgevars[i][j] )
    464 continue;
    465
    466 /* the general formulation is needed if there are more than 3 clusters. In the case of three clusters the
    467 * formulation is simplified
    468 */
    469 if( ncluster > 3 )
    470 {
    471 /* these edges are within a cluster */
    472 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][INCLUSTER],
    473 (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    474
    475 /* these are the edges that are between consequtive clusters */
    476 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER],
    477 (probdata->cmatrix[i][j] - probdata->cmatrix[j][i])) );
    478 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER],
    479 (probdata->cmatrix[j][i] - probdata->cmatrix[i][j])) );
    480
    481 /* create constraints that determine when the edge-variables have to be non-zero*/
    482 for( c1 = 0; c1 < ncluster; ++c1 )
    483 {
    484 /* constraints for edges within clusters and between clusters*/
    485 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d", i, j, c1);
    486 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    488
    489 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], -1.0) );
    490 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    491 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], 1.0) );
    492 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], 1.0) );
    493 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phiinv(c1, ncluster)], -1.0) );
    494 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phi(c1, ncluster)], -1.0) );
    495
    496 SCIP_CALL( SCIPaddCons(scip, temp) );
    497 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    498
    499 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_part2_%d", i, j, c1);
    500 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    502
    503 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], -1.0) );
    504 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    505 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], 1.0) );
    506 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], 1.0) );
    507 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phi(c1, ncluster)], -1.0) );
    508 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phiinv(c1, ncluster)], -1.0) );
    509
    510 SCIP_CALL( SCIPaddCons(scip, temp) );
    511 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    512
    513 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d_%d", i, j, c1, phi(c1, ncluster));
    514 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    516
    517 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], -1.0) );
    518 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    519 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phi(c1, ncluster)], 1.0) );
    520 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], 1.0) );
    521 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phi(c1, ncluster)], -1.0) );
    522 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], -1.0) );
    523
    524 SCIP_CALL( SCIPaddCons(scip, temp) );
    525 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    526
    527 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d_%d", i, j, c1, phiinv(c1, ncluster));
    528 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    530
    531 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], -1.0) );
    532 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    533 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phiinv(c1,ncluster)], 1.0) );
    534 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], 1.0) );
    535 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phiinv(c1, ncluster)], -1.0) );
    536 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], -1.0) );
    537
    538 SCIP_CALL( SCIPaddCons(scip, temp) );
    539 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    540 }
    541 }
    542 /* some variables become obsolete with three clusters */
    543 else
    544 {
    545 /* these are the edges that are between consequtive clusters */
    546 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER],
    547 (probdata->cmatrix[i][j] - probdata->cmatrix[j][i])
    548 - (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    549 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER],
    550 (probdata->cmatrix[j][i] - probdata->cmatrix[i][j])
    551 - (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    552
    553 SCIP_CALL( SCIPaddOrigObjoffset(scip, (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    554
    555 /* create constraints that determine when the edge-variables have to be non-zero*/
    556 for( c1 = 0; c1 < ncluster; ++c1 )
    557 {
    558 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d", i, j, c1);
    559 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    561 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], -1.0) );
    562
    563 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], 1.0) );
    564 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][c1], 1.0) );
    565 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phi(c1, ncluster)], 1.0) );
    566 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phiinv(c1, ncluster)], -1.0) );
    567 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phiinv(c1, ncluster)], -1.0) );
    568
    569 SCIP_CALL( SCIPaddCons(scip, temp) );
    570 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    571
    572 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d_incluster_%d", j, i, c1);
    573 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    575
    576 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], -1.0) );
    577 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], 1.0) );
    578 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][c1], 1.0) );
    579 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phi(c1, ncluster)], 1.0) );
    580 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[i][phiinv(c1, ncluster)], -1.0) );
    581 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->binvars[j][phiinv(c1, ncluster)], -1.0) );
    582
    583 SCIP_CALL( SCIPaddCons(scip, temp) );
    584 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    585 }
    586 }
    587 }
    588 }
    589
    590 /* only one cluster-pair at the same time can be active for an edge*/
    591 for( i = 0; i < nbins; ++i )
    592 {
    593 for( j = 0; j < i; ++j )
    594 {
    595 if( NULL == probdata->edgevars[i][j] || (SCIPisZero(scip, (probdata->cmatrix[i][j] - probdata->cmatrix[j][i]))
    596 && SCIPisZero(scip, (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) ) )
    597 continue;
    598
    599 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "sumedge_%d_%d", i, j);
    600 SCIP_CALL( SCIPcreateConsBasicLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0) );
    601
    602 for( edgetype = INCLUSTER; edgetype <= CONSECUTIVE_CLUSTER; ++edgetype )
    603 {
    604 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][edgetype], 1.0) );
    605 }
    606
    607 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], 1.0) );
    608
    609 SCIP_CALL( SCIPaddCons(scip, temp) );
    610 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    611 }
    612 }
    613
    614 /* add constraint that ensures that each cluster is used */
    615 for( c1 = 0; c1 < ncluster; ++c1 )
    616 {
    617 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cluster_%d_used", c1);
    618 SCIP_CALL( SCIPcreateConsBasicLogicor(scip, &temp, consname, 0, NULL) );
    619
    620 for( i = 0; i < nbins; ++i )
    621 {
    622 SCIP_CALL( SCIPaddCoefLogicor(scip, temp, probdata->binvars[i][c1]) );
    623 }
    624
    625 SCIP_CALL( SCIPaddCons(scip, temp) );
    626 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    627 }
    628
    629 return SCIP_OKAY;
    630}
    631
    632/** create the problem without variable amount of clusters, using quadratic formulations. This is inferior to the
    633 * simplified variant. Only useful for comparing relaxations.
    634 */
    635static
    637 SCIP* scip, /**< SCIP Data Structure */
    638 SCIP_PROBDATA* probdata /**< The problem data */
    639 )
    640{
    641 SCIP_VAR** quadvars1;
    642 SCIP_VAR** quadvars2;
    643 SCIP_VAR** edgevars;
    644 SCIP_Real* quadcoefs;
    645 SCIP_CONS* temp;
    646 SCIP_Real scale;
    647 char varname[SCIP_MAXSTRLEN];
    648 char consname[SCIP_MAXSTRLEN];
    649 int i;
    650 int j;
    651 int c1;
    652 int c;
    653 int nbins = probdata->nbins;
    654 int ncluster = probdata->ncluster;
    655
    656 SCIP_CALL( SCIPgetRealParam(scip, "cycleclustering/scale_coherence", &scale) );
    657 probdata->scale = scale;
    658 /* create variables for bins */
    660
    661 /* allocate memory to create nonlinear constraints */
    662 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars1, nbins * nbins) );
    663 SCIP_CALL( SCIPallocBufferArray(scip, &quadvars2, nbins * nbins) );
    664 SCIP_CALL( SCIPallocBufferArray(scip, &quadcoefs, nbins * nbins) );
    665
    666 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->binvars), nbins) );
    667
    668 for( i = 0; i < nbins; ++i )
    669 {
    670 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->binvars[i]), ncluster) ); /*lint !e866*/
    671 }
    672
    673 for( i = 0; i < nbins; ++i )
    674 {
    675 for( c = 0; c < ncluster; ++c )
    676 {
    677 (void)SCIPsnprintf(varname, SCIP_MAXSTRLEN, "x_%d_%d", i, c);
    678 SCIP_CALL( SCIPcreateVarBasic(scip, &probdata->binvars[i][c], varname, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY) );
    679 SCIP_CALL( SCIPaddVar(scip, probdata->binvars[i][c]) );
    680 }
    681 }
    682
    683 /* create variables for the edges in each cluster combination. Index 0 are edges within cluster, 1 edges between
    684 * consequtive clusters and 2 edges between non-consequtive clusters
    685 */
    686 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(edgevars), (SCIP_Longint) ncluster * 2) );
    687
    688 for( i = 0; i < 2 * ncluster; ++i )
    689 {
    690 (void) SCIPsnprintf(varname, SCIP_MAXSTRLEN, "f_%d", i);
    691
    694 SCIP_CALL( SCIPaddVar(scip, edgevars[i]) );
    695 }
    696
    697 /* create variables for the edges in each cluster combination. Index 0 are edges within cluster, 1 edges between
    698 * consequtive clusters and 2 edges between non-consequtive clusters
    699 */
    700 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(probdata->edgevars), nbins) );
    701
    702 for( i = 0; i < nbins; ++i )
    703 {
    704 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(probdata->edgevars[i]), nbins) ); /*lint !e866*/
    705
    706 for( j = 0; j < nbins; ++j )
    707 probdata->edgevars[i][j] = NULL;
    708 }
    709
    710 /*
    711 * create constraints
    712 */
    713
    714 /* create the set-partitioning constraints of the bins */
    715 for( i = 0; i < nbins; ++i )
    716 {
    717 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "setpart_%d", i+1);
    718 SCIP_CALL( SCIPcreateConsSetpart(scip, &temp, consname, 0, NULL, TRUE, TRUE, TRUE, TRUE, TRUE,
    719 FALSE, FALSE, FALSE, FALSE, FALSE) );
    720
    721 for ( c1 = 0; c1 < ncluster; ++c1 )
    722 {
    723 SCIP_CALL( SCIPaddCoefSetppc(scip, temp, probdata->binvars[i][c1]) );
    724 }
    725
    726 SCIP_CALL( SCIPaddCons(scip, temp) );
    727 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    728 }
    729
    730 /* add constraint that ensures that each cluster is used */
    731 for( c1 = 0; c1 < ncluster; ++c1 )
    732 {
    733 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cluster_%d_used", c1);
    734 SCIP_CALL( SCIPcreateConsBasicLogicor(scip, &temp, consname, 0, NULL) );
    735
    736 for( i = 0; i < nbins; ++i )
    737 {
    738 SCIP_CALL( SCIPaddCoefLogicor(scip, temp, probdata->binvars[i][c1]) );
    739 }
    740
    741 SCIP_CALL( SCIPaddCons(scip, temp) );
    742 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    743 }
    744
    745 for( c = 0; c < ncluster; ++c)
    746 {
    747 SCIP_Real one = 1.0;
    748 int nquadterms = 0;
    749
    750 /* collect quadratic terms */
    751 for( i = 0; i < nbins; ++i )
    752 {
    753 for( j = 0; j < nbins; ++j )
    754 {
    755 if( i != j )
    756 {
    757 quadvars1[nquadterms] = probdata->binvars[i][c];
    758 quadvars2[nquadterms] = probdata->binvars[j][phi(c,ncluster)];
    759 quadcoefs[nquadterms] = probdata->cmatrix[j][i] - probdata->cmatrix[i][j];
    760 ++nquadterms;
    761 }
    762 }
    763 }
    764
    765 /* create, add, and release constraint */
    766 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "irrev_%d", c);
    767 SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, &temp, consname, 1, &edgevars[c], &one, nquadterms, quadvars1,
    768 quadvars2, quadcoefs, -SCIPinfinity(scip), 0.0, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
    769 SCIP_CALL( SCIPaddCons(scip, temp) );
    770 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    771 }
    772
    773 for( c = 0; c < ncluster; ++c )
    774 {
    775 SCIP_Real one = 1.0;
    776 int nquadterms = 0;
    777
    778 for( i = 0; i < nbins; ++i)
    779 {
    780 for( j = 0; j < nbins; ++j )
    781 {
    782 if( i > j )
    783 {
    784 quadvars1[nquadterms] = probdata->binvars[i][c];
    785 quadvars2[nquadterms] = probdata->binvars[j][c];
    786 quadcoefs[nquadterms] = -scale * (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]);
    787 ++nquadterms;
    788 }
    789 }
    790 }
    791
    792 /* create, add, and release constraint */
    793 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "coh_%d", c);
    794 SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, &temp, consname, 1, &edgevars[c+ncluster], &one, nquadterms, quadvars1,
    795 quadvars2, quadcoefs, -SCIPinfinity(scip), 0.0, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
    796 SCIP_CALL( SCIPaddCons(scip, temp) );
    797 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    798 }
    799
    800 for (i = 0; i < 2*ncluster; i++ )
    801 {
    802 SCIP_CALL( SCIPreleaseVar(scip, &edgevars[i]) );
    803 }
    804
    805 SCIPfreeBlockMemoryArray(scip, &edgevars, (SCIP_Longint) 2 * ncluster);
    806
    807 /* free memory */
    808 SCIPfreeBufferArray(scip, &quadcoefs);
    809 SCIPfreeBufferArray(scip, &quadvars2);
    810 SCIPfreeBufferArray(scip, &quadvars1);
    811
    812 return SCIP_OKAY;
    813}
    814
    815
    816/** create the problem with variable amount of clusters. Very large number of constraints not viable for large scale
    817 * problems.
    818 */
    819static
    821 SCIP* scip, /**< SCIP Data Structure */
    822 SCIP_PROBDATA* probdata /**< The problem data */
    823 )
    824{
    825 SCIP_CONS* temp;
    826 SCIP_Real scale;
    827 SCIP_Real sign[3][3];
    828 char consname[SCIP_MAXSTRLEN];
    829 int nbins = probdata->nbins;
    830 int i;
    831 int j;
    832 int k;
    833 int l;
    834
    835 SCIP_CALL( SCIPgetRealParam(scip, "cycleclustering/scale_coherence", &scale) );
    836 probdata->scale = scale;
    837
    838 for( i = 0; i < 3; ++i )
    839 {
    840 for( j = 0; j < 3; ++j )
    841 {
    842 sign[i][j] = 1.0;
    843 }
    844 sign[i][i] = -1.0;
    845 }
    846 /*
    847 * create constraints
    848 */
    849
    850 /* create constraints for the edge-cut variables */
    852 "Using edge-representation with simplified structure. No variable amount of cluster. \n");
    853
    854 for( i = 0; i < nbins; ++i )
    855 {
    856 for( j = 0; j < nbins; ++j )
    857 {
    858 /* set the objective weight for the edge-variables */
    859
    860 /* these edges are not within a cluster */
    861 if( j < i )
    862 {
    863 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][INCLUSTER], (probdata->cmatrix[i][j] + probdata->cmatrix[j][i]) * scale) );
    864 /* these are the edges that are between consequtive clusters */
    865 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], (probdata->cmatrix[i][j] - probdata->cmatrix[j][i])) );
    866 SCIP_CALL( SCIPchgVarObj(scip, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], (probdata->cmatrix[j][i] - probdata->cmatrix[i][j])) );
    867
    868 (void)SCIPsnprintf(consname, SCIP_MAXSTRLEN, "bins_%d_%d", i+1, j+1);
    869 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    871
    872 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], 1.0) );
    873 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][CONSECUTIVE_CLUSTER], 1.0) );
    874 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][i][CONSECUTIVE_CLUSTER], 1.0) );
    875
    876 SCIP_CALL( SCIPaddCons(scip, temp) );
    877 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    878 }
    879
    880 for( k = 0; k < nbins; ++k )
    881 {
    882 if( i == k || i == j || k == j )
    883 continue;
    884
    885 if( k < j && j < i )
    886 {
    887 for( l = 0; l < 3; l++ )
    888 {
    889 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "tri_%d_%d_%d", i, j, k);
    890 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    892
    893 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][j][INCLUSTER], sign[l][0]) );
    894 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][k][INCLUSTER], sign[l][1]) );
    895 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][k][INCLUSTER], sign[l][2]) );
    896
    897 SCIP_CALL( SCIPaddCons(scip, temp) );
    898 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    899 }
    900 }
    901
    902 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "tri_%d_%d_%d", i, j, k);
    903 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    905
    906 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[MAX(i,j)][MIN(i,j)][INCLUSTER], 1.0) );
    907 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][k][CONSECUTIVE_CLUSTER], 1.0) );
    908 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][k][CONSECUTIVE_CLUSTER], -1.0) );
    909
    910 SCIP_CALL( SCIPaddCons(scip, temp) );
    911 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    912
    913 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "tri_%d_%d_%d", i, j, k);
    914 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    916
    917 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[MAX(i,j)][MIN(i,j)][INCLUSTER], 1.0) );
    918 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[k][j][CONSECUTIVE_CLUSTER], 1.0) );
    919 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[k][i][CONSECUTIVE_CLUSTER], -1.0) );
    920
    921 SCIP_CALL( SCIPaddCons(scip, temp) );
    922 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    923
    924 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "tri_%d_%d_%d", i, j, k);
    925 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    927
    928 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[MAX(i,j)][MIN(i,j)][INCLUSTER], -1.0) );
    929 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[j][k][CONSECUTIVE_CLUSTER], 1.0) );
    930 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[i][k][CONSECUTIVE_CLUSTER], 1.0) );
    931
    932 SCIP_CALL( SCIPaddCons(scip, temp) );
    933 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    934
    935 (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "tri_%d_%d_%d", i, j, k);
    936 SCIP_CALL( SCIPcreateConsLinear(scip, &temp, consname, 0, NULL, NULL, -SCIPinfinity(scip), 1.0,
    938
    939 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[MAX(i,j)][MIN(i,j)][INCLUSTER], -1.0) );
    940 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[k][j][CONSECUTIVE_CLUSTER], 1.0) );
    941 SCIP_CALL( SCIPaddCoefLinear(scip, temp, probdata->edgevars[k][i][CONSECUTIVE_CLUSTER], 1.0) );
    942
    943 SCIP_CALL( SCIPaddCons(scip, temp) );
    944 SCIP_CALL( SCIPreleaseCons(scip, &temp) );
    945 }
    946 }
    947 }
    948
    949 return SCIP_OKAY;
    950}
    951
    952/** Scip callback to transform the problem */
    953static
    955{
    956 int i;
    957 int j;
    958 int c;
    959 EDGETYPE edgetype;
    960 int nbins = sourcedata->nbins;
    961 int ncluster = sourcedata->ncluster;
    962
    963 assert(scip != NULL);
    964 assert(sourcedata != NULL);
    965 assert(targetdata != NULL);
    966
    967 /* allocate memory */
    968 SCIP_CALL( SCIPallocBlockMemory(scip, targetdata) );
    969
    970 (*targetdata)->nbins = sourcedata->nbins;
    971 (*targetdata)->ncluster = sourcedata->ncluster;
    972 (*targetdata)->model_variant = sourcedata->model_variant;
    973 (*targetdata)->scale = sourcedata->scale;
    974
    975 /* allocate memory */
    976 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->cmatrix), nbins) );
    977 for( i = 0; i < nbins; ++i )
    978 {
    979 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->cmatrix[i]), nbins) ); /*lint !e866*/
    980 }
    981 /* copy the matrizes */
    982 for ( i = 0; i < nbins; ++i )
    983 {
    984 for ( j = 0; j < nbins; ++j )
    985 {
    986 (*targetdata)->cmatrix[i][j] = sourcedata->cmatrix[i][j];
    987 }
    988 }
    989
    990 /* copy the variables */
    991 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->binvars), nbins) );
    992 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*targetdata)->edgevars), nbins) );
    993
    994 for( i = 0; i < nbins; ++i )
    995 {
    996 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*targetdata)->edgevars[i]), nbins) ); /*lint !e866*/
    997 for( j = 0; j < nbins; ++j )
    998 {
    999 if( sourcedata->edgevars[i][j] == NULL || i == j)
    1000 continue;
    1001 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*targetdata)->edgevars[i][j]), 3) ); /*lint !e866*/
    1002 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    1003 {
    1004 if( edgetype == INCLUSTER && i < j )
    1005 continue;
    1006 if( sourcedata->edgevars[i][j][edgetype] != NULL )
    1007 {
    1008 SCIP_CALL( SCIPtransformVar(scip, sourcedata->edgevars[i][j][edgetype],
    1009 &((*targetdata)->edgevars[i][j][edgetype])) );
    1010 }
    1011 else
    1012 ((*targetdata)->edgevars[i][j][edgetype]) = NULL;
    1013 }
    1014 }
    1015 }
    1016
    1017 for( i = 0; i < nbins; ++i )
    1018 {
    1019 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->binvars[i]), ncluster) ); /*lint !e866*/
    1020
    1021 for( c = 0; c < ncluster; ++c )
    1022 {
    1023 if( sourcedata->binvars[i][c] != NULL )
    1024 {
    1025 SCIP_CALL( SCIPtransformVar(scip, sourcedata->binvars[i][c], &((*targetdata)->binvars[i][c])) );
    1026 }
    1027 else
    1028 (*targetdata)->binvars[i][c] = NULL;
    1029 }
    1030 }
    1031
    1032 SCIP_CALL( SCIPcopyDigraph(scip, &((*targetdata)->edgegraph), sourcedata->edgegraph) );
    1033
    1034 return SCIP_OKAY;
    1035}
    1036
    1037/** delete-callback method of scip */
    1038static
    1040{
    1041 int c;
    1042 EDGETYPE edgetype;
    1043 int i;
    1044 int j;
    1045
    1046 assert(probdata != NULL);
    1047 assert(*probdata != NULL);
    1048
    1049 /* release all the variables */
    1050
    1051 /* binvars */
    1052 for ( c = 0; c < (*probdata)->nbins; ++c )
    1053 {
    1054 for ( i = 0; i < (*probdata)->ncluster; ++i )
    1055 {
    1056 if( (*probdata)->binvars[c][i] != NULL )
    1057 {
    1058 SCIP_CALL( SCIPreleaseVar(scip, &((*probdata)->binvars[c][i])) );
    1059 }
    1060 }
    1061 SCIPfreeBlockMemoryArray( scip, &((*probdata)->binvars[c]), (*probdata)->ncluster);
    1062 }
    1063
    1064 /* cut-edge vars */
    1065 for ( i = 0; i < (*probdata)->nbins; ++i )
    1066 {
    1067 for( j = 0; j < (*probdata)->nbins; ++j )
    1068 {
    1069 if( (*probdata)->edgevars[i][j] != NULL && j != i )
    1070 {
    1071 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    1072 {
    1073 if( edgetype == INCLUSTER && i < j )
    1074 continue;
    1075
    1076 if( (*probdata)->edgevars[i][j][edgetype] != NULL )
    1077 {
    1078 SCIP_CALL( SCIPreleaseVar( scip, &((*probdata)->edgevars[i][j][edgetype])) );
    1079 }
    1080 }
    1081
    1082 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars[i][j]), 3);
    1083 }
    1084 }
    1085
    1086 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars[i]), (*probdata)->nbins);
    1087 }
    1088
    1089 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars), (*probdata)->nbins);
    1090 SCIPfreeBlockMemoryArray(scip, &((*probdata)->binvars), (*probdata)->nbins);
    1091
    1092 SCIPdigraphFreeComponents((*probdata)->edgegraph);
    1093 SCIPdigraphFree(&((*probdata)->edgegraph));
    1094
    1095 for ( i = 0; i < (*probdata)->nbins; ++i )
    1096 {
    1097 SCIPfreeBlockMemoryArray(scip, &((*probdata)->cmatrix[i]), (*probdata)->nbins);
    1098 }
    1099 SCIPfreeBlockMemoryArray(scip, &(*probdata)->cmatrix, (*probdata)->nbins);
    1100
    1101 SCIPfreeBlockMemory(scip, probdata);
    1102
    1103 return SCIP_OKAY;
    1104}
    1105
    1106/** scip-callback to delete the transformed problem */
    1107static
    1109{
    1110 int c;
    1111 EDGETYPE edgetype;
    1112 int i;
    1113 int j;
    1114
    1115 assert(probdata != NULL);
    1116 assert(*probdata != NULL);
    1117
    1118 /* release all the variables */
    1119
    1120 /* binvars */
    1121 for ( i = 0; i < (*probdata)->nbins; ++i )
    1122 {
    1123 for ( c = 0; c < (*probdata)->ncluster; ++c )
    1124 {
    1125 if( (*probdata)->binvars[i][c] != NULL )
    1126 {
    1127 SCIP_CALL( SCIPreleaseVar(scip, &((*probdata)->binvars[i][c])) );
    1128 }
    1129 }
    1130 SCIPfreeBlockMemoryArray(scip, &((*probdata)->binvars[i]), (*probdata)->ncluster);
    1131 }
    1132
    1133 /* cut-edge vars */
    1134 for ( i = 0; i < (*probdata)->nbins; ++i )
    1135 {
    1136 for( j = 0; j < (*probdata)->nbins; ++j )
    1137 {
    1138 if( (*probdata)->edgevars[i][j] != NULL && j != i )
    1139 {
    1140 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    1141 {
    1142 if( edgetype == INCLUSTER && j > i )
    1143 continue;
    1144
    1145 if( (*probdata)->edgevars[i][j][edgetype] != NULL )
    1146 {
    1147 SCIP_CALL( SCIPreleaseVar( scip, &((*probdata)->edgevars[i][j][edgetype])) );
    1148 }
    1149 }
    1150
    1151 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars[i][j]), 3);
    1152 }
    1153 }
    1154
    1155 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars[i]), (*probdata)->nbins);
    1156 }
    1157
    1158 SCIPfreeBlockMemoryArray(scip, &((*probdata)->edgevars), (*probdata)->nbins);
    1159 SCIPfreeBlockMemoryArray(scip, &((*probdata)->binvars), (*probdata)->nbins);
    1160
    1161 SCIPdigraphFreeComponents((*probdata)->edgegraph);
    1162 SCIPdigraphFree(&((*probdata)->edgegraph));
    1163
    1164 for ( i = 0; i < (*probdata)->nbins; ++i )
    1165 {
    1166 SCIPfreeBlockMemoryArray(scip, &((*probdata)->cmatrix[i]), (*probdata)->nbins);
    1167 }
    1168 SCIPfreeBlockMemoryArray(scip, &(*probdata)->cmatrix, (*probdata)->nbins);
    1169
    1170 SCIPfreeBlockMemory(scip, probdata);
    1171
    1172 return SCIP_OKAY;
    1173}
    1174
    1175/** callback method of scip for copying the probdata */
    1176static
    1178{
    1179 SCIP_Bool success;
    1180 SCIP_VAR* var;
    1181 int nbins;
    1182 int ncluster;
    1183 EDGETYPE edgetype;
    1184 int i;
    1185 int j;
    1186 int c;
    1187
    1188 assert(scip != NULL);
    1189 assert(sourcescip != NULL);
    1190 assert(sourcedata != NULL);
    1191 assert(targetdata != NULL);
    1192
    1193 /* set up data */
    1194 SCIP_CALL( SCIPallocBlockMemory(scip, targetdata) );
    1195
    1196 nbins = sourcedata->nbins;
    1197 ncluster = sourcedata->ncluster;
    1198 success = FALSE;
    1199
    1200 (*targetdata)->nbins = nbins;
    1201 (*targetdata)->ncluster = ncluster;
    1202 (*targetdata)->model_variant = sourcedata->model_variant;
    1203 (*targetdata)->scale = sourcedata->scale;
    1204
    1205 /* allocate memory */
    1206 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->cmatrix), nbins) );
    1207 for( i = 0; i < nbins; ++i )
    1208 {
    1209 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->cmatrix[i]), nbins) ); /*lint !e866*/
    1210 }
    1211 /* copy the matrizes */
    1212 for ( i = 0; i < nbins; ++i )
    1213 {
    1214 for ( j = 0; j < nbins; ++j )
    1215 {
    1216 (*targetdata)->cmatrix[i][j] = sourcedata->cmatrix[i][j];
    1217 }
    1218 }
    1219
    1220 /* copy the variables */
    1221 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->binvars), nbins) );
    1222 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*targetdata)->edgevars), nbins) );
    1223
    1224 for( i = 0; i < nbins; ++i )
    1225 {
    1226 SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &((*targetdata)->edgevars[i]), nbins) ); /*lint !e866*/
    1227
    1228 for( j = 0; j < nbins; ++j )
    1229 {
    1230 if( (sourcedata)->edgevars[i][j] == NULL || j == i )
    1231 continue;
    1232
    1233 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->edgevars[i][j]), 3) ); /*lint !e866*/
    1234
    1235 for( edgetype = INCLUSTER; edgetype <= NON_CONSECUTIVE_CLUSTER; ++edgetype )
    1236 {
    1237 if( edgetype == 0 && j > i )
    1238 continue;
    1239
    1240 if( sourcedata->edgevars[i][j][edgetype] != NULL )
    1241 {
    1242 SCIP_CALL( SCIPgetTransformedVar(sourcescip, sourcedata->edgevars[i][j][edgetype], &var) );
    1243
    1244 if( SCIPvarIsActive(var) )
    1245 {
    1246 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &((*targetdata)->edgevars[i][j][edgetype]),
    1247 varmap, consmap, global, &success) );
    1248
    1249 assert(success);
    1250 assert((*targetdata)->edgevars[i][j][edgetype] != NULL);
    1251
    1252 SCIP_CALL( SCIPcaptureVar(scip, (*targetdata)->edgevars[i][j][edgetype]) );
    1253 }
    1254 else
    1255 (*targetdata)->edgevars[i][j][edgetype] = NULL;
    1256 }
    1257 else
    1258 (*targetdata)->edgevars[i][j][edgetype] = NULL;
    1259 }
    1260 }
    1261 }
    1262
    1263 for( i = 0; i < nbins; ++i )
    1264 {
    1265 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &((*targetdata)->binvars[i]), ncluster) ); /*lint !e866*/
    1266
    1267 for( c = 0; c < ncluster; ++c )
    1268 {
    1269 if( sourcedata->binvars[i][c] != NULL )
    1270 {
    1271 SCIP_CALL( SCIPgetTransformedVar(sourcescip, sourcedata->binvars[i][c], &var) );
    1272
    1273 if( SCIPvarIsActive(var) )
    1274 {
    1275 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &((*targetdata)->binvars[i][c]),
    1276 varmap, consmap, global, &success) );
    1277
    1278 assert(success);
    1279 assert((*targetdata)->binvars[i][c] != NULL);
    1280
    1281 SCIP_CALL( SCIPcaptureVar(scip, (*targetdata)->binvars[i][c]) );
    1282 }
    1283 else
    1284 (*targetdata)->binvars[i][c] = NULL;
    1285 }
    1286 else
    1287 (*targetdata)->binvars[i][c] = NULL;
    1288 }
    1289 }
    1290
    1291 SCIP_CALL( SCIPcopyDigraph(scip, &((*targetdata)->edgegraph), sourcedata->edgegraph) );
    1292
    1293 assert(success);
    1294
    1295 *result = SCIP_SUCCESS;
    1296
    1297 return SCIP_OKAY;
    1298}
    1299
    1300/**
    1301 * Create the probdata for an cyc-clustering problem
    1302 */
    1304 SCIP* scip, /**< SCIP data structure */
    1305 const char* name, /**< problem name */
    1306 int nbins, /**< number of bins */
    1307 int ncluster, /**< number of cluster */
    1308 SCIP_Real** cmatrix /**< The transition matrix */
    1309 )
    1310{
    1311 SCIP_PROBDATA* probdata = NULL;
    1312 int i;
    1313 int j;
    1314 char model;
    1315
    1316 assert(nbins > 0); /* at least one node */
    1317 assert(ncluster <= nbins);
    1318
    1320
    1321 /* Set up the problem */
    1322 SCIP_CALL( SCIPallocBlockMemory(scip, &probdata) );
    1323
    1324 SCIP_CALL( SCIPcreateDigraph(scip, &(probdata->edgegraph), nbins) );
    1325
    1326 /* allocate memory for the matrizes and create them from the edge-arrays */
    1327 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->cmatrix), nbins) );
    1328 for ( i = 0; i < nbins; ++i )
    1329 {
    1330 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(probdata->cmatrix[i]), nbins) ); /*lint !e866*/
    1331 for( j = 0; j < nbins; ++j )
    1332 {
    1333 probdata->cmatrix[i][j] = cmatrix[i][j];
    1334 }
    1335 }
    1336
    1337 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Creating problem: %s \n", name);
    1338
    1339 /* create variables */
    1340 probdata->nbins=nbins;
    1341 probdata->ncluster=ncluster;
    1342
    1343 SCIP_CALL( SCIPgetCharParam(scip, "cycleclustering/model", &model) );
    1344
    1345 /* create constraints depending on model selection */
    1346 switch( model )
    1347 {
    1348 case 's':
    1349 SCIP_CALL( createVariables(scip, probdata) );
    1350 SCIP_CALL( createProbSimplified(scip, probdata) );
    1351 break;
    1352 case 't':
    1353 SCIP_CALL( createVariables(scip, probdata) );
    1355 break;
    1356 case 'e':
    1357 SCIP_CALL( createVariables(scip, probdata) );
    1358 SCIP_CALL( createProbOnlyEdge(scip, probdata) );
    1359 break;
    1360 case 'q':
    1361 SCIP_CALL( createProbQP(scip, probdata) );
    1362 break;
    1363 default:
    1364 SCIPABORT();
    1365 break;
    1366 }
    1367
    1368 /** add callback methods to scip */
    1369 SCIP_CALL( SCIPsetProbDelorig(scip, probdelorigCyc) );
    1370 SCIP_CALL( SCIPsetProbCopy(scip, probcopyCyc) );
    1371 SCIP_CALL( SCIPsetProbData(scip, probdata) );
    1372 SCIP_CALL( SCIPsetProbTrans(scip, probtransCyc) );
    1373 SCIP_CALL( SCIPsetProbDeltrans(scip, probdeltransCyc) );
    1374
    1375 return SCIP_OKAY;
    1376}
    1377
    1378/** Getter methods for the various parts of the probdata */
    1379
    1380
    1381/** Returns the transition matrix*/
    1383 SCIP* scip /**< SCIP data structure */
    1384 )
    1385{
    1386 SCIP_PROBDATA* probdata;
    1387
    1388 assert(scip != NULL);
    1389
    1390 probdata = SCIPgetProbData(scip);
    1391
    1392 assert(probdata != NULL);
    1393
    1394 return probdata->cmatrix;
    1395}
    1396
    1397/** Returns the number of states */
    1399 SCIP* scip /**< SCIP data structure */
    1400 )
    1401{
    1402 SCIP_PROBDATA* probdata;
    1403
    1404 assert(scip != NULL);
    1405
    1406 probdata = SCIPgetProbData(scip);
    1407
    1408 assert(probdata != NULL);
    1409
    1410 return probdata->nbins;
    1411}
    1412
    1413/** Returns the number of clusters*/
    1415 SCIP* scip /**< SCIP data structure */
    1416 )
    1417{
    1418 SCIP_PROBDATA* probdata;
    1419
    1420 assert(scip!= NULL);
    1421
    1422 probdata = SCIPgetProbData(scip);
    1423
    1424 assert(probdata != NULL);
    1425
    1426 return probdata->ncluster;
    1427}
    1428
    1429/** Returns the state-variable-matrix*/
    1431 SCIP* scip /**< SCIP data structure */
    1432 )
    1433{
    1434 SCIP_PROBDATA* probdata;
    1435
    1436 assert(scip!= NULL);
    1437
    1438 probdata = SCIPgetProbData(scip);
    1439
    1440 assert(probdata != NULL);
    1441 assert(probdata->binvars != NULL);
    1442
    1443 return probdata->binvars;
    1444}
    1445
    1446/** Returns the scaling parameter*/
    1448 SCIP* scip /**< SCIP data structure */
    1449 )
    1450{
    1451 SCIP_PROBDATA* probdata;
    1452
    1453 assert(scip!= NULL);
    1454
    1455 probdata = SCIPgetProbData(scip);
    1456
    1457 assert(probdata != NULL);
    1458
    1459 return probdata->scale;
    1460}
    1461
    1462/** Returns the edge variables */
    1464 SCIP* scip /**< SCIP data structure */
    1465 )
    1466{
    1467 SCIP_PROBDATA* probdata;
    1468
    1469 assert(scip!= NULL);
    1470
    1471 probdata = SCIPgetProbData(scip);
    1472
    1473 assert(probdata != NULL);
    1474 assert(probdata->edgevars != NULL);
    1475
    1476 return probdata->edgevars;
    1477}
    1478
    1479/** return one specific edge variable */
    1481 SCIP_VAR**** edgevars, /**< edgevar data structure*/
    1482 int state1, /**< first state */
    1483 int state2, /**< second state */
    1484 EDGETYPE edgetype /**< position in clustering */
    1485 )
    1486{
    1487 assert(edgevars != NULL);
    1488 assert(edgevars[state1] != NULL);
    1489 assert(edgevars[state1][state2] != NULL);
    1490 assert(edgevars[state1][state2][edgetype] != NULL);
    1491
    1492 return edgevars[state1][state2][edgetype];
    1493}
    1494
    1495/** check for an array of states, if all possible edge-combinations exist */
    1497 SCIP_VAR**** edgevars, /**< edgevar data structure */
    1498 int* states, /**< state array */
    1499 int nstates /**< size of state array */
    1500 )
    1501{
    1502 int i;
    1503 int j;
    1504
    1505 assert(edgevars != NULL);
    1506 assert(states != NULL);
    1507
    1508 for( i = 0; i < nstates; ++i )
    1509 {
    1510 assert(edgevars[states[i]] != NULL);
    1511
    1512 for( j = 0; j < nstates; ++j )
    1513 {
    1514 if( j != i )
    1515 {
    1516 assert(edgevars[states[j]] != NULL);
    1517
    1518 if( edgevars[states[i]][states[j]] == NULL )
    1519 return FALSE;
    1520 }
    1521 }
    1522 }
    1523
    1524 return TRUE;
    1525}
    1526
    1527/** Returns the edge-graph */
    1529 SCIP* scip /**< SCIP data structure */
    1530 )
    1531{
    1532 SCIP_PROBDATA* probdata;
    1533
    1534 assert(scip!= NULL);
    1535
    1536 probdata = SCIPgetProbData(scip);
    1537
    1538 assert(probdata != NULL);
    1539 assert(probdata->edgegraph != NULL);
    1540
    1541 return probdata->edgegraph;
    1542}
    1543
    1544
    1545/** print the model-values like coherence in the clusters and transition-probabilities between clusters that are not
    1546 * evident from the scip-solution
    1547 */
    1549 SCIP* scip, /**< SCIP data structure */
    1550 SCIP_SOL* sol /**< The solution containg the values */
    1551 )
    1552{
    1553 SCIP_PROBDATA* probdata;
    1554 SCIP_Real value;
    1555 SCIP_Real objvalue = 0;
    1556 SCIP_Real flow = 0;
    1557 SCIP_Real coherence = 0;
    1558 int c1;
    1559 int c2;
    1560 int c3;
    1561 int i;
    1562 int j;
    1563
    1564 assert(scip!= NULL);
    1565
    1566 probdata = SCIPgetProbData(scip);
    1567
    1568 assert(probdata != NULL);
    1569
    1570 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "\nDisplaying aggregated solution data: \n");
    1571
    1572 for( c1 = 0; c1 < probdata->ncluster; ++c1 )
    1573 {
    1574 value = 0;
    1575
    1576 for( i = 0; i < probdata->nbins; ++i )
    1577 {
    1578 for( j = 0; j < probdata->nbins; ++j )
    1579 {
    1580 if( j == i )
    1581 continue;
    1582
    1583 value+= probdata->cmatrix[i][j] * SCIPgetSolVal(scip, sol, probdata->binvars[i][c1])
    1584 * SCIPgetSolVal(scip, sol, probdata->binvars[j][c1]);
    1585 }
    1586 }
    1587
    1588 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Coherence in cluster %d : %f \n", c1 + 1, value);
    1589 coherence += value;
    1590 objvalue += probdata->scale * value;
    1591 }
    1592
    1593 for( c1 = 0; c1 < probdata->ncluster; ++c1 )
    1594 {
    1595 for( c2 = 0; c2 < probdata->ncluster; ++c2 )
    1596 {
    1597 value = 0;
    1598
    1599 for( i = 0; i < probdata->nbins; ++i )
    1600 {
    1601 for( j = 0; j < probdata->nbins; ++j )
    1602 {
    1603 value+= probdata->cmatrix[i][j] * SCIPgetSolVal(scip, sol, probdata->binvars[i][c1]) *
    1604 SCIPgetSolVal(scip, sol, probdata->binvars[j][c2]);
    1605 }
    1606 }
    1607 }
    1608
    1609 c3 = (c1 + 1) % probdata->ncluster;
    1610 value = 0;
    1611
    1612 for( i = 0; i < probdata->nbins; ++i )
    1613 {
    1614 for( j = 0; j < probdata->nbins; ++j )
    1615 {
    1616 value+= (probdata->cmatrix[i][j] - probdata->cmatrix[j][i])
    1617 * SCIPgetSolVal(scip, sol, probdata->binvars[i][c1]) * SCIPgetSolVal(scip, sol, probdata->binvars[j][c3]);
    1618 }
    1619 }
    1620
    1622 " Net flow from %d to %d : %f \n", c1, phi(c1, probdata->ncluster), value);
    1623
    1624 flow += value;
    1625 objvalue += value;
    1626 }
    1627
    1628 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Total coherence : %f \n", coherence);
    1629 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Total net flow : %f \n", flow);
    1630 SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, " Total objective value : %f \n", objvalue);
    1631
    1632 return SCIP_OKAY;
    1633}
    Constraint handler for linear constraints in their most general form, .
    Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
    constraint handler for nonlinear constraints specified by algebraic expressions
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_setppc.c:9573
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: cons_setppc.c:9402
    SCIP_RETCODE SCIPcreateConsBasicLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
    SCIP_RETCODE SCIPcreateConsQuadraticNonlinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nlinvars, SCIP_VAR **linvars, SCIP_Real *lincoefs, int nquadterms, SCIP_VAR **quadvars1, SCIP_VAR **quadvars2, SCIP_Real *quadcoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable)
    SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
    Definition: scip_copy.c:713
    void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8594
    SCIP_RETCODE SCIPcopyDigraph(SCIP *scip, SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph)
    SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7739
    void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
    Definition: misc.c:7645
    SCIP_RETCODE SCIPcreateDigraph(SCIP *scip, SCIP_DIGRAPH **digraph, int nnodes)
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    SCIP_RETCODE SCIPsetProbDeltrans(SCIP *scip, SCIP_DECL_PROBDELTRANS((*probdeltrans)))
    Definition: scip_prob.c:244
    SCIP_RETCODE SCIPsetProbTrans(SCIP *scip, SCIP_DECL_PROBTRANS((*probtrans)))
    Definition: scip_prob.c:223
    SCIP_RETCODE SCIPsetProbDelorig(SCIP *scip, SCIP_DECL_PROBDELORIG((*probdelorig)))
    Definition: scip_prob.c:202
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_PROBDATA * SCIPgetProbData(SCIP *scip)
    Definition: scip_prob.c:1139
    SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
    Definition: scip_prob.c:1417
    SCIP_RETCODE SCIPaddOrigObjoffset(SCIP *scip, SCIP_Real addval)
    Definition: scip_prob.c:1486
    SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
    Definition: scip_prob.c:182
    SCIP_RETCODE SCIPsetProbData(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: scip_prob.c:1189
    SCIP_RETCODE SCIPsetProbCopy(SCIP *scip, SCIP_DECL_PROBCOPY((*probcopy)))
    Definition: scip_prob.c:308
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:225
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPgetCharParam(SCIP *scip, const char *name, char *value)
    Definition: scip_param.c:326
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocClearBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:97
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(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 SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23430
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPtransformVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:1988
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
    Definition: scip_var.c:184
    SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
    Definition: var.c:23672
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_Bool edgesExist(SCIP_VAR ****edgevars, int *states, int nstates)
    SCIP_RETCODE assignVars(SCIP *scip, SCIP_SOL *sol, SCIP_Real **clustering, int nbins, int ncluster)
    Definition: probdata_cyc.c:88
    static SCIP_RETCODE createProbOnlyEdge(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: probdata_cyc.c:820
    static SCIP_DECL_PROBDELORIG(probdelorigCyc)
    static SCIP_RETCODE createVariables(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: probdata_cyc.c:209
    static SCIP_DECL_PROBTRANS(probtransCyc)
    Definition: probdata_cyc.c:954
    SCIP_VAR **** SCIPcycGetEdgevars(SCIP *scip)
    SCIP_RETCODE SCIPcycPrintSolutionValues(SCIP *scip, SCIP_SOL *sol)
    static SCIP_RETCODE createProbQP(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: probdata_cyc.c:636
    int SCIPcycGetNBins(SCIP *scip)
    int phiinv(int k, int ncluster)
    Definition: probdata_cyc.c:193
    static SCIP_RETCODE createProbSimplified(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: probdata_cyc.c:419
    SCIP_VAR * getEdgevar(SCIP_VAR ****edgevars, int state1, int state2, EDGETYPE edgetype)
    SCIP_Real SCIPcycGetScale(SCIP *scip)
    int SCIPcycGetNCluster(SCIP *scip)
    static SCIP_RETCODE createProbSimplifiedTest(SCIP *scip, SCIP_PROBDATA *probdata)
    Definition: probdata_cyc.c:276
    SCIP_VAR *** SCIPcycGetBinvars(SCIP *scip)
    SCIP_DIGRAPH * SCIPcycGetEdgeGraph(SCIP *scip)
    static SCIP_DECL_PROBCOPY(probcopyCyc)
    SCIP_Real ** SCIPcycGetCmatrix(SCIP *scip)
    SCIP_Bool isPartition(SCIP *scip, SCIP_Real **solclustering, int nbins, int ncluster)
    Definition: probdata_cyc.c:57
    static SCIP_DECL_PROBDELTRANS(probdeltransCyc)
    SCIP_RETCODE SCIPcreateProbCyc(SCIP *scip, const char *name, int nbins, int ncluster, SCIP_Real **cmatrix)
    int phi(int k, int ncluster)
    Definition: probdata_cyc.c:181
    problem data for cycle clustering problem
    @ CONSECUTIVE_CLUSTER
    Definition: probdata_cyc.h:51
    @ INCLUSTER
    Definition: probdata_cyc.h:50
    @ NON_CONSECUTIVE_CLUSTER
    Definition: probdata_cyc.h:52
    enum EdgeType EDGETYPE
    Definition: probdata_cyc.h:54
    @ SCIP_VERBLEVEL_NORMAL
    Definition: type_message.h:60
    struct SCIP_ProbData SCIP_PROBDATA
    Definition: type_prob.h:53
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    internal methods for problem variables