SCIP

    Solving Constraint Integer Programs

    cons_lop.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/* uncomment for debug output: */
    26/* #define SCIP_DEBUG */
    27
    28/**@file cons_lop.c
    29 * @brief constraint handler for linear ordering constraints
    30 * @author Marc Pfetsch
    31 *
    32 * We handle the following system of linear constraints:
    33 * - \f$ x_{ij} + x_{ji} = 1 \f$ for \f$i < j\f$ (symmetry equations - added initially)
    34 * - \f$ x_{ij} + x_{jk} + x_{ki} \leq 2 \f$ for \f$i < j, i < k, j \neq k\f$ (triangle inequalities - separated)
    35 */
    36
    37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    38
    39#include "cons_lop.h"
    40
    41
    42/* constraint handler properties */
    43#define CONSHDLR_NAME "lop"
    44#define CONSHDLR_DESC "linear ordering constraint handler"
    45#define CONSHDLR_SEPAPRIORITY 100 /**< priority of the constraint handler for separation */
    46#define CONSHDLR_ENFOPRIORITY -100 /**< priority of the constraint handler for constraint enforcing */
    47#define CONSHDLR_CHECKPRIORITY -100 /**< priority of the constraint handler for checking feasibility */
    48#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
    49#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    50#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    51 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    52#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    53#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    54#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    55
    56#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    57
    58
    59/** constraint data for linear ordering constraints */
    60struct SCIP_ConsData
    61{
    62 int n; /**< number of elements */
    63 SCIP_VAR*** vars; /**< variables */
    64};
    65
    66
    67/** separate symmetry equations and triangle inequalities */
    68static
    70 SCIP* scip, /**< SCIP pointer */
    71 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    72 int n, /**< number of elements */
    73 SCIP_VAR*** vars, /**< n x n matrix of variables */
    74 SCIP_SOL* sol, /**< solution to be separated */
    75 int* ngen, /**< output: pointer to store number of added rows */
    76 SCIP_Bool* cutoff /**< output: pointer to store whether we detected a cutoff */
    77 )
    78{
    79 char s[SCIP_MAXSTRLEN];
    80 int i;
    81 int j;
    82 int k;
    83
    84 assert( scip != NULL );
    85 assert( vars != NULL );
    86 assert( ngen != NULL );
    87 assert( cutoff != NULL );
    88
    89 /* Consider all (i,j,k) with i < j, i < k, j != k; since the inequalities are symmetric under cyclic shifts, we can
    90 * assume i to be the smallest index. */
    91 *cutoff = FALSE;
    92 for (i = 0; i < n && ! (*cutoff); ++i)
    93 {
    94 for (j = i+1; j < n && ! (*cutoff); ++j)
    95 {
    96 SCIP_Real valIJ;
    97
    98 valIJ = SCIPgetSolVal(scip, sol, vars[i][j]);
    99
    100 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
    101 if ( ! SCIPisFeasEQ(scip, valIJ + SCIPgetSolVal(scip, sol, vars[j][i]), 1.0) )
    102 {
    103 SCIP_ROW *row;
    104
    105 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    106
    107 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
    109 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    110 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    112#ifdef SCIP_DEBUG
    114#endif
    115 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    117 ++(*ngen);
    118
    119 if ( *cutoff )
    120 break;
    121 }
    122
    123 /* check triangle inequalities */
    124 for (k = i+1; k < n; ++k)
    125 {
    126 SCIP_Real sum;
    127
    128 if ( k == j )
    129 continue;
    130
    131 sum = valIJ + SCIPgetSolVal(scip, sol, vars[j][k]) + SCIPgetSolVal(scip, sol, vars[k][i]);
    132
    133 /* if sum - 2.0 > 0, i.e., the cut is violated */
    134 if ( SCIPisEfficacious(scip, sum - 2.0) )
    135 {
    136 SCIP_ROW *row;
    137
    138 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
    139
    140 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
    142 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    143 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
    144 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
    146#ifdef SCIP_DEBUG
    148#endif
    149 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    151 ++(*ngen);
    152
    153 if ( *cutoff )
    154 break;
    155 }
    156 }
    157 }
    158 }
    159
    160 return SCIP_OKAY;
    161}
    162
    163
    164/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    165static
    167{ /*lint --e{715}*/
    168 assert( scip != NULL );
    169 assert( conshdlr != NULL );
    170 assert( valid != NULL );
    171
    173
    174 /* call inclusion method of constraint handler */
    176
    177 *valid = TRUE;
    178
    179 return SCIP_OKAY;
    180}
    181
    182/** frees specific constraint data */
    183static
    185{ /*lint --e{715}*/
    186 int i;
    187 int n;
    188
    189 assert( scip != NULL );
    190 assert( conshdlr != NULL );
    191 assert( cons != NULL );
    192 assert( consdata != NULL);
    193 assert( *consdata != NULL);
    194 assert( (*consdata)->vars != NULL );
    195
    197
    198 SCIPdebugMsg(scip, "deleting linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    199
    200 n = (*consdata)->n;
    201 for (i = 0; i < n; ++i)
    202 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars[i]), n); /*lint !e866*/
    203 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars), n);
    204 SCIPfreeBlockMemory(scip, consdata);
    205
    206 return SCIP_OKAY;
    207}
    208
    209/** deinitialization method of constraint handler (called before transformed problem is freed)
    210 *
    211 * We output the final linear ordering.
    212 */
    213static
    215{ /*lint --e{715}*/
    216 SCIP_SOL* sol;
    217 int c;
    218 int i;
    219 int j;
    220 int n;
    221
    222 assert( scip != NULL );
    223 assert( conshdlr != NULL );
    224
    226
    227 SCIPdebugMsg(scip, "exiting linear ordering constraint handler <%s>.\n", SCIPconshdlrGetName(conshdlr));
    228
    229 /* avoid output for subscips */
    230 if ( SCIPgetSubscipDepth(scip) > 0 )
    231 return SCIP_OKAY;
    232
    233 /* get best solution */
    234 sol = SCIPgetBestSol(scip);
    235 if ( sol == NULL )
    236 return SCIP_OKAY;
    237
    238 /* loop through all constraints */
    239 for (c = 0; c < nconss; ++c)
    240 {
    241 SCIP_CONSDATA* consdata;
    242 SCIP_VAR*** vars;
    243 int* outdeg;
    244 int* indices;
    245
    246 assert( conss != NULL );
    247 assert( conss[c] != NULL );
    248 SCIPdebugMsg(scip, "solution for for linear ordering constraint <%s>.\n", SCIPconsGetName(conss[c]));
    249
    250 consdata = SCIPconsGetData(conss[c]);
    251 assert( consdata != NULL );
    252 assert( consdata->vars != NULL );
    253 n = consdata->n;
    254 vars = consdata->vars;
    255
    256 SCIP_CALL( SCIPallocBufferArray(scip, &outdeg, n) );
    257 SCIP_CALL( SCIPallocBufferArray(scip, &indices, n) );
    258
    259 /* compute out-degree */
    260 for (i = 0; i < n; ++i)
    261 {
    262 int deg = 0;
    263 for (j = 0; j < n; ++j)
    264 {
    265 SCIP_Real val;
    266
    267 if (j == i)
    268 continue;
    269
    270 val = SCIPgetSolVal(scip, sol, vars[i][j]);
    271 assert( SCIPisFeasIntegral(scip, val) );
    272 if ( val < 0.5 )
    273 ++deg;
    274 }
    275 outdeg[i] = deg;
    276 indices[i] = i;
    277 }
    278
    279 /* sort such that degrees are non-decreasing */
    280 SCIPsortIntInt(outdeg, indices, n);
    281
    282 /* output */
    283 SCIPinfoMessage(scip, NULL, "\nFinal order of linear ordering constraint <%s>:\n", SCIPconsGetName(conss[c]));
    284 for (i = 0; i < n; ++i)
    285 SCIPinfoMessage(scip, NULL, "%d ", indices[i]);
    286 SCIPinfoMessage(scip, NULL, "\n");
    287
    288 SCIPfreeBufferArray(scip, &indices);
    289 SCIPfreeBufferArray(scip, &outdeg);
    290 }
    291
    292 return SCIP_OKAY;
    293}
    294
    295/** transforms constraint data into data belonging to the transformed problem */
    296static
    298{ /*lint --e{715}*/
    299 SCIP_CONSDATA* consdata;
    300 SCIP_CONSDATA* sourcedata;
    301 int i;
    302 int j;
    303 int n;
    304 char s[SCIP_MAXSTRLEN];
    305
    306 assert( scip != NULL );
    307 assert( conshdlr != NULL );
    308 assert( sourcecons != NULL );
    309 assert( targetcons != NULL );
    310
    312
    313 SCIPdebugMsg(scip, "transforming linear ordering constraint <%s>.\n", SCIPconsGetName(sourcecons) );
    314
    315 /* get data of original constraint */
    316 sourcedata = SCIPconsGetData(sourcecons);
    317 assert( sourcedata != NULL);
    318
    319 /* create constraint data */
    320 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    321
    322 n = sourcedata->n;
    323 consdata->n = n;
    324
    325 /* transform variables */
    326 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
    327 for (i = 0; i < n; ++i)
    328 {
    329 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
    330 for (j = 0; j < n; ++j)
    331 {
    332 if (j != i)
    333 {
    334 assert( sourcedata->vars[i][j] != NULL );
    335 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[i][j], &(consdata->vars[i][j])) );
    336 }
    337 }
    338 }
    339
    340 /* create constraint */
    341 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
    342
    343 SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
    344 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
    345 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
    346 SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
    347 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
    348 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    349
    350 return SCIP_OKAY;
    351}
    352
    353/** LP initialization method of constraint handler */
    354static
    356{ /*lint --e{715}*/
    357 char s[SCIP_MAXSTRLEN];
    358 int c;
    359 int ngen = 0;
    360
    361 assert( scip != NULL );
    362 assert( conshdlr != NULL );
    363 assert( infeasible != NULL );
    364
    366
    367 *infeasible = FALSE;
    368
    369 /* loop through all constraints */
    370 for (c = 0; c < nconss; ++c)
    371 {
    372 SCIP_CONSDATA* consdata;
    373 SCIP_VAR*** vars;
    374 int i;
    375 int j;
    376 int n;
    377
    378 assert( conss != NULL );
    379 assert( conss[c] != NULL );
    380 SCIPdebugMsg(scip, "adding initial rows for linear ordering constraint <%s>.\n", SCIPconsGetName(conss[c]));
    381
    382 consdata = SCIPconsGetData(conss[c]);
    383 assert( consdata != NULL );
    384 assert( consdata->vars != NULL );
    385 n = consdata->n;
    386 vars = consdata->vars;
    387
    388 /* add symmetry equation */
    389 for (i = 0; i < n; ++i)
    390 {
    391 for (j = i+1; j < n; ++j)
    392 {
    393 SCIP_ROW* row;
    394
    395 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    396 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, FALSE) );
    398 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    399 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    401#ifdef SCIP_DEBUG
    403#endif
    404 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
    406 ++ngen;
    407
    408 /* cannot handle infeasible case here - just exit */
    409 if ( *infeasible )
    410 return SCIP_OKAY;
    411 }
    412 }
    413 }
    414 SCIPdebugMsg(scip, "added %d equations.\n", ngen);
    415
    416 return SCIP_OKAY;
    417}
    418
    419/** separation method of constraint handler for LP solutions */
    420static
    422{ /*lint --e{715}*/
    423 int ngen = 0;
    424 int c;
    425
    426 assert( scip != NULL );
    427 assert( conshdlr != NULL );
    428 assert( conss != NULL );
    429 assert( result != NULL );
    430
    432
    433 *result = SCIP_DIDNOTRUN;
    434
    435 /* loop through all constraints */
    436 for (c = 0; c < nconss; ++c)
    437 {
    438 SCIP_CONSDATA* consdata;
    439 SCIP_CONS* cons;
    440 SCIP_Bool cutoff;
    441
    442 cons = conss[c];
    443 assert( cons != NULL );
    444 SCIPdebugMsg(scip, "separating LP solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    445
    446 consdata = SCIPconsGetData(cons);
    447 assert( consdata != NULL );
    448
    449 *result = SCIP_DIDNOTFIND;
    450 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, NULL, &ngen, &cutoff) );
    451 if ( cutoff )
    452 {
    453 *result = SCIP_CUTOFF;
    454 return SCIP_OKAY;
    455 }
    456 }
    457 if ( ngen > 0 )
    458 *result = SCIP_SEPARATED;
    459 SCIPdebugMsg(scip, "separated %d cuts.\n", ngen);
    460
    461 return SCIP_OKAY;
    462}
    463
    464/** separation method of constraint handler for arbitrary primal solutions */
    465static
    467{ /*lint --e{715}*/
    468 int ngen = 0;
    469 int c;
    470
    471 assert( scip != NULL );
    472 assert( conshdlr != NULL );
    473 assert( conss != NULL );
    474 assert( result != NULL );
    475
    477
    478 *result = SCIP_DIDNOTRUN;
    479
    480 /* loop through all constraints */
    481 for (c = 0; c < nconss; ++c)
    482 {
    483 SCIP_CONSDATA* consdata;
    484 SCIP_CONS* cons;
    485 SCIP_Bool cutoff;
    486
    487 cons = conss[c];
    488 assert( cons != NULL );
    489 SCIPdebugMsg(scip, "separating solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    490
    491 consdata = SCIPconsGetData(cons);
    492 assert( consdata != NULL );
    493
    494 *result = SCIP_DIDNOTFIND;
    495 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, sol, &ngen, &cutoff) );
    496 if ( cutoff )
    497 {
    498 *result = SCIP_CUTOFF;
    499 return SCIP_OKAY;
    500 }
    501 }
    502 if ( ngen > 0 )
    503 *result = SCIP_SEPARATED;
    504
    505 return SCIP_OKAY;
    506}
    507
    508/** constraint enforcing method of constraint handler for LP solutions */
    509static
    511{ /*lint --e{715}*/
    512 char s[SCIP_MAXSTRLEN];
    513 int ngen = 0;
    514 int c;
    515
    516 assert( scip != NULL );
    517 assert( conshdlr != NULL );
    518 assert( conss != NULL );
    519 assert( result != NULL );
    520
    522
    523 *result = SCIP_DIDNOTRUN;
    524
    525 /* loop through all constraints */
    526 for (c = 0; c < nconss; ++c)
    527 {
    528 SCIP_CONSDATA* consdata;
    529 SCIP_CONS* cons;
    530 SCIP_VAR*** vars;
    531 int i;
    532 int j;
    533 int k;
    534 int n;
    535
    536 cons = conss[c];
    537 assert( cons != NULL );
    538 SCIPdebugMsg(scip, "enforcing lp solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    539
    540 consdata = SCIPconsGetData(cons);
    541 assert( consdata != NULL );
    542
    543 n = consdata->n;
    544 vars = consdata->vars;
    545 assert( vars != NULL );
    546
    547 for (i = 0; i < n; ++i)
    548 {
    549 for (j = i + 1; j < n; ++j)
    550 {
    551 SCIP_Real valIJ;
    552
    553 valIJ = SCIPgetSolVal(scip, NULL, vars[i][j]);
    554
    555 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
    556 if ( ! SCIPisFeasEQ(scip, 1.0 - valIJ, SCIPgetSolVal(scip, NULL, vars[j][i])) )
    557 {
    558 SCIP_ROW *row;
    559 SCIP_Bool infeasible;
    560
    561 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    562
    563 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
    565 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    566 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    568#ifdef SCIP_DEBUG
    570#endif
    571 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    573 ++ngen;
    574
    575 if ( infeasible )
    576 {
    577 *result = SCIP_CUTOFF;
    578 return SCIP_OKAY;
    579 }
    580 }
    581
    582 /* enforce triangle inequalities */
    583 for (k = i + 1; k < n; ++k)
    584 {
    585 SCIP_Real sum;
    586
    587 if ( k == j )
    588 continue;
    589
    590 sum = valIJ + SCIPgetSolVal(scip, NULL, vars[j][k]) + SCIPgetSolVal(scip, NULL, vars[k][i]);
    591
    592 /* if sum > 2.0, i.e., the cut is violated */
    593 if ( SCIPisFeasGT(scip, sum, 2.0) ) /* this is the only difference to the separation call */
    594 {
    595 SCIP_ROW *row;
    596 SCIP_Bool infeasible;
    597
    598 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
    599
    600 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
    602 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    603 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
    604 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
    606#ifdef SCIP_DEBUG
    608#endif
    609 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    611 ++ngen;
    612
    613 if ( infeasible )
    614 {
    615 *result = SCIP_CUTOFF;
    616 return SCIP_OKAY;
    617 }
    618 }
    619 }
    620 }
    621 }
    622
    623 if ( ngen > 0 )
    624 {
    625 *result = SCIP_SEPARATED;
    626 return SCIP_OKAY;
    627 }
    628
    629 }
    630 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    631 *result = SCIP_FEASIBLE;
    632
    633 return SCIP_OKAY;
    634}
    635
    636/** constraint enforcing method of constraint handler for pseudo solutions */
    637static
    639{ /*lint --e{715}*/
    640 int c;
    641
    642 assert( scip != NULL );
    643 assert( conshdlr != NULL );
    644 assert( conss != NULL );
    645 assert( result != NULL );
    646
    648
    649 /* loop through all constraints */
    650 for (c = 0; c < nconss; ++c)
    651 {
    652 SCIP_CONSDATA* consdata;
    653 SCIP_CONS* cons;
    654 SCIP_VAR*** vars;
    655 int i;
    656 int j;
    657 int k;
    658 int n;
    659
    660 cons = conss[c];
    661 assert( cons != NULL );
    662 SCIPdebugMsg(scip, "enforcing pseudo solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    663
    664 consdata = SCIPconsGetData(cons);
    665 assert( consdata != NULL );
    666 assert( consdata->vars != NULL );
    667 vars = consdata->vars;
    668 n = consdata->n;
    669
    670 /* check triangle inequalities */
    671 for (i = 0; i < n; ++i)
    672 {
    673 for (j = i + 1; j < n; ++j)
    674 {
    675 SCIP_Bool oneIJ;
    676 SCIP_Bool oneJI;
    677
    678 /* the priorities should ensure that the solution is integral */
    679 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[i][j])) );
    680 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][i])) );
    681
    682 oneIJ = SCIPgetSolVal(scip, NULL, vars[i][j]) > 0.5 ? TRUE : FALSE;
    683 oneJI = SCIPgetSolVal(scip, NULL, vars[j][i]) > 0.5 ? TRUE : FALSE;
    684
    685 if ( oneIJ == oneJI )
    686 {
    687 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
    688 *result = SCIP_INFEASIBLE;
    689 return SCIP_OKAY;
    690 }
    691
    692 for (k = i + 1; k < n; ++k)
    693 {
    694 SCIP_Bool oneJK;
    695 SCIP_Bool oneKI;
    696
    697 if ( k == j )
    698 continue;
    699
    700 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][k])) );
    701 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[k][i])) );
    702
    703 oneJK = SCIPgetSolVal(scip, NULL, vars[j][k]) > 0.5 ? TRUE : FALSE;
    704 oneKI = SCIPgetSolVal(scip, NULL, vars[k][i]) > 0.5 ? TRUE : FALSE;
    705
    706 /* if triangle inequality is violated */
    707 if ( oneIJ && oneJK && oneKI )
    708 {
    709 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
    710 *result = SCIP_INFEASIBLE;
    711 return SCIP_OKAY;
    712 }
    713 }
    714 }
    715 }
    716 }
    717 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    718 *result = SCIP_FEASIBLE;
    719
    720 return SCIP_OKAY;
    721}
    722
    723/** feasibility check method of constraint handler for integral solutions */
    724static
    726{ /*lint --e{715}*/
    727 int c;
    728
    729 assert( scip != NULL );
    730 assert( conshdlr != NULL );
    731 assert( conss != NULL );
    732 assert( result != NULL );
    733
    735
    736 /* loop through all constraints */
    737 for (c = 0; c < nconss; ++c)
    738 {
    739 SCIP_CONSDATA* consdata;
    740 SCIP_CONS* cons;
    741 SCIP_VAR*** vars;
    742 int i;
    743 int j;
    744 int k;
    745 int n;
    746
    747 cons = conss[c];
    748 assert( cons != NULL );
    749 SCIPdebugMsg(scip, "checking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    750
    751 consdata = SCIPconsGetData(cons);
    752 assert( consdata != NULL );
    753 assert( consdata->vars != NULL );
    754 vars = consdata->vars;
    755 n = consdata->n;
    756
    757 /* check triangle inequalities and symmetry equations */
    758 for (i = 0; i < n; ++i)
    759 {
    760 for (j = i + 1; j < n; ++j)
    761 {
    762 SCIP_Bool oneIJ;
    763 SCIP_Bool oneJI;
    764
    765 /* the priorities should ensure that the solution is integral */
    766 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[i][j])) );
    767 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][i])) );
    768
    769 oneIJ = SCIPgetSolVal(scip, sol, vars[i][j]) > 0.5 ? TRUE : FALSE;
    770 oneJI = SCIPgetSolVal(scip, sol, vars[j][i]) > 0.5 ? TRUE : FALSE;
    771
    772 /* check symmetry equations */
    773 if ( oneIJ == oneJI )
    774 {
    775 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
    776 *result = SCIP_INFEASIBLE;
    777 if( printreason )
    778 {
    779 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    780 SCIPinfoMessage(scip, NULL, "violation: symmetry equation violated <%s> = %.15g and <%s> = %.15g\n",
    781 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
    782 SCIPvarGetName(vars[j][i]), SCIPgetSolVal(scip, sol, vars[j][i]));
    783 }
    784 return SCIP_OKAY;
    785 }
    786
    787 for (k = i + 1; k < n; ++k)
    788 {
    789 SCIP_Bool oneJK;
    790 SCIP_Bool oneKI;
    791
    792 if ( k == j )
    793 continue;
    794
    795 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][k])) );
    796 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[k][i])) );
    797
    798 oneJK = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[j][k]), 0.5);
    799 oneKI = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[k][i]), 0.5);
    800
    801 /* if triangle inequality is violated */
    802 if ( oneIJ && oneJK && oneKI )
    803 {
    804 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
    805 *result = SCIP_INFEASIBLE;
    806 if( printreason )
    807 {
    808 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    810 "violation: triangle inequality violated <%s> = %.15g, <%s> = %.15g, <%s> = %.15g\n",
    811 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
    812 SCIPvarGetName(vars[j][k]), SCIPgetSolVal(scip, sol, vars[j][k]),
    813 SCIPvarGetName(vars[k][i]), SCIPgetSolVal(scip, sol, vars[k][i]));
    814 }
    815 return SCIP_OKAY;
    816 }
    817 }
    818 }
    819 }
    820 }
    821 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    822 *result = SCIP_FEASIBLE;
    823
    824 return SCIP_OKAY;
    825}
    826
    827/** domain propagation method of constraint handler */
    828static
    830{ /*lint --e{715}*/
    831 int c;
    832 int ngen = 0;
    833
    834 assert( scip != NULL );
    835 assert( conshdlr != NULL );
    836 assert( conss != NULL );
    837 assert( result != NULL );
    838
    840
    841 *result = SCIP_DIDNOTRUN;
    842
    843 /* loop through all constraints */
    844 for (c = 0; c < nconss; ++c)
    845 {
    846 SCIP_CONSDATA* consdata;
    847 SCIP_CONS* cons;
    848 SCIP_VAR*** vars;
    849 int i;
    850 int j;
    851 int k;
    852 int n;
    853
    854 cons = conss[c];
    855 assert( cons != NULL );
    856 SCIPdebugMsg(scip, "propagating linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    857
    858 *result = SCIP_DIDNOTFIND;
    859
    860 consdata = SCIPconsGetData(cons);
    861 assert( consdata != NULL );
    862 assert( consdata->vars != NULL );
    863
    864 vars = consdata->vars;
    865 n = consdata->n;
    866
    867 /* check triangle inequalities */
    868 for (i = 0; i < n; ++i)
    869 {
    870 for (j = i + 1; j < n; ++j)
    871 {
    872 SCIP_Bool infeasible;
    873 SCIP_Bool tightened;
    874
    875 /* for consistency make sure that the complementarity constraints are satisfied */
    876
    877 /* if x[i][j] == 1 then x[j][i] = 0 */
    878 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
    879 {
    880 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], FALSE, cons, i*n + j, &infeasible, &tightened) );
    881 if ( infeasible )
    882 {
    883 SCIPdebugMsg(scip, " -> node infeasible.\n");
    885 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    886 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
    888 *result = SCIP_CUTOFF;
    889 return SCIP_OKAY;
    890 }
    891 if ( tightened )
    892 ++ngen;
    893 }
    894
    895 /* if x[i][j] == 0 then x[j][i] = 1 */
    896 if ( SCIPvarGetUbLocal(vars[i][j]) < 0.5 )
    897 {
    898 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], TRUE, cons, i*n + j, &infeasible, &tightened) );
    899 if ( infeasible )
    900 {
    901 SCIPdebugMsg(scip, " -> node infeasible.\n");
    903 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    904 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
    906 *result = SCIP_CUTOFF;
    907 return SCIP_OKAY;
    908 }
    909 if ( tightened )
    910 ++ngen;
    911 }
    912
    913 /* check whether triangle inequality allows to fix variables */
    914 for (k = i + 1; k < n; ++k)
    915 {
    916 if ( k == j )
    917 continue;
    918
    919 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
    920 {
    921 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 )
    922 {
    923 /* if x[i][j] == 1 and x[j][k] == 1 then x[k][i] = 0 */
    924 SCIP_CALL( SCIPinferBinvarCons(scip, vars[k][i], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    925 if ( infeasible )
    926 {
    927 SCIPdebugMsg(scip, " -> node infeasible.\n");
    929 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    930 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    931 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    933 *result = SCIP_CUTOFF;
    934 return SCIP_OKAY;
    935 }
    936 if ( tightened )
    937 ++ngen;
    938 }
    939
    940 if ( SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
    941 {
    942 /* if x[k][i] == 1 and x[i][j] = 1 then x[j][k] = 0 */
    943 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][k], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    944 if ( infeasible )
    945 {
    946 SCIPdebugMsg(scip, " -> node infeasible.\n");
    948 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    949 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    950 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    952 *result = SCIP_CUTOFF;
    953 return SCIP_OKAY;
    954 }
    955 if ( tightened )
    956 ++ngen;
    957 }
    958 }
    959
    960 /* if x[j][k] == 1 and x[k][i] == 1 then x[i][j] = 0 */
    961 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 && SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
    962 {
    963 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    964 if ( infeasible )
    965 {
    966 SCIPdebugMsg(scip, " -> node infeasible.\n");
    968 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    969 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    970 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    972 *result = SCIP_CUTOFF;
    973 return SCIP_OKAY;
    974 }
    975 if ( tightened )
    976 ++ngen;
    977 }
    978
    979 /* all other implications occur with other indices i, j, k */
    980 }
    981 }
    982 }
    983 }
    984 SCIPdebugMsg(scip, "propagated %d domains.\n", ngen);
    985 if ( ngen > 0 )
    986 *result = SCIP_REDUCEDDOM;
    987
    988 return SCIP_OKAY;
    989}
    990
    991/** propagation conflict resolving method of constraint handler */
    992static
    994{ /*lint --e{715}*/
    995 SCIP_CONSDATA* consdata;
    996 SCIP_VAR*** vars;
    997 int n;
    998 int nsqrd;
    999
    1000 assert( scip != NULL );
    1001 assert( conshdlr != NULL );
    1002 assert( cons != NULL );
    1003 assert( infervar != NULL );
    1004 assert( bdchgidx != NULL );
    1005 assert( result != NULL );
    1006
    1008
    1009 SCIPdebugMsg(scip, "Propagation resolution of constraint <%s>.\n", SCIPconsGetName(cons));
    1010 *result = SCIP_DIDNOTFIND;
    1011
    1012 consdata = SCIPconsGetData(cons);
    1013 assert( consdata != NULL);
    1014 assert( consdata->vars != NULL );
    1015
    1016 n = consdata->n;
    1017 nsqrd = n * n;
    1018 vars = consdata->vars;
    1019
    1020 assert( 0 <= inferinfo && inferinfo < n*n + n*n*n );
    1021
    1022 /* if the conflict came from an equation */
    1023 if ( inferinfo < nsqrd )
    1024 {
    1025 int index1;
    1026 int index2;
    1027
    1028 index1 = inferinfo/n;
    1029 index2 = inferinfo % n;
    1030 assert( 0 <= index1 && index1 < n );
    1031 assert( 0 <= index2 && index2 < n );
    1032 assert( vars[index2][index1] == infervar );
    1033
    1034 /* if the variable was fixed to 0 */
    1035 if ( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 )
    1036 {
    1037 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = 1.\n", index2, index1, index1, index2);
    1038 /* the reason was that x[i][j] was fixed to 1 */
    1039 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1040 *result = SCIP_SUCCESS;
    1041 return SCIP_OKAY;
    1042 }
    1043
    1044 /* if the variable was fixed to 1 */
    1045 if ( SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE) < 0.5 && SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5 )
    1046 {
    1047 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 1 was x[%d][%d] = 0.\n", index2, index1, index1, index2);
    1048 /* the reason was that x[i][j] was fixed to 0 */
    1049 SCIP_CALL( SCIPaddConflictUb(scip, vars[index1][index2], bdchgidx) );
    1050 *result = SCIP_SUCCESS;
    1051 return SCIP_OKAY;
    1052 }
    1053 }
    1054 else
    1055 {
    1056 /* otherwise the conflict came from a triangle inequality */
    1057 int index1;
    1058 int index2;
    1059 int index3;
    1060
    1061 index1 = (inferinfo - nsqrd) / nsqrd;
    1062 index2 = (inferinfo - nsqrd - index1 * nsqrd) / n;
    1063 index3 = (inferinfo - nsqrd) % n;
    1064
    1065 assert( 0 <= index1 && index1 < n );
    1066 assert( 0 <= index2 && index2 < n );
    1067 assert( 0 <= index3 && index3 < n );
    1068 assert( index1 < index2 );
    1069 assert( index1 < index3 );
    1070 assert( index2 != index3 );
    1071
    1072 if ( vars[index3][index1] == infervar )
    1073 {
    1074 /* the variable should have been fixed to 0 */
    1075 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1076
    1077 /* the reason was that x[index1][index2] and x[index2][index3] were fixed to 1 */
    1078 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index3, index1, index1, index2, index2, index3);
    1079 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1080 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
    1081 *result = SCIP_SUCCESS;
    1082 }
    1083 else if ( vars[index2][index3] == infervar )
    1084 {
    1085 /* the variable should have been fixed to 0 */
    1086 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1087
    1088 /* the reason was that x[index1][index2] and x[index3][index1] were fixed to 1 */
    1089 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index2, index3, index1, index2, index3, index1);
    1090 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1091 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
    1092 *result = SCIP_SUCCESS;
    1093 }
    1094 else if ( vars[index1][index2] == infervar )
    1095 {
    1096 /* the variable should have been fixed to 0 */
    1097 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1098
    1099 /* the reason was that x[index2][index3] and x[index3][index1] were fixed to 1 */
    1100 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index1, index2, index2, index3, index3, index1);
    1101 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
    1102 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
    1103 *result = SCIP_SUCCESS;
    1104 }
    1105 else
    1106 {
    1107 /* should not happen */
    1108 SCIPABORT();
    1109 }
    1110 }
    1111
    1112 return SCIP_OKAY;
    1113}
    1114
    1115/** variable rounding lock method of constraint handler */
    1116static
    1118{ /*lint --e{715}*/
    1119 int i;
    1120 int j;
    1121 SCIP_CONSDATA* consdata;
    1122 SCIP_VAR*** vars;
    1123 int n;
    1124
    1125 assert( scip != NULL );
    1126 assert( conshdlr != NULL );
    1127 assert( cons != NULL );
    1128
    1130
    1131 SCIPdebugMsg(scip, "Locking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    1132
    1133 /* get data of constraint */
    1134 consdata = SCIPconsGetData(cons);
    1135 assert( consdata != NULL);
    1136 assert( consdata->vars != NULL );
    1137 n = consdata->n;
    1138 vars = consdata->vars;
    1139
    1140 for (i = 0; i < n; ++i)
    1141 {
    1142 for (j = 0; j < n; ++j)
    1143 {
    1144 if ( i != j )
    1145 {
    1146 /* the constraint may be violated in any way */
    1147 SCIP_CALL( SCIPaddVarLocksType(scip, vars[i][j], SCIP_LOCKTYPE_MODEL, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    1148 }
    1149 }
    1150 }
    1151
    1152 return SCIP_OKAY;
    1153}
    1154
    1155/** constraint display method of constraint handler */
    1156static
    1158{ /*lint --e{715}*/
    1159 SCIP_CONSDATA* consdata;
    1160 SCIP_VAR*** vars;
    1161 int i;
    1162 int j;
    1163 int n;
    1164
    1165 assert( scip != NULL );
    1166 assert( conshdlr != NULL );
    1167 assert( cons != NULL );
    1168
    1170
    1171 consdata = SCIPconsGetData(cons);
    1172 assert( consdata != NULL );
    1173 assert( consdata->vars != NULL );
    1174 n = consdata->n;
    1175 vars = consdata->vars;
    1176
    1177 SCIPinfoMessage(scip, file, "LOP[");
    1178 for (i = 0; i < n; ++i)
    1179 {
    1180 if ( i > 0 )
    1181 SCIPinfoMessage(scip, file, ", ");
    1182 SCIPinfoMessage(scip, file, "(");
    1183 for (j = 0; j < n; ++j)
    1184 {
    1185 if ( j != i )
    1186 {
    1187 if ( j > 0 && (i > 0 || j > 1) )
    1188 SCIPinfoMessage(scip, file, ",");
    1189 SCIPinfoMessage(scip, file, "%s", SCIPvarGetName(vars[i][j]));
    1190 }
    1191 }
    1192 SCIPinfoMessage(scip, file, ")");
    1193 }
    1194 SCIPinfoMessage(scip, file, "]\n");
    1195
    1196 return SCIP_OKAY;
    1197}
    1198
    1199/** constraint copying method of constraint handler */
    1200static
    1202{ /*lint --e{715}*/
    1203 SCIP_CONSDATA* sourcedata;
    1204 SCIP_VAR*** sourcevars;
    1205 SCIP_VAR*** vars;
    1206 int i;
    1207 int j;
    1208 int n;
    1209
    1210 assert( scip != NULL );
    1211 assert( sourceconshdlr != NULL );
    1212 assert( cons != NULL );
    1213 assert( sourcescip != NULL );
    1214 assert( sourcecons != NULL );
    1215 assert( varmap != NULL );
    1216 assert( valid != NULL );
    1217
    1219
    1220 *valid = TRUE;
    1221
    1222 SCIPdebugMsg(scip, "Copying method for linear ordering constraint handler.\n");
    1223
    1224 sourcedata = SCIPconsGetData(sourcecons);
    1225 assert( sourcedata != NULL );
    1226
    1227 n = sourcedata->n;
    1228 sourcevars = sourcedata->vars;
    1229 assert( sourcevars != NULL );
    1230
    1231 SCIP_CALL( SCIPallocBufferArray(scip, &vars, n) );
    1232 BMSclearMemoryArray(vars, n);
    1233
    1234 for (i = 0; i < n; ++i)
    1235 {
    1236 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), n) ); /*lint !e866*/
    1237
    1238 for (j = 0; j < n && *valid; ++j)
    1239 {
    1240 if ( i != j )
    1241 {
    1242 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &vars[i][j], varmap, consmap, global, valid) );
    1243 assert( !(*valid) || vars[i][j] != NULL );
    1244 }
    1245 }
    1246 }
    1247
    1248 if ( *valid )
    1249 {
    1250 /* create copied constraint */
    1251 if ( name == 0 )
    1252 name = SCIPconsGetName(sourcecons);
    1253
    1254 SCIP_CALL( SCIPcreateConsLOP(scip, cons, name, n, vars,
    1255 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    1256 }
    1257
    1258 /* free memory in reverse order */
    1259 for (i = n-1; i >= 0; --i)
    1260 SCIPfreeBufferArrayNull(scip, &vars[i]);
    1261 SCIPfreeBufferArray(scip, &vars);
    1262
    1263 return SCIP_OKAY;
    1264}
    1265
    1266/** creates the handler for linear ordering constraints and includes it in SCIP */
    1268 SCIP* scip /**< SCIP data structure */
    1269 )
    1270{
    1271 SCIP_CONSHDLR* conshdlr = NULL;
    1272
    1273 /* include constraint handler */
    1276 consEnfolpLOP, consEnfopsLOP, consCheckLOP, consLockLOP, NULL) );
    1277 assert( conshdlr != NULL );
    1278
    1279 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLOP) );
    1280 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLOP) );
    1281 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLOP, consCopyLOP) );
    1282 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLOP) );
    1283 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLOP) );
    1284 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLOP, consSepasolLOP,
    1286 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLOP, CONSHDLR_PROPFREQ,
    1288 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLOP) );
    1289 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLOP) );
    1290
    1291 return SCIP_OKAY;
    1292}
    1293
    1294/** creates and captures a linear ordering constraint */
    1296 SCIP* scip, /**< SCIP data structure */
    1297 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    1298 const char* name, /**< name of constraint */
    1299 int n, /**< number of elements */
    1300 SCIP_VAR*** vars, /**< n x n matrix of binary variables */
    1301 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
    1302 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
    1303 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
    1304 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
    1305 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
    1306 SCIP_Bool local, /**< is constraint only valid locally? */
    1307 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
    1308 SCIP_Bool dynamic, /**< is constraint subject to aging? */
    1309 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
    1310 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    1311 * if it may be moved to a more global node? */
    1312 )
    1313{
    1314 SCIP_CONSHDLR* conshdlr;
    1315 SCIP_CONSDATA* consdata;
    1316 int i;
    1317 int j;
    1318
    1319 /* find the linear ordering constraint handler */
    1320 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    1321 if (conshdlr == NULL)
    1322 {
    1323 SCIPerrorMessage("linear ordering constraint handler not found\n");
    1324 return SCIP_PLUGINNOTFOUND;
    1325 }
    1326
    1327 /* create constraint data */
    1328 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    1329
    1330 consdata->n = n;
    1331 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
    1332 for (i = 0; i < n; ++i)
    1333 {
    1334 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
    1335 for (j = 0; j < n; ++j)
    1336 {
    1337 if ( j != i )
    1338 {
    1339 assert( vars[i][j] != NULL );
    1340 consdata->vars[i][j] = vars[i][j];
    1341 }
    1342 }
    1343 }
    1344
    1345 /* create constraint */
    1346 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    1347 local, modifiable, dynamic, removable, stickingatnode) );
    1348
    1349 return SCIP_OKAY;
    1350}
    static SCIP_DECL_CONSRESPROP(consRespropLOP)
    Definition: cons_lop.c:993
    SCIP_RETCODE SCIPincludeConshdlrLOP(SCIP *scip)
    Definition: cons_lop.c:1267
    #define CONSHDLR_NEEDSCONS
    Definition: cons_lop.c:54
    #define CONSHDLR_SEPAFREQ
    Definition: cons_lop.c:48
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_lop.c:47
    static SCIP_DECL_CONSENFOPS(consEnfopsLOP)
    Definition: cons_lop.c:638
    #define CONSHDLR_DESC
    Definition: cons_lop.c:44
    #define CONSHDLR_PROP_TIMING
    Definition: cons_lop.c:56
    static SCIP_DECL_CONSENFOLP(consEnfolpLOP)
    Definition: cons_lop.c:510
    static SCIP_DECL_CONSEXIT(consExitLOP)
    Definition: cons_lop.c:214
    static SCIP_DECL_CONSINITLP(consInitlpLOP)
    Definition: cons_lop.c:355
    SCIP_RETCODE SCIPcreateConsLOP(SCIP *scip, SCIP_CONS **cons, const char *name, int n, 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_lop.c:1295
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_lop.c:45
    static SCIP_DECL_CONSPROP(consPropLOP)
    Definition: cons_lop.c:829
    static SCIP_DECL_CONSTRANS(consTransLOP)
    Definition: cons_lop.c:297
    static SCIP_DECL_CONSCOPY(consCopyLOP)
    Definition: cons_lop.c:1201
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLOP)
    Definition: cons_lop.c:166
    static SCIP_RETCODE LOPseparate(SCIP *scip, SCIP_CONSHDLR *conshdlr, int n, SCIP_VAR ***vars, SCIP_SOL *sol, int *ngen, SCIP_Bool *cutoff)
    Definition: cons_lop.c:69
    #define CONSHDLR_PROPFREQ
    Definition: cons_lop.c:49
    static SCIP_DECL_CONSSEPALP(consSepalpLOP)
    Definition: cons_lop.c:421
    #define CONSHDLR_EAGERFREQ
    Definition: cons_lop.c:50
    static SCIP_DECL_CONSPRINT(consPrintLOP)
    Definition: cons_lop.c:1157
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_lop.c:46
    #define CONSHDLR_DELAYSEPA
    Definition: cons_lop.c:52
    #define CONSHDLR_NAME
    Definition: cons_lop.c:43
    static SCIP_DECL_CONSSEPASOL(consSepasolLOP)
    Definition: cons_lop.c:466
    #define CONSHDLR_DELAYPROP
    Definition: cons_lop.c:53
    static SCIP_DECL_CONSCHECK(consCheckLOP)
    Definition: cons_lop.c:725
    static SCIP_DECL_CONSLOCK(consLockLOP)
    Definition: cons_lop.c:1117
    static SCIP_DECL_CONSDELETE(consDeleteLOP)
    Definition: cons_lop.c:184
    constraint handler for linear ordering constraints
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #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 TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIPABORT()
    Definition: def.h:336
    #define SCIP_CALL(x)
    Definition: def.h:364
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2589
    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 SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
    Definition: scip_cons.c:235
    SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
    Definition: scip_cons.c:281
    SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: scip_cons.c:181
    SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
    Definition: scip_cons.c:578
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4320
    SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
    Definition: scip_cons.c:420
    SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
    Definition: scip_cons.c:347
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
    Definition: scip_cons.c:601
    SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
    Definition: scip_cons.c:647
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, 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: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
    Definition: scip_cut.c:135
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #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 SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    SCIP_RETCODE SCIPcreateEmptyRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1367
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2872
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
    Definition: scip_var.c:2736
    SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:7412
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_FEASIBLE
    Definition: type_result.h:45
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141