SCIP

    Solving Constraint Integer Programs

    sepa_minor.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-2026 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 sepa_minor.c
    26 * @ingroup DEFPLUGINS_SEPA
    27 * @brief principal minor separator
    28 * @author Benjamin Mueller
    29 *
    30 * @todo detect non-principal minors and use them to derive split cuts
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    35#include "scip/sepa_minor.h"
    36#include "scip/cons_nonlinear.h"
    37#include "scip/lapack_calls.h"
    38
    39#define SEPA_NAME "minor"
    40#define SEPA_DESC "separator to ensure that 2x2 principal minors of X - xx' are positive semi-definite"
    41#define SEPA_PRIORITY 0
    42#define SEPA_FREQ 10
    43#define SEPA_MAXBOUNDDIST 1.0
    44#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
    45#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
    46
    47#define DEFAULT_MAXMINORSCONST 3000 /**< default constant for the maximum number of minors, i.e., max(const, fac * # quadratic terms) */
    48#define DEFAULT_MAXMINORSFAC 10.0 /**< default factor for the maximum number of minors, i.e., max(const, fac * # quadratic terms) */
    49#define DEFAULT_MINCUTVIOL 1e-4 /**< default minimum required violation of a cut */
    50#define DEFAULT_RANDSEED 157 /**< default random seed */
    51#define DEFAULT_MAXROUNDS 10 /**< maximal number of separation rounds per node (-1: unlimited) */
    52#define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
    53#define DEFAULT_IGNOREPACKINGCONSS TRUE /**< default for ignoring circle packing constraints during minor detection */
    54
    55/*
    56 * Data structures
    57 */
    58
    59/** separator data */
    60struct SCIP_SepaData
    61{
    62 SCIP_VAR** minors; /**< variables of 2x2 minors; each minor is stored like (auxvar_x^2,auxvar_y^2,auxvar_xy) */
    63 int nminors; /**< total number of minors */
    64 int minorssize; /**< size of minors array */
    65 int maxminorsconst; /**< constant for the maximum number of minors, i.e., max(const, fac * # quadratic terms) */
    66 SCIP_Real maxminorsfac; /**< factor for the maximum number of minors, i.e., max(const, fac * # quadratic terms) */
    67 int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
    68 int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
    69 SCIP_Bool detectedminors; /**< has minor detection be called? */
    70 SCIP_Real mincutviol; /**< minimum required violation of a cut */
    71 SCIP_RANDNUMGEN* randnumgen; /**< random number generation */
    72 SCIP_Bool ignorepackingconss; /**< whether to ignore circle packing constraints during minor detection */
    73};
    74
    75/*
    76 * Local methods
    77 */
    78
    79/** helper method to store a 2x2 minor in the separation data */
    80static
    82 SCIP* scip, /**< SCIP data structure */
    83 SCIP_SEPADATA* sepadata, /**< separator data */
    84 SCIP_VAR* x, /**< x variable */
    85 SCIP_VAR* y, /**< y variable */
    86 SCIP_VAR* auxvarxx, /**< auxiliary variable for x*x */
    87 SCIP_VAR* auxvaryy, /**< auxiliary variable for y*y */
    88 SCIP_VAR* auxvarxy /**< auxiliary variable for x*y */
    89 )
    90{
    91 assert(sepadata != NULL);
    92 assert(x != NULL);
    93 assert(y != NULL);
    94 assert(x != y);
    95 assert(auxvarxx != NULL);
    96 assert(auxvaryy != NULL);
    97 assert(auxvarxy != NULL);
    98 assert(auxvarxx != auxvaryy);
    99 assert(auxvarxx != auxvarxy);
    100 assert(auxvaryy != auxvarxy);
    101
    102 SCIPdebugMsg(scip, "store 2x2 minor: %s %s %s for x=%s y=%s\n", SCIPvarGetName(auxvarxx), SCIPvarGetName(auxvaryy),
    104
    105 /* reallocate if necessary */
    106 if( sepadata->minorssize < 5 * (sepadata->nminors + 1) )
    107 {
    108 int newsize = SCIPcalcMemGrowSize(scip, 5 * (sepadata->nminors + 1));
    109 assert(newsize > 5 * (sepadata->nminors + 1));
    110
    111 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->minors), sepadata->minorssize, newsize) );
    112 sepadata->minorssize = newsize;
    113 }
    114
    115 /* store minor */
    116 sepadata->minors[5 * sepadata->nminors] = x;
    117 sepadata->minors[5 * sepadata->nminors + 1] = y;
    118 sepadata->minors[5 * sepadata->nminors + 2] = auxvarxx;
    119 sepadata->minors[5 * sepadata->nminors + 3] = auxvaryy;
    120 sepadata->minors[5 * sepadata->nminors + 4] = auxvarxy;
    121 ++(sepadata->nminors);
    122
    123 /* capture variables */
    126 SCIP_CALL( SCIPcaptureVar(scip, auxvarxx) );
    127 SCIP_CALL( SCIPcaptureVar(scip, auxvaryy) );
    128 SCIP_CALL( SCIPcaptureVar(scip, auxvarxy) );
    129
    130 return SCIP_OKAY;
    131}
    132
    133/** helper method to clear separation data */
    134static
    136 SCIP* scip, /**< SCIP data structure */
    137 SCIP_SEPADATA* sepadata /**< separator data */
    138 )
    139{
    140 int i;
    141
    142 assert(sepadata != NULL);
    143
    144 SCIPdebugMsg(scip, "clear separation data\n");
    145
    146 /* release captured variables */
    147 for( i = 0; i < 5 * sepadata->nminors; ++i )
    148 {
    149 assert(sepadata->minors[i] != NULL);
    150 SCIP_CALL( SCIPreleaseVar(scip, &sepadata->minors[i]) );
    151 }
    152
    153 /* free memory */
    154 SCIPfreeBlockMemoryArrayNull(scip, &sepadata->minors, sepadata->minorssize);
    155
    156 /* reset counters */
    157 sepadata->nminors = 0;
    158 sepadata->minorssize = 0;
    159
    160 return SCIP_OKAY;
    161}
    162
    163/** helper method to identify non-overlapping constraints in circle packing */
    164static
    166 SCIP* scip, /**< SCIP data structure */
    167 SCIP_CONS* cons /**< nonlinear constraint */
    168 )
    169{
    170 SCIP_EXPR* root;
    171 SCIP_VAR* quadvars[4] = {NULL, NULL, NULL, NULL};
    172 SCIP_VAR* bilinvars[4] = {NULL, NULL, NULL, NULL};
    173 int nbilinvars = 0;
    174 int nquadvars = 0;
    175 int nchildren;
    176 int i;
    177
    178 assert(scip != NULL);
    179 assert(cons != NULL);
    180
    181 root = SCIPgetExprNonlinear(cons);
    182 assert(root != NULL);
    183 nchildren = SCIPexprGetNChildren(root);
    184
    185 /* non-overlapping constraint has 6 terms (2 bilinear + 4 quadratic) */
    186 if( nchildren != 6 || !SCIPisExprSum(scip, root) )
    187 return FALSE;
    188
    189 for( i = 0; i < nchildren; ++i )
    190 {
    191 SCIP_EXPR* expr;
    192 SCIP_EXPR** children;
    193
    194 /* get child */
    195 expr = SCIPexprGetChildren(root)[i];
    196 assert(expr != NULL);
    197 children = SCIPexprGetChildren(expr);
    198
    199 /* case: expr = x^2; x is no auxiliary variable */
    200 if( SCIPisExprPower(scip, expr) && SCIPgetExponentExprPow(expr) == 2.0
    201 && SCIPisExprVar(scip, children[0]) )
    202 {
    203 SCIP_VAR* x;
    204
    205 /* too many quadratic variables -> stop */
    206 if( nquadvars > 3 )
    207 return FALSE;
    208
    209 x = SCIPgetVarExprVar(children[0]);
    210 assert(x != NULL);
    211
    212 quadvars[nquadvars++] = x;
    213 }
    214 /* case: expr = x * y; x and y are no auxiliary variables */
    215 else if( SCIPisExprProduct(scip, expr) && SCIPexprGetNChildren(expr) == 2
    216 && SCIPisExprVar(scip, children[0]) && SCIPisExprVar(scip, children[1]) )
    217 {
    218 SCIP_VAR* x;
    219 SCIP_VAR* y;
    220
    221 /* too many bilinear variables -> stop */
    222 if( nbilinvars > 2 )
    223 return FALSE;
    224
    225 x = SCIPgetVarExprVar(children[0]);
    226 assert(x != NULL);
    227 y = SCIPgetVarExprVar(children[1]);
    228 assert(y != NULL);
    229 assert(x != y);
    230
    231 bilinvars[nbilinvars++] = x;
    232 bilinvars[nbilinvars++] = y;
    233 }
    234 else
    235 {
    236 return FALSE;
    237 }
    238 }
    239
    240 /* number of bilinear and quadratic terms do not fit */
    241 if( nbilinvars != 4 || nquadvars != 4 )
    242 return FALSE;
    243
    244 /* each quadratic variable has to appear in exactly one bilinear terms */
    245 for( i = 0; i < nquadvars; ++i )
    246 {
    247 int counter = 0;
    248 int j;
    249
    250 for( j = 0; j < nbilinvars; ++j )
    251 {
    252 if( quadvars[i] == bilinvars[j] )
    253 ++counter;
    254 }
    255
    256 if( counter != 1 )
    257 return FALSE;
    258 }
    259
    260 return TRUE;
    261}
    262
    263/** helper method to get the variables associated to a minor */
    264static
    266 SCIP_SEPADATA* sepadata, /**< separator data */
    267 int idx, /**< index of the stored minor */
    268 SCIP_VAR** x, /**< pointer to store x variable */
    269 SCIP_VAR** y, /**< pointer to store x variable */
    270 SCIP_VAR** auxvarxx, /**< pointer to store auxiliary variable for x*x */
    271 SCIP_VAR** auxvaryy, /**< pointer to store auxiliary variable for y*y */
    272 SCIP_VAR** auxvarxy /**< pointer to store auxiliary variable for x*y */
    273 )
    274{
    275 assert(sepadata != NULL);
    276 assert(idx >= 0 && idx < sepadata->nminors);
    277 assert(auxvarxx != NULL);
    278 assert(auxvaryy != NULL);
    279 assert(auxvarxy != NULL);
    280
    281 *x = sepadata->minors[5 * idx];
    282 *y = sepadata->minors[5 * idx + 1];
    283 *auxvarxx = sepadata->minors[5 * idx + 2];
    284 *auxvaryy = sepadata->minors[5 * idx + 3];
    285 *auxvarxy = sepadata->minors[5 * idx + 4];
    286
    287 return SCIP_OKAY;
    288}
    289
    290/** method to detect and store principal minors */
    291static
    293 SCIP* scip, /**< SCIP data structure */
    294 SCIP_SEPADATA* sepadata /**< separator data */
    295 )
    296{
    297 SCIP_CONSHDLR* conshdlr;
    298 SCIP_EXPRITER* it;
    299 SCIP_HASHMAP* quadmap;
    300 SCIP_VAR** xs;
    301 SCIP_VAR** ys;
    302 SCIP_VAR** auxvars;
    303 int* perm = NULL;
    304 int nbilinterms = 0;
    305 int nquadterms = 0;
    306 int maxminors;
    307 int c;
    308 int i;
    309
    310#ifdef SCIP_STATISTIC
    311 SCIP_Real totaltime = -SCIPgetTotalTime(scip);
    312#endif
    313
    314 assert(sepadata != NULL);
    315
    316 /* check whether minor detection has been called already */
    317 if( sepadata->detectedminors )
    318 return SCIP_OKAY;
    319
    320 assert(sepadata->minors == NULL);
    321 assert(sepadata->nminors == 0);
    322
    323 /* we assume that the auxiliary variables in the nonlinear constraint handler have been already generated */
    324 sepadata->detectedminors = TRUE;
    325
    326 /* check whether there are nonlinear constraints available */
    327 conshdlr = SCIPfindConshdlr(scip, "nonlinear");
    328 if( conshdlr == NULL || SCIPconshdlrGetNConss(conshdlr) == 0 )
    329 return SCIP_OKAY;
    330
    331 SCIPdebugMsg(scip, "call detectMinors()\n");
    332
    333 /* allocate memory */
    339
    340 /* initialize iterator */
    343
    344 for( c = 0; c < SCIPconshdlrGetNConss(conshdlr); ++c )
    345 {
    346 SCIP_CONS* cons;
    347 SCIP_EXPR* expr;
    348 SCIP_EXPR* root;
    349
    350 cons = SCIPconshdlrGetConss(conshdlr)[c];
    351 assert(cons != NULL);
    352 root = SCIPgetExprNonlinear(cons);
    353 assert(root != NULL);
    354
    355 /* ignore circle packing constraints; the motivation for this is that in circle packing instance not only the SDP
    356 * relaxation is weak (see "Packing circles in a square: a theoretical comparison of various convexification
    357 * techniques", http://www.optimization-online.org/DB_HTML/2017/03/5911.html), but it also hurts performance
    358 */
    359 if( sepadata->ignorepackingconss && isPackingCons(scip, cons) )
    360 {
    361 SCIPdebugMsg(scip, "ignore packing constraints %s\n", SCIPconsGetName(cons));
    362 continue;
    363 }
    364
    365 for( expr = SCIPexpriterRestartDFS(it, root); !SCIPexpriterIsEnd(it); expr = SCIPexpriterGetNext(it) ) /*lint !e441*/ /*lint !e440*/
    366 {
    367 SCIP_EXPR** children;
    368 SCIP_VAR* auxvar;
    369
    370 SCIPdebugMsg(scip, "visit expression %p in constraint %s\n", (void*)expr, SCIPconsGetName(cons));
    371
    372 /* check whether the expression has an auxiliary variable */
    373 auxvar = SCIPgetExprAuxVarNonlinear(expr);
    374 if( auxvar == NULL )
    375 {
    376 SCIPdebugMsg(scip, "expression has no auxiliary variable -> skip\n");
    377 continue;
    378 }
    379
    380 children = SCIPexprGetChildren(expr);
    381
    382 /* check for expr = (x)^2 */
    383 if( SCIPexprGetNChildren(expr) == 1 && SCIPisExprPower(scip, expr)
    384 && SCIPgetExponentExprPow(expr) == 2.0
    385 && SCIPgetExprAuxVarNonlinear(children[0]) != NULL )
    386 {
    387 SCIP_VAR* quadvar;
    388
    389 assert(children[0] != NULL);
    390
    391 quadvar = SCIPgetExprAuxVarNonlinear(children[0]);
    392 assert(quadvar != NULL);
    393 assert(!SCIPhashmapExists(quadmap, (void*)quadvar));
    394 SCIPdebugMsg(scip, "found %s = (%s)^2\n", SCIPvarGetName(auxvar), SCIPvarGetName(quadvar));
    395
    396 /* hash the quadratic variable to its corresponding auxiliary variable */
    397 SCIP_CALL( SCIPhashmapInsert(quadmap, (void*)quadvar, auxvar) );
    398 ++nquadterms;
    399 }
    400 /* check for expr = x * y */
    401 else if( SCIPexprGetNChildren(expr) == 2 && SCIPisExprProduct(scip, expr)
    402 && SCIPgetExprAuxVarNonlinear(children[0]) != NULL && SCIPgetExprAuxVarNonlinear(children[1]) != NULL )
    403 {
    404 SCIP_VAR* x;
    405 SCIP_VAR* y;
    406
    407 assert(children[0] != NULL);
    408 assert(children[1] != NULL);
    409
    410 x = SCIPgetExprAuxVarNonlinear(children[0]);
    411 y = SCIPgetExprAuxVarNonlinear(children[1]);
    412
    413 /* ignore binary variables */
    415 {
    416 xs[nbilinterms] = SCIPgetExprAuxVarNonlinear(children[0]);
    417 ys[nbilinterms] = SCIPgetExprAuxVarNonlinear(children[1]);
    418 auxvars[nbilinterms] = auxvar;
    419 SCIPdebugMsg(scip, "found %s = %s * %s\n", SCIPvarGetName(auxvar), SCIPvarGetName(xs[nbilinterms]), SCIPvarGetName(ys[nbilinterms]));
    420 ++nbilinterms;
    421 }
    422 }
    423 }
    424 }
    425 assert(nbilinterms < SCIPgetNVars(scip));
    426 SCIPdebugMsg(scip, "stored %d bilinear terms in total\n", nbilinterms);
    427
    428 /* use max(maxminorsconst, maxminorsfac * # quadratic terms) as a limit for the maximum number of minors */
    429 maxminors = (int) MAX(sepadata->maxminorsconst, sepadata->maxminorsfac * nquadterms);
    430 SCIPdebugMsg(scip, "maximum number of minors = %d\n", maxminors);
    431
    432 /* permute bilinear terms if there are too many of them; the motivation for this is that we don't want to
    433 * prioritize variables because of the order in the bilinear terms where they appear; however, variables that
    434 * appear more often in bilinear terms might be more important than others so the corresponding bilinear terms
    435 * are more likely to be chosen
    436 */
    437 if( maxminors < nbilinterms && maxminors < SQR(nquadterms) )
    438 {
    439 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nbilinterms) );
    440
    441 for( i = 0; i < nbilinterms; ++i )
    442 perm[i] = i;
    443
    444 /* permute array */
    445 SCIPrandomPermuteIntArray(sepadata->randnumgen, perm, 0, nbilinterms);
    446 }
    447
    448 /* store 2x2 principal minors */
    449 for( i = 0; i < nbilinterms && sepadata->nminors < maxminors; ++i )
    450 {
    451 SCIP_VAR* x;
    452 SCIP_VAR* y;
    453 SCIP_VAR* auxvarxy;
    454
    455 if( perm == NULL )
    456 {
    457 x = xs[i];
    458 y = ys[i];
    459 auxvarxy = auxvars[i];
    460 }
    461 else
    462 {
    463 x = xs[perm[i]];
    464 y = ys[perm[i]];
    465 auxvarxy = auxvars[perm[i]];
    466 }
    467
    468 assert(x != NULL);
    469 assert(y != NULL);
    470 assert(auxvarxy != NULL);
    471 assert(x != y);
    472
    473 if( SCIPhashmapExists(quadmap, (void*)x) && SCIPhashmapExists(quadmap, (void*)y) )
    474 {
    475 SCIP_VAR* auxvarxx;
    476 SCIP_VAR* auxvaryy;
    477
    478 auxvarxx = (SCIP_VAR*)SCIPhashmapGetImage(quadmap, (void*)x);
    479 assert(auxvarxx != NULL);
    480 auxvaryy = (SCIP_VAR*)SCIPhashmapGetImage(quadmap, (void*)y);
    481 assert(auxvaryy != NULL);
    482
    483 /* store minor into the separation data */
    484 SCIP_CALL( sepadataAddMinor(scip, sepadata, x, y, auxvarxx, auxvaryy, auxvarxy) );
    485 }
    486 }
    487 SCIPdebugMsg(scip, "found %d principal minors in total\n", sepadata->nminors);
    488
    489 /* free memory */
    491 SCIPfreeBufferArray(scip, &auxvars);
    494 SCIPhashmapFree(&quadmap);
    495 SCIPfreeExpriter(&it);
    496
    497#ifdef SCIP_STATISTIC
    498 totaltime += SCIPgetTotalTime(scip);
    499 SCIPstatisticMessage("MINOR DETECT %s %f %d %d\n", SCIPgetProbName(scip), totaltime, sepadata->nminors, maxminors);
    500#endif
    501
    502 return SCIP_OKAY;
    503}
    504
    505/** helper method to compute eigenvectors and eigenvalues */
    506static
    508 SCIP* scip, /**< SCIP data structure */
    509 SCIP_Real x, /**< solution value of x */
    510 SCIP_Real y, /**< solution value of y */
    511 SCIP_Real xx, /**< solution value of x*x */
    512 SCIP_Real yy, /**< solution value of y*y */
    513 SCIP_Real xy, /**< solution value of x*y */
    514 SCIP_Real* eigenvals, /**< array to store eigenvalues (at least of size 3) */
    515 SCIP_Real* eigenvecs, /**< array to store eigenvalues (at least of size 9) */
    516 SCIP_Bool* success /**< pointer to store whether eigenvalue computation was successful */
    517 )
    518{
    519 assert(eigenvals != NULL);
    520 assert(eigenvecs != NULL);
    521 assert(success != NULL);
    522
    523 *success = TRUE;
    524
    525 /* construct matrix */
    526 eigenvecs[0] = 1.0;
    527 eigenvecs[1] = x;
    528 eigenvecs[2] = y;
    529 eigenvecs[3] = x;
    530 eigenvecs[4] = xx;
    531 eigenvecs[5] = xy;
    532 eigenvecs[6] = y;
    533 eigenvecs[7] = xy;
    534 eigenvecs[8] = yy;
    535
    536 /* use LAPACK to compute the eigenvalues and eigenvectors */
    537 if( SCIPlapackComputeEigenvalues(SCIPbuffer(scip), TRUE, 3, eigenvecs, eigenvals) != SCIP_OKAY )
    538 {
    539 SCIPdebugMsg(scip, "Failed to compute eigenvalues and eigenvectors of augmented quadratic form matrix.\n");
    540 *success = FALSE;
    541 }
    542
    543 return SCIP_OKAY;
    544}
    545
    546/** generate and add a cut */
    547static
    549 SCIP* scip, /**< SCIP data structure */
    550 SCIP_SEPA* sepa, /**< separator */
    551 SCIP_SOL* sol, /**< solution to separate (might be NULL) */
    552 SCIP_VAR* x, /**< x variable */
    553 SCIP_VAR* y, /**< y variable */
    554 SCIP_VAR* xx, /**< auxiliary variable for x*x */
    555 SCIP_VAR* yy, /**< auxiliary variable for y*y */
    556 SCIP_VAR* xy, /**< auxiliary variable for x*y */
    557 SCIP_Real* eigenvec, /**< array containing an eigenvector */
    558 SCIP_Real eigenval, /**< eigenvalue */
    559 SCIP_Real mincutviol, /**< minimal required violation */
    560 SCIP_RESULT* result /**< pointer to update the result */
    561 )
    562{
    563 SCIP_VAR* vars[5] = {x, y, xx, yy, xy};
    564 SCIP_Real coefs[5];
    565 SCIP_Real constant;
    566 SCIP_ROWPREP* rowprep;
    567 SCIP_Bool success;
    568
    569 assert(x != NULL);
    570 assert(y != NULL);
    571 assert(xx != NULL);
    572 assert(yy != NULL);
    573 assert(xy != NULL);
    574 assert(eigenvec != NULL);
    575 assert(mincutviol >= 0.0);
    576 assert(result != NULL);
    577
    578 /* check whether the resulting cut is violated enough */
    579 if( !SCIPisFeasLT(scip, eigenval, -mincutviol) )
    580 return SCIP_OKAY;
    581
    582 /* the resulting cut reads as
    583 * (1 x y ) (v0)
    584 * (v0 v1 v2) (x xx xy) (v1) >= 0
    585 * (y xy yy) (v2)
    586 * where v is the eigenvector corresponding to a negative eigenvalue
    587 * that is,
    588 * v0^2 + 2 v0 v1 * x + 2 v0 v2 * y + v1^2 * xx + v2^2 * yy + 2 v1 v2 * xy >= 0
    589 */
    590 constant = SQR(eigenvec[0]);
    591 coefs[0] = 2.0 * eigenvec[0] * eigenvec[1];
    592 coefs[1] = 2.0 * eigenvec[0] * eigenvec[2];
    593 coefs[2] = SQR(eigenvec[1]);
    594 coefs[3] = SQR(eigenvec[2]);
    595 coefs[4] = 2.0 * eigenvec[1] * eigenvec[2];
    596
    597 /* create rowprep */
    599 SCIP_CALL( SCIPaddRowprepTerms(scip, rowprep, 5, vars, coefs) );
    600 SCIProwprepAddConstant(rowprep, constant);
    601 SCIPdebug( SCIPprintRowprep(scip, rowprep, NULL) );
    602 SCIPdebugMsg(scip, "cut violation %g mincutviol = %g\n", SCIPgetRowprepViolation(scip, rowprep, sol, NULL), mincutviol);
    603
    604 /* cleanup coefficient and side, esp treat epsilon to integral values; don't consider scaling up here */
    605 SCIP_CALL( SCIPcleanupRowprep(scip, rowprep, NULL, 0.0, NULL, &success) );
    606
    607 /* check cut violation */
    608 if( success && SCIPgetRowprepViolation(scip, rowprep, sol, NULL) > mincutviol )
    609 {
    610 SCIP_ROW* row;
    611 SCIP_Bool infeasible;
    612
    613 /* set name of rowprep */
    614 (void) SCIPsnprintf(SCIProwprepGetName(rowprep), SCIP_MAXSTRLEN, "minor_%s_%s_%s_%lld", SCIPvarGetName(xx), SCIPvarGetName(yy),
    616
    617 /* create, add, and release row */
    618 SCIP_CALL( SCIPgetRowprepRowSepa(scip, &row, rowprep, sepa) );
    619 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    620 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    621
    622 /* update result pointer */
    623 *result = infeasible ? SCIP_CUTOFF : SCIP_SEPARATED;
    624 }
    625
    626 /* free rowprep */
    627 SCIPfreeRowprep(scip, &rowprep);
    628
    629 return SCIP_OKAY;
    630}
    631
    632/** separates cuts for stored principal minors */
    633static
    635 SCIP* scip, /**< SCIP data structure */
    636 SCIP_SEPA* sepa, /**< separator */
    637 SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
    638 SCIP_RESULT* result /**< pointer to store the result of the separation call */
    639 )
    640{
    641 SCIP_SEPADATA* sepadata;
    642 int i;
    643
    644 assert(sepa != NULL);
    645 assert(result != NULL);
    646
    647 *result = SCIP_DIDNOTRUN;
    648
    649 sepadata = SCIPsepaGetData(sepa);
    650 assert(sepadata != NULL);
    651
    652 /* check whether there are some minors available */
    653 if( sepadata->nminors == 0 )
    654 return SCIP_OKAY;
    655
    656 *result = SCIP_DIDNOTFIND;
    657
    658 for( i = 0; i < sepadata->nminors && (*result != SCIP_CUTOFF); ++i )
    659 {
    660 SCIP_Real eigenvals[3];
    661 SCIP_Real eigenvecs[9];
    662 SCIP_VAR* x;
    663 SCIP_VAR* y;
    664 SCIP_VAR* xx;
    665 SCIP_VAR* yy;
    666 SCIP_VAR* xy;
    667 SCIP_Real solx;
    668 SCIP_Real soly;
    669 SCIP_Real solxx;
    670 SCIP_Real solyy;
    671 SCIP_Real solxy;
    672 SCIP_Bool success;
    673 int k;
    674
    675 /* get variables of the i-th minor */
    676 SCIP_CALL( getMinorVars(sepadata, i, &x, &y, &xx, &yy, &xy) );
    677 assert(x != NULL);
    678 assert(y != NULL);
    679 assert(xx != NULL);
    680 assert(yy != NULL);
    681 assert(xy != NULL);
    682
    683 /* get current solution values */
    684 solx = SCIPgetSolVal(scip, sol, x);
    685 soly = SCIPgetSolVal(scip, sol, y);
    686 solxx = SCIPgetSolVal(scip, sol, xx);
    687 solyy = SCIPgetSolVal(scip, sol, yy);
    688 solxy = SCIPgetSolVal(scip, sol, xy);
    689 SCIPdebugMsg(scip, "solution values (x,y,xx,yy,xy)=(%g,%g,%g,%g,%g)\n", solx, soly, solxx, solyy, solxy);
    690
    691 /* compute eigenvalues and eigenvectors */
    692 SCIP_CALL( getEigenValues(scip, solx, soly, solxx, solyy, solxy, eigenvals, eigenvecs, &success) );
    693 if( !success )
    694 continue;
    695
    696 /* try to generate a cut for each negative eigenvalue */
    697 for( k = 0; k < 3 && (*result != SCIP_CUTOFF); ++k )
    698 {
    699 SCIPdebugMsg(scip, "eigenvalue = %g eigenvector = (%g,%g,%g)\n", eigenvals[k], eigenvecs[3*k], eigenvecs[3*k + 1], eigenvecs[3*k + 2]);
    700 SCIP_CALL( addCut(scip, sepa, sol, x, y, xx, yy, xy, &eigenvecs[3*k], eigenvals[k], sepadata->mincutviol, result) );
    701 SCIPdebugMsg(scip, "result: %d\n", *result);
    702 }
    703 }
    704
    705 return SCIP_OKAY;
    706}
    707
    708/*
    709 * Callback methods of separator
    710 */
    711
    712/** copy method for separator plugins (called when SCIP copies plugins) */
    713static
    714SCIP_DECL_SEPACOPY(sepaCopyMinor)
    715{ /*lint --e{715}*/
    716 assert(scip != NULL);
    717 assert(sepa != NULL);
    718
    720
    721 /* call inclusion method of constraint handler */
    723
    724 return SCIP_OKAY;
    725}
    726
    727
    728/** destructor of separator to free user data (called when SCIP is exiting) */
    729static
    730SCIP_DECL_SEPAFREE(sepaFreeMinor)
    731{ /*lint --e{715}*/
    732 SCIP_SEPADATA* sepadata;
    733
    734 sepadata = SCIPsepaGetData(sepa);
    735 assert(sepadata != NULL);
    736 assert(sepadata->minors == NULL);
    737 assert(sepadata->nminors == 0);
    738 assert(sepadata->minorssize == 0);
    739
    740 /* free separator data */
    741 SCIPfreeBlockMemory(scip, &sepadata);
    742 SCIPsepaSetData(sepa, NULL);
    743
    744 return SCIP_OKAY;
    745}
    746
    747
    748/** initialization method of separator (called after problem was transformed) */
    749static
    750SCIP_DECL_SEPAINIT(sepaInitMinor)
    751{ /*lint --e{715}*/
    752 SCIP_SEPADATA* sepadata;
    753
    754 /* get separator data */
    755 sepadata = SCIPsepaGetData(sepa);
    756 assert(sepadata != NULL);
    757 assert(sepadata->randnumgen == NULL);
    758
    759 /* create random number generator */
    760 SCIP_CALL( SCIPcreateRandom(scip, &sepadata->randnumgen, DEFAULT_RANDSEED, TRUE) );
    761
    762 return SCIP_OKAY;
    763}
    764
    765
    766/** deinitialization method of separator (called before transformed problem is freed) */
    767static
    768SCIP_DECL_SEPAEXIT(sepaExitMinor)
    769{ /*lint --e{715}*/
    770 SCIP_SEPADATA* sepadata;
    771
    772 /* get separator data */
    773 sepadata = SCIPsepaGetData(sepa);
    774 assert(sepadata != NULL);
    775 assert(sepadata->randnumgen != NULL);
    776
    777 /* free random number generator */
    778 SCIPfreeRandom(scip, &sepadata->randnumgen);
    779
    780 return SCIP_OKAY;
    781}
    782
    783
    784/** solving process initialization method of separator (called when branch and bound process is about to begin) */
    785static
    786SCIP_DECL_SEPAINITSOL(sepaInitsolMinor)
    787{ /*lint --e{715}*/
    788 return SCIP_OKAY;
    789}
    790
    791
    792/** solving process deinitialization method of separator (called before branch and bound process data is freed) */
    793static
    794SCIP_DECL_SEPAEXITSOL(sepaExitsolMinor)
    795{ /*lint --e{715}*/
    796 SCIP_SEPADATA* sepadata;
    797
    798 sepadata = SCIPsepaGetData(sepa);
    799 assert(sepadata != NULL);
    800
    801 /* clear separation data */
    802 SCIP_CALL( sepadataClear(scip, sepadata) );
    803
    804 return SCIP_OKAY;
    805}
    806
    807
    808/** LP solution separation method of separator */
    809static
    810SCIP_DECL_SEPAEXECLP(sepaExeclpMinor)
    811{ /*lint --e{715}*/
    812 SCIP_SEPADATA* sepadata;
    813 int ncalls;
    814
    815 /* need routine to compute eigenvalues/eigenvectors */
    816 if( ! SCIPlapackIsAvailable() )
    817 return SCIP_OKAY;
    818
    819 sepadata = SCIPsepaGetData(sepa);
    820 assert(sepadata != NULL);
    821 ncalls = SCIPsepaGetNCallsAtNode(sepa);
    822
    823 /* only call the separator a given number of times at each node */
    824 if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
    825 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
    826 {
    827 SCIPdebugMsg(scip, "reached round limit for node\n");
    828 return SCIP_OKAY;
    829 }
    830
    831 /* try to detect minors */
    832 SCIP_CALL( detectMinors(scip, sepadata) );
    833
    834 /* call separation method */
    835 SCIP_CALL( separatePoint(scip, sepa, NULL, result) );
    836
    837 return SCIP_OKAY;
    838}
    839
    840
    841/** arbitrary primal solution separation method of separator */
    842static
    843SCIP_DECL_SEPAEXECSOL(sepaExecsolMinor)
    844{ /*lint --e{715}*/
    845 SCIP_SEPADATA* sepadata;
    846 int ncalls;
    847
    848 /* need routine to compute eigenvalues/eigenvectors */
    849 if( ! SCIPlapackIsAvailable() )
    850 return SCIP_OKAY;
    851
    852 sepadata = SCIPsepaGetData(sepa);
    853 assert(sepadata != NULL);
    854 ncalls = SCIPsepaGetNCallsAtNode(sepa);
    855
    856 /* only call the separator a given number of times at each node */
    857 if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
    858 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
    859 {
    860 SCIPdebugMsg(scip, "reached round limit for node\n");
    861 return SCIP_OKAY;
    862 }
    863
    864 /* try to detect minors */
    866
    867 /* call separation method */
    868 SCIP_CALL( separatePoint(scip, sepa, sol, result) );
    869
    870 return SCIP_OKAY;
    871}
    872
    873/*
    874 * separator specific interface methods
    875 */
    876
    877/** creates the minor separator and includes it in SCIP */
    879 SCIP* scip /**< SCIP data structure */
    880 )
    881{
    882 SCIP_SEPADATA* sepadata = NULL;
    883 SCIP_SEPA* sepa = NULL;
    884
    885 /* create minor separator data */
    886 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
    887 BMSclearMemory(sepadata);
    888
    889 /* include separator */
    892 sepaExeclpMinor, sepaExecsolMinor,
    893 sepadata) );
    894
    895 assert(sepa != NULL);
    896
    897 /* set non fundamental callbacks via setter functions */
    898 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyMinor) );
    899 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeMinor) );
    900 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitMinor) );
    901 SCIP_CALL( SCIPsetSepaExit(scip, sepa, sepaExitMinor) );
    902 SCIP_CALL( SCIPsetSepaInitsol(scip, sepa, sepaInitsolMinor) );
    903 SCIP_CALL( SCIPsetSepaExitsol(scip, sepa, sepaExitsolMinor) );
    904
    905 /* add minor separator parameters */
    907 "separating/" SEPA_NAME "/maxminorsconst",
    908 "constant for the maximum number of minors, i.e., max(const, fac * # quadratic terms)",
    909 &sepadata->maxminorsconst, FALSE, DEFAULT_MAXMINORSCONST, 0, INT_MAX, NULL, NULL) );
    910
    912 "separating/" SEPA_NAME "/maxminorsfac",
    913 "factor for the maximum number of minors, i.e., max(const, fac * # quadratic terms)",
    914 &sepadata->maxminorsfac, FALSE, DEFAULT_MAXMINORSFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    915
    917 "separating/" SEPA_NAME "/mincutviol",
    918 "minimum required violation of a cut",
    919 &sepadata->mincutviol, FALSE, DEFAULT_MINCUTVIOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    920
    922 "separating/" SEPA_NAME "/maxrounds",
    923 "maximal number of separation rounds per node (-1: unlimited)",
    924 &sepadata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
    925
    927 "separating/" SEPA_NAME "/maxroundsroot",
    928 "maximal number of separation rounds in the root node (-1: unlimited)",
    929 &sepadata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
    930
    932 "separating/" SEPA_NAME "/ignorepackingconss",
    933 "whether to ignore circle packing constraints during minor detection",
    934 &sepadata->ignorepackingconss, FALSE, DEFAULT_IGNOREPACKINGCONSS, NULL, NULL) );
    935
    936 return SCIP_OKAY;
    937}
    SCIP_VAR ** y
    Definition: circlepacking.c:64
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    constraint handler for nonlinear constraints specified by algebraic expressions
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define SQR(x)
    Definition: def.h:208
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_VAR * SCIPgetExprAuxVarNonlinear(SCIP_EXPR *expr)
    SCIP_EXPR * SCIPgetExprNonlinear(SCIP_CONS *cons)
    const char * SCIPgetProbName(SCIP *scip)
    Definition: scip_prob.c:1242
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3143
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
    Definition: misc.c:10264
    int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4782
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4739
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
    Definition: expr_pow.c:3449
    SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1490
    SCIP_Bool SCIPexpriterIsEnd(SCIP_EXPRITER *iterator)
    Definition: expriter.c:969
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    void SCIPexpriterSetStagesDFS(SCIP_EXPRITER *iterator, SCIP_EXPRITER_STAGE stopstages)
    Definition: expriter.c:664
    SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1457
    SCIP_EXPR * SCIPexpriterRestartDFS(SCIP_EXPRITER *iterator, SCIP_EXPR *expr)
    Definition: expriter.c:630
    SCIP_RETCODE SCIPcreateExpriter(SCIP *scip, SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2362
    SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1501
    SCIP_EXPR * SCIPexpriterGetNext(SCIP_EXPRITER *iterator)
    Definition: expriter.c:858
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
    Definition: expr_var.c:423
    void SCIPfreeExpriter(SCIP_EXPRITER **iterator)
    Definition: scip_expr.c:2376
    SCIP_RETCODE SCIPexpriterInit(SCIP_EXPRITER *iterator, SCIP_EXPR *expr, SCIP_EXPRITER_TYPE type, SCIP_Bool allowrevisit)
    Definition: expriter.c:501
    BMS_BLKMEM * SCIPblkmem(SCIP *scip)
    Definition: scip_mem.c:57
    BMS_BUFMEM * SCIPbuffer(SCIP *scip)
    Definition: scip_mem.c:72
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPsetSepaExit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXIT((*sepaexit)))
    Definition: scip_sepa.c:205
    SCIP_RETCODE SCIPsetSepaInitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINITSOL((*sepainitsol)))
    Definition: scip_sepa.c:221
    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)
    Definition: scip_sepa.c:115
    const char * SCIPsepaGetName(SCIP_SEPA *sepa)
    Definition: sepa.c:746
    int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
    Definition: sepa.c:893
    SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
    Definition: scip_sepa.c:173
    SCIP_RETCODE SCIPsetSepaExitsol(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXITSOL((*sepaexitsol)))
    Definition: scip_sepa.c:237
    SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
    Definition: sepa.c:636
    void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
    Definition: sepa.c:646
    SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
    Definition: scip_sepa.c:157
    SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINIT((*sepainit)))
    Definition: scip_sepa.c:189
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_Real SCIPgetTotalTime(SCIP *scip)
    Definition: scip_timing.c:351
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    SCIP_Real SCIPgetRowprepViolation(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Bool *reliable)
    Definition: misc_rowprep.c:972
    char * SCIProwprepGetName(SCIP_ROWPREP *rowprep)
    Definition: misc_rowprep.c:689
    void SCIProwprepAddConstant(SCIP_ROWPREP *rowprep, SCIP_Real constant)
    Definition: misc_rowprep.c:760
    SCIP_RETCODE SCIPgetRowprepRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_ROWPREP *rowprep, SCIP_SEPA *sepa)
    SCIP_RETCODE SCIPcreateRowprep(SCIP *scip, SCIP_ROWPREP **rowprep, SCIP_SIDETYPE sidetype, SCIP_Bool local)
    Definition: misc_rowprep.c:563
    SCIP_RETCODE SCIPaddRowprepTerms(SCIP *scip, SCIP_ROWPREP *rowprep, int nvars, SCIP_VAR **vars, SCIP_Real *coefs)
    Definition: misc_rowprep.c:938
    SCIP_RETCODE SCIPcleanupRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, SCIP_SOL *sol, SCIP_Real minviol, SCIP_Real *viol, SCIP_Bool *success)
    void SCIPfreeRowprep(SCIP *scip, SCIP_ROWPREP **rowprep)
    Definition: misc_rowprep.c:583
    void SCIPprintRowprep(SCIP *scip, SCIP_ROWPREP *rowprep, FILE *file)
    Definition: misc_rowprep.c:801
    SCIP_RETCODE SCIPincludeSepaMinor(SCIP *scip)
    Definition: sepa_minor.c:878
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_Bool SCIPlapackIsAvailable(void)
    Definition: lapack_calls.c:121
    SCIP_RETCODE SCIPlapackComputeEigenvalues(BMS_BUFMEM *bufmem, SCIP_Bool geteigenvectors, int N, SCIP_Real *a, SCIP_Real *w)
    Definition: lapack_calls.c:352
    interface methods for lapack functions
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    #define SCIPstatisticMessage
    Definition: pub_message.h:123
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SEPA_PRIORITY
    Definition: sepa_minor.c:41
    static SCIP_RETCODE getMinorVars(SCIP_SEPADATA *sepadata, int idx, SCIP_VAR **x, SCIP_VAR **y, SCIP_VAR **auxvarxx, SCIP_VAR **auxvaryy, SCIP_VAR **auxvarxy)
    Definition: sepa_minor.c:265
    #define DEFAULT_MAXMINORSFAC
    Definition: sepa_minor.c:48
    static SCIP_DECL_SEPAINIT(sepaInitMinor)
    Definition: sepa_minor.c:750
    #define SEPA_DELAY
    Definition: sepa_minor.c:45
    static SCIP_DECL_SEPAEXECLP(sepaExeclpMinor)
    Definition: sepa_minor.c:810
    static SCIP_RETCODE sepadataClear(SCIP *scip, SCIP_SEPADATA *sepadata)
    Definition: sepa_minor.c:135
    static SCIP_DECL_SEPAEXECSOL(sepaExecsolMinor)
    Definition: sepa_minor.c:843
    #define SEPA_DESC
    Definition: sepa_minor.c:40
    #define DEFAULT_MAXROUNDSROOT
    Definition: sepa_minor.c:52
    #define SEPA_USESSUBSCIP
    Definition: sepa_minor.c:44
    #define DEFAULT_IGNOREPACKINGCONSS
    Definition: sepa_minor.c:53
    static SCIP_RETCODE getEigenValues(SCIP *scip, SCIP_Real x, SCIP_Real y, SCIP_Real xx, SCIP_Real yy, SCIP_Real xy, SCIP_Real *eigenvals, SCIP_Real *eigenvecs, SCIP_Bool *success)
    Definition: sepa_minor.c:507
    #define DEFAULT_MAXMINORSCONST
    Definition: sepa_minor.c:47
    static SCIP_DECL_SEPAFREE(sepaFreeMinor)
    Definition: sepa_minor.c:730
    static SCIP_DECL_SEPACOPY(sepaCopyMinor)
    Definition: sepa_minor.c:714
    static SCIP_RETCODE sepadataAddMinor(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_VAR *x, SCIP_VAR *y, SCIP_VAR *auxvarxx, SCIP_VAR *auxvaryy, SCIP_VAR *auxvarxy)
    Definition: sepa_minor.c:81
    static SCIP_DECL_SEPAEXITSOL(sepaExitsolMinor)
    Definition: sepa_minor.c:794
    static SCIP_RETCODE separatePoint(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Definition: sepa_minor.c:634
    #define DEFAULT_MINCUTVIOL
    Definition: sepa_minor.c:49
    static SCIP_RETCODE detectMinors(SCIP *scip, SCIP_SEPADATA *sepadata)
    Definition: sepa_minor.c:292
    #define SEPA_MAXBOUNDDIST
    Definition: sepa_minor.c:43
    static SCIP_DECL_SEPAEXIT(sepaExitMinor)
    Definition: sepa_minor.c:768
    #define SEPA_FREQ
    Definition: sepa_minor.c:42
    #define DEFAULT_RANDSEED
    Definition: sepa_minor.c:50
    #define SEPA_NAME
    Definition: sepa_minor.c:39
    static SCIP_DECL_SEPAINITSOL(sepaInitsolMinor)
    Definition: sepa_minor.c:786
    static SCIP_Bool isPackingCons(SCIP *scip, SCIP_CONS *cons)
    Definition: sepa_minor.c:165
    #define DEFAULT_MAXROUNDS
    Definition: sepa_minor.c:51
    static SCIP_RETCODE addCut(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_VAR *x, SCIP_VAR *y, SCIP_VAR *xx, SCIP_VAR *yy, SCIP_VAR *xy, SCIP_Real *eigenvec, SCIP_Real eigenval, SCIP_Real mincutviol, SCIP_RESULT *result)
    Definition: sepa_minor.c:548
    principal minor separator
    @ SCIP_EXPRITER_DFS
    Definition: type_expr.h:718
    #define SCIP_EXPRITER_ENTEREXPR
    Definition: type_expr.h:694
    @ SCIP_SIDETYPE_LEFT
    Definition: type_lp.h:65
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    struct SCIP_SepaData SCIP_SEPADATA
    Definition: type_sepa.h:52