Scippy

    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-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/* 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#include <assert.h>
    42#include <string.h>
    43
    44
    45/* constraint handler properties */
    46#define CONSHDLR_NAME "lop"
    47#define CONSHDLR_DESC "linear ordering constraint handler"
    48#define CONSHDLR_SEPAPRIORITY 100 /**< priority of the constraint handler for separation */
    49#define CONSHDLR_ENFOPRIORITY -100 /**< priority of the constraint handler for constraint enforcing */
    50#define CONSHDLR_CHECKPRIORITY -100 /**< priority of the constraint handler for checking feasibility */
    51#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
    52#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    53#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    54 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    55#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    56#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    57#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    58
    59#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    60
    61
    62/** constraint data for linear ordering constraints */
    63struct SCIP_ConsData
    64{
    65 int n; /**< number of elements */
    66 SCIP_VAR*** vars; /**< variables */
    67};
    68
    69
    70/** separate symmetry equations and triangle inequalities */
    71static
    73 SCIP* scip, /**< SCIP pointer */
    74 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    75 int n, /**< number of elements */
    76 SCIP_VAR*** vars, /**< n x n matrix of variables */
    77 SCIP_SOL* sol, /**< solution to be separated */
    78 int* ngen, /**< output: pointer to store number of added rows */
    79 SCIP_Bool* cutoff /**< output: pointer to store whether we detected a cutoff */
    80 )
    81{
    82 char s[SCIP_MAXSTRLEN];
    83 int i;
    84 int j;
    85 int k;
    86
    87 assert( scip != NULL );
    88 assert( vars != NULL );
    89 assert( ngen != NULL );
    90 assert( cutoff != NULL );
    91
    92 /* Consider all (i,j,k) with i < j, i < k, j != k; since the inequalities are symmetric under cyclic shifts, we can
    93 * assume i to be the smallest index. */
    94 *cutoff = FALSE;
    95 for (i = 0; i < n && ! (*cutoff); ++i)
    96 {
    97 for (j = i+1; j < n && ! (*cutoff); ++j)
    98 {
    99 SCIP_Real valIJ;
    100
    101 valIJ = SCIPgetSolVal(scip, sol, vars[i][j]);
    102
    103 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
    104 if ( ! SCIPisFeasEQ(scip, valIJ + SCIPgetSolVal(scip, sol, vars[j][i]), 1.0) )
    105 {
    106 SCIP_ROW *row;
    107
    108 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    109
    110 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
    112 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    113 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    115#ifdef SCIP_DEBUG
    117#endif
    118 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    120 ++(*ngen);
    121
    122 if ( *cutoff )
    123 break;
    124 }
    125
    126 /* check triangle inequalities */
    127 for (k = i+1; k < n; ++k)
    128 {
    129 SCIP_Real sum;
    130
    131 if ( k == j )
    132 continue;
    133
    134 sum = valIJ + SCIPgetSolVal(scip, sol, vars[j][k]) + SCIPgetSolVal(scip, sol, vars[k][i]);
    135
    136 /* if sum - 2.0 > 0, i.e., the cut is violated */
    137 if ( SCIPisEfficacious(scip, sum - 2.0) )
    138 {
    139 SCIP_ROW *row;
    140
    141 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
    142
    143 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
    145 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    146 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
    147 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
    149#ifdef SCIP_DEBUG
    151#endif
    152 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    154 ++(*ngen);
    155
    156 if ( *cutoff )
    157 break;
    158 }
    159 }
    160 }
    161 }
    162
    163 return SCIP_OKAY;
    164}
    165
    166
    167/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    168static
    170{ /*lint --e{715}*/
    171 assert( scip != NULL );
    172 assert( conshdlr != NULL );
    173 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    174 assert( valid != NULL );
    175
    176 /* call inclusion method of constraint handler */
    178
    179 *valid = TRUE;
    180
    181 return SCIP_OKAY;
    182}
    183
    184/** frees specific constraint data */
    185static
    187{ /*lint --e{715}*/
    188 int i;
    189 int n;
    190
    191 assert( scip != NULL );
    192 assert( conshdlr != NULL );
    193 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    194 assert( cons != NULL );
    195 assert( consdata != NULL);
    196 assert( *consdata != NULL);
    197 assert( (*consdata)->vars != NULL );
    198
    199 SCIPdebugMsg(scip, "deleting linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    200
    201 n = (*consdata)->n;
    202 for (i = 0; i < n; ++i)
    203 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars[i]), n); /*lint !e866*/
    204 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars), n);
    205 SCIPfreeBlockMemory(scip, consdata);
    206
    207 return SCIP_OKAY;
    208}
    209
    210/** deinitialization method of constraint handler (called before transformed problem is freed)
    211 *
    212 * We output the final linear ordering.
    213 */
    214static
    216{ /*lint --e{715}*/
    217 SCIP_SOL* sol;
    218 int c;
    219 int i;
    220 int j;
    221 int n;
    222
    223 assert( scip != NULL );
    224 assert( conshdlr != NULL );
    225 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    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( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    309 assert( sourcecons != NULL );
    310 assert( targetcons != NULL );
    311
    312 SCIPdebugMsg(scip, "transforming linear ordering constraint <%s>.\n", SCIPconsGetName(sourcecons) );
    313
    314 /* get data of original constraint */
    315 sourcedata = SCIPconsGetData(sourcecons);
    316 assert( sourcedata != NULL);
    317
    318 /* create constraint data */
    319 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    320
    321 n = sourcedata->n;
    322 consdata->n = n;
    323
    324 /* transform variables */
    325 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
    326 for (i = 0; i < n; ++i)
    327 {
    328 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
    329 for (j = 0; j < n; ++j)
    330 {
    331 if (j != i)
    332 {
    333 assert( sourcedata->vars[i][j] != NULL );
    334 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[i][j], &(consdata->vars[i][j])) );
    335 }
    336 }
    337 }
    338
    339 /* create constraint */
    340 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
    341
    342 SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
    343 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
    344 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
    345 SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
    346 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
    347 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    348
    349 return SCIP_OKAY;
    350}
    351
    352/** LP initialization method of constraint handler */
    353static
    355{ /*lint --e{715}*/
    356 char s[SCIP_MAXSTRLEN];
    357 int c;
    358 int ngen = 0;
    359
    360 assert( scip != NULL );
    361 assert( conshdlr != NULL );
    362 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    363 assert( infeasible != NULL );
    364
    365 *infeasible = FALSE;
    366
    367 /* loop through all constraints */
    368 for (c = 0; c < nconss; ++c)
    369 {
    370 SCIP_CONSDATA* consdata;
    371 SCIP_VAR*** vars;
    372 int i;
    373 int j;
    374 int n;
    375
    376 assert( conss != NULL );
    377 assert( conss[c] != NULL );
    378 SCIPdebugMsg(scip, "adding initial rows for linear ordering constraint <%s>.\n", SCIPconsGetName(conss[c]));
    379
    380 consdata = SCIPconsGetData(conss[c]);
    381 assert( consdata != NULL );
    382 assert( consdata->vars != NULL );
    383 n = consdata->n;
    384 vars = consdata->vars;
    385
    386 /* add symmetry equation */
    387 for (i = 0; i < n; ++i)
    388 {
    389 for (j = i+1; j < n; ++j)
    390 {
    391 SCIP_ROW* row;
    392
    393 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    394 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, FALSE) );
    396 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    397 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    399#ifdef SCIP_DEBUG
    401#endif
    402 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
    404 ++ngen;
    405
    406 /* cannot handle infeasible case here - just exit */
    407 if ( *infeasible )
    408 return SCIP_OKAY;
    409 }
    410 }
    411 }
    412 SCIPdebugMsg(scip, "added %d equations.\n", ngen);
    413
    414 return SCIP_OKAY;
    415}
    416
    417/** separation method of constraint handler for LP solutions */
    418static
    420{ /*lint --e{715}*/
    421 int ngen = 0;
    422 int c;
    423
    424 assert( scip != NULL );
    425 assert( conshdlr != NULL );
    426 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    427 assert( conss != NULL );
    428 assert( result != NULL );
    429
    430 *result = SCIP_DIDNOTRUN;
    431
    432 /* loop through all constraints */
    433 for (c = 0; c < nconss; ++c)
    434 {
    435 SCIP_CONSDATA* consdata;
    436 SCIP_CONS* cons;
    437 SCIP_Bool cutoff;
    438
    439 cons = conss[c];
    440 assert( cons != NULL );
    441 SCIPdebugMsg(scip, "separating LP solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    442
    443 consdata = SCIPconsGetData(cons);
    444 assert( consdata != NULL );
    445
    446 *result = SCIP_DIDNOTFIND;
    447 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, NULL, &ngen, &cutoff) );
    448 if ( cutoff )
    449 {
    450 *result = SCIP_CUTOFF;
    451 return SCIP_OKAY;
    452 }
    453 }
    454 if ( ngen > 0 )
    455 *result = SCIP_SEPARATED;
    456 SCIPdebugMsg(scip, "separated %d cuts.\n", ngen);
    457
    458 return SCIP_OKAY;
    459}
    460
    461/** separation method of constraint handler for arbitrary primal solutions */
    462static
    464{ /*lint --e{715}*/
    465 int ngen = 0;
    466 int c;
    467
    468 assert( scip != NULL );
    469 assert( conshdlr != NULL );
    470 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    471 assert( conss != NULL );
    472 assert( result != NULL );
    473
    474 *result = SCIP_DIDNOTRUN;
    475
    476 /* loop through all constraints */
    477 for (c = 0; c < nconss; ++c)
    478 {
    479 SCIP_CONSDATA* consdata;
    480 SCIP_CONS* cons;
    481 SCIP_Bool cutoff;
    482
    483 cons = conss[c];
    484 assert( cons != NULL );
    485 SCIPdebugMsg(scip, "separating solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    486
    487 consdata = SCIPconsGetData(cons);
    488 assert( consdata != NULL );
    489
    490 *result = SCIP_DIDNOTFIND;
    491 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, sol, &ngen, &cutoff) );
    492 if ( cutoff )
    493 {
    494 *result = SCIP_CUTOFF;
    495 return SCIP_OKAY;
    496 }
    497 }
    498 if ( ngen > 0 )
    499 *result = SCIP_SEPARATED;
    500
    501 return SCIP_OKAY;
    502}
    503
    504/** constraint enforcing method of constraint handler for LP solutions */
    505static
    507{ /*lint --e{715}*/
    508 char s[SCIP_MAXSTRLEN];
    509 int ngen = 0;
    510 int c;
    511
    512 assert( scip != NULL );
    513 assert( conshdlr != NULL );
    514 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    515 assert( conss != NULL );
    516 assert( result != NULL );
    517
    518 *result = SCIP_DIDNOTRUN;
    519
    520 /* loop through all constraints */
    521 for (c = 0; c < nconss; ++c)
    522 {
    523 SCIP_CONSDATA* consdata;
    524 SCIP_CONS* cons;
    525 SCIP_VAR*** vars;
    526 int i;
    527 int j;
    528 int k;
    529 int n;
    530
    531 cons = conss[c];
    532 assert( cons != NULL );
    533 SCIPdebugMsg(scip, "enforcing lp solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    534
    535 consdata = SCIPconsGetData(cons);
    536 assert( consdata != NULL );
    537
    538 n = consdata->n;
    539 vars = consdata->vars;
    540 assert( vars != NULL );
    541
    542 for (i = 0; i < n; ++i)
    543 {
    544 for (j = i + 1; j < n; ++j)
    545 {
    546 SCIP_Real valIJ;
    547
    548 valIJ = SCIPgetSolVal(scip, NULL, vars[i][j]);
    549
    550 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
    551 if ( ! SCIPisFeasEQ(scip, 1.0 - valIJ, SCIPgetSolVal(scip, NULL, vars[j][i])) )
    552 {
    553 SCIP_ROW *row;
    554 SCIP_Bool infeasible;
    555
    556 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
    557
    558 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
    560 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    561 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
    563#ifdef SCIP_DEBUG
    565#endif
    566 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    568 ++ngen;
    569
    570 if ( infeasible )
    571 {
    572 *result = SCIP_CUTOFF;
    573 return SCIP_OKAY;
    574 }
    575 }
    576
    577 /* enforce triangle inequalities */
    578 for (k = i + 1; k < n; ++k)
    579 {
    580 SCIP_Real sum;
    581
    582 if ( k == j )
    583 continue;
    584
    585 sum = valIJ + SCIPgetSolVal(scip, NULL, vars[j][k]) + SCIPgetSolVal(scip, NULL, vars[k][i]);
    586
    587 /* if sum > 2.0, i.e., the cut is violated */
    588 if ( SCIPisFeasGT(scip, sum, 2.0) ) /* this is the only difference to the separation call */
    589 {
    590 SCIP_ROW *row;
    591 SCIP_Bool infeasible;
    592
    593 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
    594
    595 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
    597 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
    598 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
    599 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
    601#ifdef SCIP_DEBUG
    603#endif
    604 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
    606 ++ngen;
    607
    608 if ( infeasible )
    609 {
    610 *result = SCIP_CUTOFF;
    611 return SCIP_OKAY;
    612 }
    613 }
    614 }
    615 }
    616 }
    617
    618 if ( ngen > 0 )
    619 {
    620 *result = SCIP_SEPARATED;
    621 return SCIP_OKAY;
    622 }
    623
    624 }
    625 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    626 *result = SCIP_FEASIBLE;
    627
    628 return SCIP_OKAY;
    629}
    630
    631/** constraint enforcing method of constraint handler for pseudo solutions */
    632static
    634{ /*lint --e{715}*/
    635 int c;
    636
    637 assert( scip != NULL );
    638 assert( conshdlr != NULL );
    639 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    640 assert( conss != NULL );
    641 assert( result != NULL );
    642
    643 /* loop through all constraints */
    644 for (c = 0; c < nconss; ++c)
    645 {
    646 SCIP_CONSDATA* consdata;
    647 SCIP_CONS* cons;
    648 SCIP_VAR*** vars;
    649 int i;
    650 int j;
    651 int k;
    652 int n;
    653
    654 cons = conss[c];
    655 assert( cons != NULL );
    656 SCIPdebugMsg(scip, "enforcing pseudo solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    657
    658 consdata = SCIPconsGetData(cons);
    659 assert( consdata != NULL );
    660 assert( consdata->vars != NULL );
    661 vars = consdata->vars;
    662 n = consdata->n;
    663
    664 /* check triangle inequalities */
    665 for (i = 0; i < n; ++i)
    666 {
    667 for (j = i + 1; j < n; ++j)
    668 {
    669 SCIP_Bool oneIJ;
    670 SCIP_Bool oneJI;
    671
    672 /* the priorities should ensure that the solution is integral */
    673 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[i][j])) );
    674 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][i])) );
    675
    676 oneIJ = SCIPgetSolVal(scip, NULL, vars[i][j]) > 0.5 ? TRUE : FALSE;
    677 oneJI = SCIPgetSolVal(scip, NULL, vars[j][i]) > 0.5 ? TRUE : FALSE;
    678
    679 if ( oneIJ == oneJI )
    680 {
    681 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
    682 *result = SCIP_INFEASIBLE;
    683 return SCIP_OKAY;
    684 }
    685
    686 for (k = i + 1; k < n; ++k)
    687 {
    688 SCIP_Bool oneJK;
    689 SCIP_Bool oneKI;
    690
    691 if ( k == j )
    692 continue;
    693
    694 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][k])) );
    695 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[k][i])) );
    696
    697 oneJK = SCIPgetSolVal(scip, NULL, vars[j][k]) > 0.5 ? TRUE : FALSE;
    698 oneKI = SCIPgetSolVal(scip, NULL, vars[k][i]) > 0.5 ? TRUE : FALSE;
    699
    700 /* if triangle inequality is violated */
    701 if ( oneIJ && oneJK && oneKI )
    702 {
    703 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
    704 *result = SCIP_INFEASIBLE;
    705 return SCIP_OKAY;
    706 }
    707 }
    708 }
    709 }
    710 }
    711 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    712 *result = SCIP_FEASIBLE;
    713
    714 return SCIP_OKAY;
    715}
    716
    717/** feasibility check method of constraint handler for integral solutions */
    718static
    720{ /*lint --e{715}*/
    721 int c;
    722
    723 assert( scip != NULL );
    724 assert( conshdlr != NULL );
    725 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    726 assert( conss != NULL );
    727 assert( result != NULL );
    728
    729 /* loop through all constraints */
    730 for (c = 0; c < nconss; ++c)
    731 {
    732 SCIP_CONSDATA* consdata;
    733 SCIP_CONS* cons;
    734 SCIP_VAR*** vars;
    735 int i;
    736 int j;
    737 int k;
    738 int n;
    739
    740 cons = conss[c];
    741 assert( cons != NULL );
    742 SCIPdebugMsg(scip, "checking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    743
    744 consdata = SCIPconsGetData(cons);
    745 assert( consdata != NULL );
    746 assert( consdata->vars != NULL );
    747 vars = consdata->vars;
    748 n = consdata->n;
    749
    750 /* check triangle inequalities and symmetry equations */
    751 for (i = 0; i < n; ++i)
    752 {
    753 for (j = i + 1; j < n; ++j)
    754 {
    755 SCIP_Bool oneIJ;
    756 SCIP_Bool oneJI;
    757
    758 /* the priorities should ensure that the solution is integral */
    759 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[i][j])) );
    760 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][i])) );
    761
    762 oneIJ = SCIPgetSolVal(scip, sol, vars[i][j]) > 0.5 ? TRUE : FALSE;
    763 oneJI = SCIPgetSolVal(scip, sol, vars[j][i]) > 0.5 ? TRUE : FALSE;
    764
    765 /* check symmetry equations */
    766 if ( oneIJ == oneJI )
    767 {
    768 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
    769 *result = SCIP_INFEASIBLE;
    770 if( printreason )
    771 {
    772 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    773 SCIPinfoMessage(scip, NULL, "violation: symmetry equation violated <%s> = %.15g and <%s> = %.15g\n",
    774 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
    775 SCIPvarGetName(vars[j][i]), SCIPgetSolVal(scip, sol, vars[j][i]));
    776 }
    777 return SCIP_OKAY;
    778 }
    779
    780 for (k = i + 1; k < n; ++k)
    781 {
    782 SCIP_Bool oneJK;
    783 SCIP_Bool oneKI;
    784
    785 if ( k == j )
    786 continue;
    787
    788 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][k])) );
    789 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[k][i])) );
    790
    791 oneJK = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[j][k]), 0.5);
    792 oneKI = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[k][i]), 0.5);
    793
    794 /* if triangle inequality is violated */
    795 if ( oneIJ && oneJK && oneKI )
    796 {
    797 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
    798 *result = SCIP_INFEASIBLE;
    799 if( printreason )
    800 {
    801 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
    803 "violation: triangle inequality violated <%s> = %.15g, <%s> = %.15g, <%s> = %.15g\n",
    804 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
    805 SCIPvarGetName(vars[j][k]), SCIPgetSolVal(scip, sol, vars[j][k]),
    806 SCIPvarGetName(vars[k][i]), SCIPgetSolVal(scip, sol, vars[k][i]));
    807 }
    808 return SCIP_OKAY;
    809 }
    810 }
    811 }
    812 }
    813 }
    814 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
    815 *result = SCIP_FEASIBLE;
    816
    817 return SCIP_OKAY;
    818}
    819
    820/** domain propagation method of constraint handler */
    821static
    823{ /*lint --e{715}*/
    824 int c;
    825 int ngen = 0;
    826
    827 assert( scip != NULL );
    828 assert( conshdlr != NULL );
    829 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    830 assert( conss != NULL );
    831 assert( result != NULL );
    832
    833 *result = SCIP_DIDNOTRUN;
    834
    835 /* loop through all constraints */
    836 for (c = 0; c < nconss; ++c)
    837 {
    838 SCIP_CONSDATA* consdata;
    839 SCIP_CONS* cons;
    840 SCIP_VAR*** vars;
    841 int i;
    842 int j;
    843 int k;
    844 int n;
    845
    846 cons = conss[c];
    847 assert( cons != NULL );
    848 SCIPdebugMsg(scip, "propagating linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    849
    850 *result = SCIP_DIDNOTFIND;
    851
    852 consdata = SCIPconsGetData(cons);
    853 assert( consdata != NULL );
    854 assert( consdata->vars != NULL );
    855
    856 vars = consdata->vars;
    857 n = consdata->n;
    858
    859 /* check triangle inequalities */
    860 for (i = 0; i < n; ++i)
    861 {
    862 for (j = i + 1; j < n; ++j)
    863 {
    864 SCIP_Bool infeasible;
    865 SCIP_Bool tightened;
    866
    867 /* for consistency make sure that the complementarity constraints are satisfied */
    868
    869 /* if x[i][j] == 1 then x[j][i] = 0 */
    870 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
    871 {
    872 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], FALSE, cons, i*n + j, &infeasible, &tightened) );
    873 if ( infeasible )
    874 {
    875 SCIPdebugMsg(scip, " -> node infeasible.\n");
    877 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    878 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
    880 *result = SCIP_CUTOFF;
    881 return SCIP_OKAY;
    882 }
    883 if ( tightened )
    884 ++ngen;
    885 }
    886
    887 /* if x[i][j] == 0 then x[j][i] = 1 */
    888 if ( SCIPvarGetUbLocal(vars[i][j]) < 0.5 )
    889 {
    890 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], TRUE, cons, i*n + j, &infeasible, &tightened) );
    891 if ( infeasible )
    892 {
    893 SCIPdebugMsg(scip, " -> node infeasible.\n");
    895 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    896 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
    898 *result = SCIP_CUTOFF;
    899 return SCIP_OKAY;
    900 }
    901 if ( tightened )
    902 ++ngen;
    903 }
    904
    905 /* check whether triangle inequality allows to fix variables */
    906 for (k = i + 1; k < n; ++k)
    907 {
    908 if ( k == j )
    909 continue;
    910
    911 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
    912 {
    913 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 )
    914 {
    915 /* if x[i][j] == 1 and x[j][k] == 1 then x[k][i] = 0 */
    916 SCIP_CALL( SCIPinferBinvarCons(scip, vars[k][i], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    917 if ( infeasible )
    918 {
    919 SCIPdebugMsg(scip, " -> node infeasible.\n");
    921 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    922 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    923 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    925 *result = SCIP_CUTOFF;
    926 return SCIP_OKAY;
    927 }
    928 if ( tightened )
    929 ++ngen;
    930 }
    931
    932 if ( SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
    933 {
    934 /* if x[k][i] == 1 and x[i][j] = 1 then x[j][k] = 0 */
    935 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][k], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    936 if ( infeasible )
    937 {
    938 SCIPdebugMsg(scip, " -> node infeasible.\n");
    940 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    941 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    942 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    944 *result = SCIP_CUTOFF;
    945 return SCIP_OKAY;
    946 }
    947 if ( tightened )
    948 ++ngen;
    949 }
    950 }
    951
    952 /* if x[j][k] == 1 and x[k][i] == 1 then x[i][j] = 0 */
    953 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 && SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
    954 {
    955 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
    956 if ( infeasible )
    957 {
    958 SCIPdebugMsg(scip, " -> node infeasible.\n");
    960 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    961 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
    962 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
    964 *result = SCIP_CUTOFF;
    965 return SCIP_OKAY;
    966 }
    967 if ( tightened )
    968 ++ngen;
    969 }
    970
    971 /* all other implications occur with other indices i, j, k */
    972 }
    973 }
    974 }
    975 }
    976 SCIPdebugMsg(scip, "propagated %d domains.\n", ngen);
    977 if ( ngen > 0 )
    978 *result = SCIP_REDUCEDDOM;
    979
    980 return SCIP_OKAY;
    981}
    982
    983/** propagation conflict resolving method of constraint handler */
    984static
    986{ /*lint --e{715}*/
    987 SCIP_CONSDATA* consdata;
    988 SCIP_VAR*** vars;
    989 int n;
    990 int nsqrd;
    991
    992 assert( scip != NULL );
    993 assert( conshdlr != NULL );
    994 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    995 assert( cons != NULL );
    996 assert( infervar != NULL );
    997 assert( bdchgidx != NULL );
    998 assert( result != NULL );
    999
    1000 SCIPdebugMsg(scip, "Propagation resolution of constraint <%s>.\n", SCIPconsGetName(cons));
    1001 *result = SCIP_DIDNOTFIND;
    1002
    1003 consdata = SCIPconsGetData(cons);
    1004 assert( consdata != NULL);
    1005 assert( consdata->vars != NULL );
    1006
    1007 n = consdata->n;
    1008 nsqrd = n * n;
    1009 vars = consdata->vars;
    1010
    1011 assert( 0 <= inferinfo && inferinfo < n*n + n*n*n );
    1012
    1013 /* if the conflict came from an equation */
    1014 if ( inferinfo < nsqrd )
    1015 {
    1016 int index1;
    1017 int index2;
    1018
    1019 index1 = inferinfo/n;
    1020 index2 = inferinfo % n;
    1021 assert( 0 <= index1 && index1 < n );
    1022 assert( 0 <= index2 && index2 < n );
    1023 assert( vars[index2][index1] == infervar );
    1024
    1025 /* if the variable was fixed to 0 */
    1026 if ( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 )
    1027 {
    1028 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = 1.\n", index2, index1, index1, index2);
    1029 /* the reason was that x[i][j] was fixed to 1 */
    1030 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1031 *result = SCIP_SUCCESS;
    1032 return SCIP_OKAY;
    1033 }
    1034
    1035 /* if the variable was fixed to 1 */
    1036 if ( SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE) < 0.5 && SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5 )
    1037 {
    1038 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 1 was x[%d][%d] = 0.\n", index2, index1, index1, index2);
    1039 /* the reason was that x[i][j] was fixed to 0 */
    1040 SCIP_CALL( SCIPaddConflictUb(scip, vars[index1][index2], bdchgidx) );
    1041 *result = SCIP_SUCCESS;
    1042 return SCIP_OKAY;
    1043 }
    1044 }
    1045 else
    1046 {
    1047 /* otherwise the conflict came from a triangle inequality */
    1048 int index1;
    1049 int index2;
    1050 int index3;
    1051
    1052 index1 = (inferinfo - nsqrd) / nsqrd;
    1053 index2 = (inferinfo - nsqrd - index1 * nsqrd) / n;
    1054 index3 = (inferinfo - nsqrd) % n;
    1055
    1056 assert( 0 <= index1 && index1 < n );
    1057 assert( 0 <= index2 && index2 < n );
    1058 assert( 0 <= index3 && index3 < n );
    1059 assert( index1 < index2 );
    1060 assert( index1 < index3 );
    1061 assert( index2 != index3 );
    1062
    1063 if ( vars[index3][index1] == infervar )
    1064 {
    1065 /* the variable should have been fixed to 0 */
    1066 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1067
    1068 /* the reason was that x[index1][index2] and x[index2][index3] were fixed to 1 */
    1069 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index3, index1, index1, index2, index2, index3);
    1070 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1071 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
    1072 *result = SCIP_SUCCESS;
    1073 }
    1074 else if ( vars[index2][index3] == infervar )
    1075 {
    1076 /* the variable should have been fixed to 0 */
    1077 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1078
    1079 /* the reason was that x[index1][index2] and x[index3][index1] were fixed to 1 */
    1080 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index2, index3, index1, index2, index3, index1);
    1081 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
    1082 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
    1083 *result = SCIP_SUCCESS;
    1084 }
    1085 else if ( vars[index1][index2] == infervar )
    1086 {
    1087 /* the variable should have been fixed to 0 */
    1088 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
    1089
    1090 /* the reason was that x[index2][index3] and x[index3][index1] were fixed to 1 */
    1091 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index1, index2, index2, index3, index3, index1);
    1092 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
    1093 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
    1094 *result = SCIP_SUCCESS;
    1095 }
    1096 else
    1097 {
    1098 /* should not happen */
    1099 SCIPABORT();
    1100 }
    1101 }
    1102
    1103 return SCIP_OKAY;
    1104}
    1105
    1106/** variable rounding lock method of constraint handler */
    1107static
    1109{ /*lint --e{715}*/
    1110 int i;
    1111 int j;
    1112 SCIP_CONSDATA* consdata;
    1113 SCIP_VAR*** vars;
    1114 int n;
    1115
    1116 assert( scip != NULL );
    1117 assert( conshdlr != NULL );
    1118 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    1119 assert( cons != NULL );
    1120
    1121 SCIPdebugMsg(scip, "Locking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
    1122
    1123 /* get data of constraint */
    1124 consdata = SCIPconsGetData(cons);
    1125 assert( consdata != NULL);
    1126 assert( consdata->vars != NULL );
    1127 n = consdata->n;
    1128 vars = consdata->vars;
    1129
    1130 for (i = 0; i < n; ++i)
    1131 {
    1132 for (j = 0; j < n; ++j)
    1133 {
    1134 if ( i != j )
    1135 {
    1136 /* the constraint may be violated in any way */
    1137 SCIP_CALL( SCIPaddVarLocksType(scip, vars[i][j], SCIP_LOCKTYPE_MODEL, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    1138 }
    1139 }
    1140 }
    1141
    1142 return SCIP_OKAY;
    1143}
    1144
    1145/** constraint display method of constraint handler */
    1146static
    1148{ /*lint --e{715}*/
    1149 SCIP_CONSDATA* consdata;
    1150 SCIP_VAR*** vars;
    1151 int i;
    1152 int j;
    1153 int n;
    1154
    1155 assert( scip != NULL );
    1156 assert( conshdlr != NULL );
    1157 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    1158 assert( cons != NULL );
    1159
    1160 consdata = SCIPconsGetData(cons);
    1161 assert( consdata != NULL );
    1162 assert( consdata->vars != NULL );
    1163 n = consdata->n;
    1164 vars = consdata->vars;
    1165
    1166 SCIPinfoMessage(scip, file, "LOP[");
    1167 for (i = 0; i < n; ++i)
    1168 {
    1169 if ( i > 0 )
    1170 SCIPinfoMessage(scip, file, ", ");
    1171 SCIPinfoMessage(scip, file, "(");
    1172 for (j = 0; j < n; ++j)
    1173 {
    1174 if ( j != i )
    1175 {
    1176 if ( j > 0 && (i > 0 || j > 1) )
    1177 SCIPinfoMessage(scip, file, ",");
    1178 SCIPinfoMessage(scip, file, "%s", SCIPvarGetName(vars[i][j]));
    1179 }
    1180 }
    1181 SCIPinfoMessage(scip, file, ")");
    1182 }
    1183 SCIPinfoMessage(scip, file, "]\n");
    1184
    1185 return SCIP_OKAY;
    1186}
    1187
    1188/** constraint copying method of constraint handler */
    1189static
    1191{ /*lint --e{715}*/
    1192 SCIP_CONSDATA* sourcedata;
    1193 SCIP_VAR*** sourcevars;
    1194 SCIP_VAR*** vars;
    1195 int i;
    1196 int j;
    1197 int n;
    1198
    1199 assert( scip != NULL );
    1200 assert( sourceconshdlr != NULL );
    1201 assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
    1202 assert( cons != NULL );
    1203 assert( sourcescip != NULL );
    1204 assert( sourcecons != NULL );
    1205 assert( varmap != NULL );
    1206 assert( valid != NULL );
    1207
    1208 *valid = TRUE;
    1209
    1210 SCIPdebugMsg(scip, "Copying method for linear ordering constraint handler.\n");
    1211
    1212 sourcedata = SCIPconsGetData(sourcecons);
    1213 assert( sourcedata != NULL );
    1214
    1215 n = sourcedata->n;
    1216 sourcevars = sourcedata->vars;
    1217 assert( sourcevars != NULL );
    1218
    1219 SCIP_CALL( SCIPallocBufferArray(scip, &vars, n) );
    1220 BMSclearMemoryArray(vars, n);
    1221
    1222 for (i = 0; i < n; ++i)
    1223 {
    1224 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), n) ); /*lint !e866*/
    1225
    1226 for (j = 0; j < n && *valid; ++j)
    1227 {
    1228 if ( i != j )
    1229 {
    1230 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &vars[i][j], varmap, consmap, global, valid) );
    1231 assert( !(*valid) || vars[i][j] != NULL );
    1232 }
    1233 }
    1234 }
    1235
    1236 if ( *valid )
    1237 {
    1238 /* create copied constraint */
    1239 if ( name == 0 )
    1240 name = SCIPconsGetName(sourcecons);
    1241
    1242 SCIP_CALL( SCIPcreateConsLOP(scip, cons, name, n, vars,
    1243 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    1244 }
    1245
    1246 /* free memory in reverse order */
    1247 for (i = n-1; i >= 0; --i)
    1248 SCIPfreeBufferArrayNull(scip, &vars[i]);
    1249 SCIPfreeBufferArray(scip, &vars);
    1250
    1251 return SCIP_OKAY;
    1252}
    1253
    1254/** creates the handler for linear ordering constraints and includes it in SCIP */
    1256 SCIP* scip /**< SCIP data structure */
    1257 )
    1258{
    1259 SCIP_CONSHDLR* conshdlr = NULL;
    1260
    1261 /* include constraint handler */
    1264 consEnfolpLOP, consEnfopsLOP, consCheckLOP, consLockLOP, NULL) );
    1265 assert( conshdlr != NULL );
    1266
    1267 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLOP) );
    1268 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLOP) );
    1269 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLOP, consCopyLOP) );
    1270 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLOP) );
    1271 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLOP) );
    1272 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLOP, consSepasolLOP,
    1274 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLOP, CONSHDLR_PROPFREQ,
    1276 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLOP) );
    1277 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLOP) );
    1278
    1279 return SCIP_OKAY;
    1280}
    1281
    1282/** creates and captures a linear ordering constraint */
    1284 SCIP* scip, /**< SCIP data structure */
    1285 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    1286 const char* name, /**< name of constraint */
    1287 int n, /**< number of elements */
    1288 SCIP_VAR*** vars, /**< n x n matrix of binary variables */
    1289 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
    1290 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
    1291 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
    1292 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
    1293 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
    1294 SCIP_Bool local, /**< is constraint only valid locally? */
    1295 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
    1296 SCIP_Bool dynamic, /**< is constraint subject to aging? */
    1297 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
    1298 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    1299 * if it may be moved to a more global node? */
    1300 )
    1301{
    1302 SCIP_CONSHDLR* conshdlr;
    1303 SCIP_CONSDATA* consdata;
    1304 int i;
    1305 int j;
    1306
    1307 /* find the linear ordering constraint handler */
    1308 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    1309 if (conshdlr == NULL)
    1310 {
    1311 SCIPerrorMessage("linear ordering constraint handler not found\n");
    1312 return SCIP_PLUGINNOTFOUND;
    1313 }
    1314
    1315 /* create constraint data */
    1316 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
    1317
    1318 consdata->n = n;
    1319 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
    1320 for (i = 0; i < n; ++i)
    1321 {
    1322 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
    1323 for (j = 0; j < n; ++j)
    1324 {
    1325 if ( j != i )
    1326 {
    1327 assert( vars[i][j] != NULL );
    1328 consdata->vars[i][j] = vars[i][j];
    1329 }
    1330 }
    1331 }
    1332
    1333 /* create constraint */
    1334 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    1335 local, modifiable, dynamic, removable, stickingatnode) );
    1336
    1337 return SCIP_OKAY;
    1338}
    static SCIP_DECL_CONSRESPROP(consRespropLOP)
    Definition: cons_lop.c:985
    SCIP_RETCODE SCIPincludeConshdlrLOP(SCIP *scip)
    Definition: cons_lop.c:1255
    #define CONSHDLR_NEEDSCONS
    Definition: cons_lop.c:57
    #define CONSHDLR_SEPAFREQ
    Definition: cons_lop.c:51
    #define CONSHDLR_CHECKPRIORITY
    Definition: cons_lop.c:50
    static SCIP_DECL_CONSENFOPS(consEnfopsLOP)
    Definition: cons_lop.c:633
    #define CONSHDLR_DESC
    Definition: cons_lop.c:47
    #define CONSHDLR_PROP_TIMING
    Definition: cons_lop.c:59
    static SCIP_DECL_CONSENFOLP(consEnfolpLOP)
    Definition: cons_lop.c:506
    static SCIP_DECL_CONSEXIT(consExitLOP)
    Definition: cons_lop.c:215
    static SCIP_DECL_CONSINITLP(consInitlpLOP)
    Definition: cons_lop.c:354
    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:1283
    #define CONSHDLR_SEPAPRIORITY
    Definition: cons_lop.c:48
    static SCIP_DECL_CONSPROP(consPropLOP)
    Definition: cons_lop.c:822
    static SCIP_DECL_CONSTRANS(consTransLOP)
    Definition: cons_lop.c:297
    static SCIP_DECL_CONSCOPY(consCopyLOP)
    Definition: cons_lop.c:1190
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLOP)
    Definition: cons_lop.c:169
    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:72
    #define CONSHDLR_PROPFREQ
    Definition: cons_lop.c:52
    static SCIP_DECL_CONSSEPALP(consSepalpLOP)
    Definition: cons_lop.c:419
    #define CONSHDLR_EAGERFREQ
    Definition: cons_lop.c:53
    static SCIP_DECL_CONSPRINT(consPrintLOP)
    Definition: cons_lop.c:1147
    #define CONSHDLR_ENFOPRIORITY
    Definition: cons_lop.c:49
    #define CONSHDLR_DELAYSEPA
    Definition: cons_lop.c:55
    #define CONSHDLR_NAME
    Definition: cons_lop.c:46
    static SCIP_DECL_CONSSEPASOL(consSepasolLOP)
    Definition: cons_lop.c:463
    #define CONSHDLR_DELAYPROP
    Definition: cons_lop.c:56
    static SCIP_DECL_CONSCHECK(consCheckLOP)
    Definition: cons_lop.c:719
    static SCIP_DECL_CONSLOCK(consLockLOP)
    Definition: cons_lop.c:1108
    static SCIP_DECL_CONSDELETE(consDeleteLOP)
    Definition: cons_lop.c:186
    constraint handler for linear ordering constraints
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    int SCIPgetSubscipDepth(SCIP *scip)
    Definition: scip_copy.c:2588
    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:4316
    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:8419
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8648
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8558
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    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:8608
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8628
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8389
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8638
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8668
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8568
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8658
    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:2981
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    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:24268
    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:23267
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    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:1221
    @ 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
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141