Scippy

    SCIP

    Solving Constraint Integer Programs

    cons_orbitope_pp.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_orbitope_pp.c
    26 * @ingroup DEFPLUGINS_CONS
    27 * @brief constraint handler for partitioning/packing orbitope constraints w.r.t. the full symmetric group
    28 * @author Timo Berthold
    29 * @author Marc Pfetsch
    30 * @author Christopher Hojny
    31 *
    32 * The type of constraints of this constraint handler is described in cons_orbitope_pp.h.
    33 * When creating the constraint, users can decide whether it is a constraint defining the model
    34 * or "just" use to handle symmetries. In the latter case, symmetry reductions are only performed
    35 * by the constraint handler if strong dual reductions are permitted.
    36 *
    37 * The details of the method implemented here are described in the following papers.
    38 *
    39 * Packing and Partitioning Orbitopes@n
    40 * Volker Kaibel and Marc E. Pfetsch,@n
    41 * Math. Program. 114, No. 1, 1-36 (2008)
    42 *
    43 * Among other things, this paper describes so-called shifted column inequalities of the following
    44 * form \f$x(S) \leq x(B)\f$, where \f$S\f$ is a so-called shifted column and \f$B\f$ is a so-called
    45 * bar. These inequalities can be used to handle symmetry and they are separated in this constraint
    46 * handler. We use the linear time separation algorithm of the paper.@par
    47 *
    48 * Orbitopal Fixing@n
    49 * Volker Kaibel, Matthias Peinhardt, and Marc E. Pfetsch,@n
    50 * Discrete Optimization 8, No. 4, 595-610 (2011)
    51 * (A preliminary version appears in Proc. IPCO 2007.)
    52 *
    53 * In this paper a linear time propagation algorithm is described, a variant of which is implemented
    54 * here. The implemented variant does not run in linear time, but is very fast in practice.
    55 *
    56 * <table>
    57 * <caption>translation table</caption>
    58 * <tr><td>here</td><td>paper</td></tr>
    59 * <tr><td></td><td></td></tr>
    60 * <tr><td>nrows </td><td>p </td></tr>
    61 * <tr><td>ncols </td><td>q </td></tr>
    62 * <tr><td>vars </td><td>x </td></tr>
    63 * <tr><td>vals </td><td>A^\\star</td></tr>
    64 * <tr><td>weights </td><td>\\omega </td></tr>
    65 * <tr><td>cases </td><td>\\tau </td></tr>
    66 * <tr><td>fixtriangle </td><td>-- </td></tr>
    67 * <tr><td>resolveprop </td><td>-- </td></tr>
    68 * <tr><td>firstnonzeros</td><td>\\mu </td></tr>
    69 * <tr><td>lastones </td><td>\\alpha </td></tr>
    70 * <tr><td>frontiersteps</td><td>\\Gamma </td></tr>
    71 * </table>
    72 *
    73 */
    74
    75/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    76
    79#include "scip/cons_setppc.h"
    80#include "scip/pub_cons.h"
    81#include "scip/pub_message.h"
    82#include "scip/pub_var.h"
    83#include "scip/scip.h"
    84#include "scip/scip_branch.h"
    85#include "scip/scip_conflict.h"
    86#include "scip/scip_cons.h"
    87#include "scip/scip_copy.h"
    88#include "scip/scip_cut.h"
    89#include "scip/scip_general.h"
    90#include "scip/scip_lp.h"
    91#include "scip/scip_mem.h"
    92#include "scip/scip_message.h"
    93#include "scip/scip_numerics.h"
    94#include "scip/scip_param.h"
    95#include "scip/scip_prob.h"
    96#include "scip/scip_probing.h"
    97#include "scip/scip_sol.h"
    98#include "scip/scip_var.h"
    99#include "scip/symmetry.h"
    101
    102/* constraint handler properties */
    103#define CONSHDLR_NAME "orbitope_pp"
    104#define CONSHDLR_DESC "symmetry breaking constraint handler relying on partitioning/packing orbitopes"
    105#define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
    106#define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
    107#define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
    108#define CONSHDLR_SEPAFREQ -1 /**< frequency for separating cuts; zero means to separate only in the root node */
    109#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    110#define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
    111 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    112#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    113#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    114#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    115#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    116
    117#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
    118#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
    119
    120#define DEFAULT_FORCECONSCOPY FALSE /**< whether orbitope constraints should be forced to be copied to sub SCIPs */
    121
    122/*
    123 * Data structures
    124 */
    125
    126/** constraint handler data */
    127struct SCIP_ConshdlrData
    128{
    129 SCIP_Bool forceconscopy; /**< whether orbitope constraints should be forced to be copied to sub SCIPs */
    130};
    131
    132/** constraint data for orbitope constraints */
    133struct SCIP_ConsData
    134{
    135 SCIP_VAR*** vars; /**< matrix of variables on which the symmetry acts */
    136 SCIP_VAR** tmpvars; /**< temporary storage for variables */
    137 SCIP_Real** vals; /**< LP-solution for those variables */
    138 SCIP_Real* tmpvals; /**< temporary storage for values */
    139 SCIP_Real** weights; /**< SC weight table */
    140 int** cases; /**< indicator of the SC cases */
    141 int nrows; /**< number of rows in orbitope matrix <=> p */
    142 int ncols; /**< number of columns in orbitope matrix <=> q */
    143 SCIP_ORBITOPETYPE orbitopetype; /**< type of orbitope constraint */
    144 SCIP_Bool resolveprop; /**< should propagation be resolved? */
    145 SCIP_Bool istrianglefixed; /**< has the upper right triangle already globally been fixed to zero? */
    146 SCIP_Bool ismodelcons; /**< whether the orbitope is a model constraint */
    147};
    148
    149
    150/*
    151 * Local methods
    152 */
    153
    154/** frees an orbitope constraint data */
    155static
    157 SCIP* scip, /**< SCIP data structure */
    158 SCIP_CONSDATA** consdata /**< pointer to orbitope constraint data */
    159 )
    160{
    161 int i;
    162 int j;
    163 int nrows;
    164 int ncols;
    165
    166 assert( consdata != NULL );
    167 assert( *consdata != NULL );
    168
    169 nrows = (*consdata)->nrows;
    170 ncols = (*consdata)->ncols;
    171 for (i = 0; i < nrows; ++i)
    172 {
    173 /* release variables in vars array */
    174 for (j = 0; j < ncols; ++j)
    175 {
    176 assert( (*consdata)->vars[i] != NULL );
    177 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vars[i][j]) );
    178 }
    179
    180 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cases[i]), ncols); /*lint !e866*/
    181 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars[i]), ncols); /*lint !e866*/
    182 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->weights[i]), ncols); /*lint !e866*/
    183 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vals[i]), ncols); /*lint !e866*/
    184 }
    185
    186 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cases), nrows);
    187 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars), nrows);
    188 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->weights), nrows);
    189 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vals), nrows);
    190
    191 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->tmpvals), nrows + ncols);
    192 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->tmpvars), nrows + ncols);
    193
    194 SCIPfreeBlockMemory(scip, consdata);
    195
    196 return SCIP_OKAY;
    197}
    198
    199
    200/** creates orbitope constraint data */
    201static
    203 SCIP* scip, /**< SCIP data structure */
    204 SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
    205 SCIP_VAR*** vars, /**< variables array, must have size nspcons x nblocks */
    206 int nrows, /**< number of rows in orbitope matrix <=> p */
    207 int ncols, /**< number of columns in orbitope matrix <=> q */
    208 SCIP_ORBITOPETYPE orbitopetype, /**< type of orbitope constraint */
    209 SCIP_Bool resolveprop, /**< should propagation be resolved? */
    210 SCIP_Bool ismodelcons /**< whether the orbitope is a model constraint */
    211 )
    212{
    213 int i;
    214 int j;
    215
    216 assert(consdata != NULL);
    217
    218 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    219
    220 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vals, nrows) );
    221 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->weights, nrows) );
    222 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vars, nrows) );
    223 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->cases, nrows) );
    224
    225 for (i = 0; i < nrows; ++i)
    226 {
    227 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vals[i], ncols) ); /*lint !e866*/
    228 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->weights[i], ncols) ); /*lint !e866*/
    229 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars[i], vars[i], ncols) ); /*lint !e866*/
    230 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->cases[i], ncols) ); /*lint !e866*/
    231 }
    232 (*consdata)->tmpvals = NULL;
    233 (*consdata)->tmpvars = NULL;
    234 (*consdata)->nrows = nrows;
    235 (*consdata)->ncols = ncols;
    236 (*consdata)->orbitopetype = orbitopetype;
    237 (*consdata)->resolveprop = resolveprop;
    238 (*consdata)->istrianglefixed = FALSE;
    239 (*consdata)->ismodelcons = ismodelcons;
    240
    241 /* get transformed variables, if we are in the transformed problem */
    242 if ( SCIPisTransformed(scip) )
    243 {
    244 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->tmpvals, nrows + ncols) );
    245 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->tmpvars, nrows + ncols) );
    246
    247 for (i = 0; i < nrows; ++i)
    248 {
    249 /* make sure that no variable gets multiaggregated (cannot be handled by cons_orbitope, since one cannot easily
    250 * eliminate single variables from an orbitope constraint).
    251 */
    252 for (j = 0; j < ncols; ++j)
    253 {
    254 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars[i][j], &(*consdata)->vars[i][j]) );
    255 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[i][j]) );
    256 }
    257 }
    258 }
    259
    260 /* capture vars contained in vars array */
    261 for (i = 0; i < nrows; ++i)
    262 {
    263 for (j = 0; j < ncols; ++j)
    264 {
    265 assert( (*consdata)->vars[i][j] != NULL );
    266 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[i][j]) );
    267 }
    268 }
    269
    270 return SCIP_OKAY;
    271}
    272
    273
    274#ifdef PRINT_MATRIX
    275/** debug method, prints variable matrix */
    276static
    277void printMatrix(
    278 SCIP* scip, /**< SCIP data structure */
    279 SCIP_CONSDATA* consdata /**< the constraint data */
    280 )
    281{
    282 int i;
    283 int j;
    284
    285 assert( consdata != NULL );
    286 assert( consdata->nrows > 0 );
    287 assert( consdata->ncols > 0 );
    288 assert( consdata->vars != NULL );
    289
    290 for (j = 0; j < consdata->ncols; ++j)
    292
    293 SCIPinfoMessage(scip, NULL, "\n");
    294 for (i = 0; i < consdata->nrows; ++i)
    295 {
    296 for (j = 0; j < consdata->ncols; ++j)
    297 {
    298 if ( SCIPvarGetUbLocal(consdata->vars[i][j]) - SCIPvarGetLbLocal(consdata->vars[i][j]) < 0.5 )
    299 SCIPinfoMessage(scip, NULL, "%1.0f", REALABS(SCIPvarGetUbLocal(consdata->vars[i][j])));
    300 else
    302 }
    303 SCIPinfoMessage(scip, NULL, "|\n");
    304 }
    305 for (j = 0; j < consdata->ncols; ++j)
    307 SCIPinfoMessage(scip, NULL, "\n");
    308}
    309#endif
    310
    311
    312#ifdef SHOW_SCI
    313/** Print SCI in nice form for debugging */
    314static
    315SCIP_RETCODE printSCI(
    316 SCIP* scip, /**< SCIP pointer */
    317 int nrows, /**< number of rows */
    318 int ncols, /**< number of columns */
    319 int** cases, /**< SCI dynamic programming table */
    320 int i, /**< row position of bar */
    321 int j /**< column position of bar */
    322 )
    323{
    324 int k;
    325 int l;
    326 int** M;
    327 int p1;
    328 int p2;
    329
    330 SCIP_CALL( SCIPallocBufferArray(scip, &M, nrows) );
    331 for (k = 0; k < nrows; ++k)
    332 {
    333 SCIP_CALL( SCIPallocBufferArray(scip, &M[k], ncols) ); /*lint !e866*/
    334 for (l = 0; l < ncols; ++l)
    335 M[k][l] = 0;
    336 }
    337
    338 /* first add bar */
    339 for (l = j; l < ncols; ++l)
    340 {
    341 assert( M[i][l] == 0 );
    342 M[i][l] = 1;
    343 }
    344
    345 /* then add shifted column */
    346 p1 = i-1;
    347 p2 = j-1;
    348 do
    349 {
    350 assert( cases[p1][p2] != -1 );
    351 assert( p1 >= 0 && p1 < i );
    352 assert( p2 >= 0 && p2 < j );
    353
    354 /* if case 1 */
    355 if ( cases[p1][p2] == 1 )
    356 --p2; /* decrease column */
    357 else
    358 {
    359 /* case 2 or 3: */
    360 assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
    361 assert( M[p1][p2] == 0 );
    362 M[p1][p2] = -1;
    363 if ( cases[p1][p2] == 3 )
    364 break;
    365 }
    366 --p1; /* decrease row */
    367 }
    368 while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
    369 assert( cases[p1][p2] == 3 );
    370
    371 /* now output matrix M */
    372 for (l = 0; l < ncols; ++l)
    374 SCIPinfoMessage(scip, NULL, "\n");
    375
    376 for (k = 0; k < nrows; ++k)
    377 {
    378 for (l = 0; l < ncols; ++l)
    379 {
    380 if ( l > k )
    382 else
    383 {
    384 switch (M[k][l])
    385 {
    386 case 1:
    388 break;
    389 case -1:
    391 break;
    392 case 0:
    394 break;
    395 default:
    396 SCIPerrorMessage("unexpected matrix entry <%d>: should be -1, 0 or +1\n", M[k][l]);
    397 SCIPABORT();
    398 }
    399 }
    400 }
    401 SCIPinfoMessage(scip, NULL, "\n");
    402 }
    403
    404 for (l = 0; l < ncols; ++l)
    406 SCIPinfoMessage(scip, NULL, "\n");
    407
    408 for (k = 0; k < nrows; ++k)
    411
    412 return SCIP_OKAY;
    413}
    414#endif
    415
    416
    417/** copies the variables values from the solution to the constraint data structure */
    418static
    420 SCIP* scip, /**< the SCIP data structure */
    421 SCIP_CONSDATA* consdata, /**< the constraint data */
    422 SCIP_SOL* sol /**< a primal solution or NULL for the current LP optimum */
    423 )
    424{
    425 int i;
    426 int j;
    427
    428 assert( scip != NULL );
    429 assert( consdata != NULL );
    430 assert( consdata->nrows > 0 );
    431 assert( consdata->ncols > 0 );
    432 assert( consdata->vars != NULL );
    433 assert( consdata->vals != NULL );
    434
    435 for (i = 0; i < consdata->nrows; ++i)
    436 {
    437 for (j = 0; j < consdata->ncols; ++j)
    438 consdata->vals[i][j] = SCIPgetSolVal(scip, sol, consdata->vars[i][j]);
    439 }
    440}
    441
    442
    443/** compute the dynamic programming table for SC
    444 *
    445 * Build up dynamic programming table in order to find SCs with minimum weight.
    446 *
    447 * The values of the minimal SCIs are stored in @a weights.
    448 * The array @a cases[i][j] stores which of the cases were applied to get @a weights[i][j].
    449 * Here, 3 means that we have reached the upper limit.
    450 *
    451 * We assume that the upper right triangle is fixed to 0. Hence we can perform the computation a
    452 * bit more efficient.
    453 */
    454static
    456 SCIP* scip, /**< SCIP pointer */
    457 int nrows, /**< number of rows in orbitope matrix <=> p */
    458 int ncols, /**< number of columns in orbitope matrix <=> q */
    459 SCIP_Real** weights, /**< SC weight table */
    460 int** cases, /**< indicator of the SC cases */
    461 SCIP_Real** vals /**< current solution */
    462 )
    463{
    464 SCIP_Real minvalue;
    465 int diagsize;
    466 int i;
    467 int j;
    468
    469 assert( weights != NULL );
    470 assert( cases != NULL );
    471 assert( vals != NULL );
    472
    473#ifndef NDEBUG
    474 /* for debugging */
    475 for (i = 0; i < nrows; ++i)
    476 {
    477 for (j = 0; j < ncols; ++j)
    478 {
    479 if ( i >= j )
    480 {
    481 weights[i][j] = -1.0;
    482 cases[i][j] = -1;
    483 }
    484 }
    485 }
    486#endif
    487
    488 /* initialize diagonal */
    489 minvalue = vals[0][0];
    490 weights[0][0] = minvalue;
    491 cases[0][0] = 3;
    492
    493 /* get last row of triangle */
    494 diagsize = ncols;
    495 if ( nrows < ncols )
    496 diagsize = nrows;
    497
    498 for (j = 1; j < diagsize; ++j)
    499 {
    500 /* use LT to move entry as far to the left as possible */
    501 if ( SCIPisLT(scip, vals[j][j], minvalue) )
    502 {
    503 minvalue = vals[j][j];
    504 cases[j][j] = 3;
    505 }
    506 else
    507 cases[j][j] = 1;
    508 weights[j][j] = minvalue;
    509 }
    510
    511 /* initialize first column */
    512 for (i = 1; i < nrows; ++i)
    513 {
    514 weights[i][0] = weights[i-1][0] + vals[i][0];
    515 cases[i][0] = 2; /* second case */
    516 }
    517
    518 /* build the table */
    519 for (i = 2; i < nrows; ++i)
    520 {
    521 for (j = 1; j < ncols && j < i; ++j)
    522 {
    523 SCIP_Real weightleft;
    524 SCIP_Real weightright;
    525
    526 assert( cases[i-1][j] != -1 );
    527 assert( cases[i-1][j-1] != -1 );
    528
    529 weightleft = weights[i-1][j-1];
    530 weightright = vals[i][j] + weights[i-1][j];
    531
    532 /* For first column: cannot take left possibility */
    533 if ( SCIPisLT(scip, weightleft, weightright) )
    534 {
    535 weights[i][j] = weightleft;
    536 cases[i][j] = 1;
    537 }
    538 else
    539 {
    540 weights[i][j] = weightright;
    541 cases[i][j] = 2;
    542 }
    543 }
    544 }
    545}
    546
    547
    548/** fix upper right triangle if necessary */
    549static
    551 SCIP* scip, /**< SCIP data structure */
    552 SCIP_CONS* cons, /**< constraint to be processed */
    553 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the node can be cut off */
    554 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    555 )
    556{
    557 SCIP_CONSDATA* consdata;
    558 SCIP_VAR*** vars;
    559 SCIP_Bool fixedglobal;
    560 SCIP_Bool fixed;
    561 int diagsize;
    562 int nrows;
    563 int ncols;
    564 int i;
    565 int j;
    566
    567 assert( scip != NULL );
    568 assert( cons != NULL );
    569 assert( infeasible != NULL );
    570 assert( nfixedvars != NULL );
    571
    572 consdata = SCIPconsGetData(cons);
    573 assert( consdata != NULL );
    574 assert( consdata->nrows > 0 );
    575 assert( consdata->ncols > 0 );
    576 assert( consdata->vars != NULL );
    577
    578 *infeasible = FALSE;
    579 *nfixedvars = 0;
    580
    581 if ( consdata->istrianglefixed )
    582 return SCIP_OKAY;
    583
    584 nrows = consdata->nrows;
    585 ncols = consdata->ncols;
    586 vars = consdata->vars;
    587 fixedglobal = TRUE;
    588
    589 /* get last row of triangle */
    590 diagsize = ncols;
    591 if ( nrows < ncols )
    592 diagsize = nrows;
    593
    594 /* fix variables to 0 */
    595 for (i = 0; i < diagsize; ++i)
    596 {
    597 for (j = i+1; j < ncols; ++j)
    598 {
    599 /* fix variable, if not in the root the fixation is local */
    600 SCIP_CALL( SCIPfixVar(scip, vars[i][j], 0.0, infeasible, &fixed) );
    601
    602 if ( *infeasible )
    603 {
    604 SCIPdebugMsg(scip, "The problem is infeasible: some variable in the upper right triangle is fixed to 1.\n");
    605 return SCIP_OKAY;
    606 }
    607
    608 if ( fixed )
    609 ++(*nfixedvars);
    610
    611 if ( SCIPvarGetUbGlobal(vars[i][j]) > 0.5 )
    612 fixedglobal = FALSE;
    613 }
    614 }
    615 if ( *nfixedvars > 0 )
    616 {
    617 SCIPdebugMsg(scip, "<%s>: %s fixed upper right triangle to 0 (fixed vars: %d).\n",
    618 SCIPconsGetName(cons), fixedglobal ? "globally" : "locally", *nfixedvars);
    619 }
    620 else
    621 {
    622 SCIPdebugMsg(scip, "<%s>: Upper right triangle already fixed to 0.\n", SCIPconsGetName(cons));
    623 }
    624
    625 if ( fixedglobal )
    626 consdata->istrianglefixed = TRUE;
    627
    628 return SCIP_OKAY;
    629}
    630
    631
    632/** separates shifted column inequalities according to the solution stored in consdata->vals */
    633static
    635 SCIP* scip, /**< the SCIP data structure */
    636 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    637 SCIP_CONS* cons, /**< constraint */
    638 SCIP_CONSDATA* consdata, /**< the constraint data */
    639 SCIP_Bool* infeasible, /**< whether we detected infeasibility */
    640 int* nfixedvars, /**< pointer to store the number of variables fixed */
    641 int* ncuts /**< pointer to store number of separated SCIs */
    642 )
    643{
    644 SCIP_Real** vals;
    645 SCIP_Real** weights;
    646 SCIP_Real* tmpvals;
    647 SCIP_VAR*** vars;
    648 SCIP_VAR** tmpvars;
    649 int** cases;
    650 int nrows;
    651 int ncols;
    652 int i;
    653 int j;
    654 int l;
    655
    656 assert( scip != NULL );
    657 assert( conshdlr != NULL );
    658 assert( cons != NULL );
    659 assert( infeasible != NULL);
    660 assert( nfixedvars != NULL );
    661 assert( ncuts != NULL );
    662
    663 assert( consdata != NULL );
    664 assert( consdata->nrows > 0 );
    665 assert( consdata->ncols > 0 );
    666 assert( consdata->vars != NULL );
    667 assert( consdata->vals != NULL );
    668 assert( consdata->tmpvars != NULL );
    669 assert( consdata->tmpvals != NULL );
    670 assert( consdata->weights != NULL );
    671 assert( consdata->cases != NULL );
    672
    673 *infeasible = FALSE;
    674 *nfixedvars = 0;
    675 *ncuts = 0;
    676
    677 nrows = consdata->nrows;
    678 ncols = consdata->ncols;
    679 vars = consdata->vars;
    680 vals = consdata->vals;
    681 tmpvars = consdata->tmpvars;
    682 tmpvals = consdata->tmpvals;
    683 weights = consdata->weights;
    684 cases = consdata->cases;
    685
    686 /* check for upper right triangle */
    687 if ( ! consdata->istrianglefixed )
    688 {
    689 SCIP_CALL( fixTriangle(scip, cons, infeasible, nfixedvars) );
    690 if ( *infeasible )
    691 return SCIP_OKAY;
    692 if ( *nfixedvars > 0 )
    693 return SCIP_OKAY;
    694 }
    695
    696 /* compute table if necessary (i.e., not computed before) */
    697 computeSCTable(scip, nrows, ncols, weights, cases, vals);
    698
    699 /* loop through rows */
    700 for (i = 1; i < nrows && ! (*infeasible); ++i)
    701 {
    702 SCIP_Real bar; /* value of bar: */
    703 int lastcolumn; /* last column considered as part of the bar */
    704
    705 bar = 0.0;
    706 lastcolumn = ncols - 1;
    707 if ( lastcolumn > i )
    708 lastcolumn = i;
    709
    710 /* traverse row from right to left: */
    711 /* j >= 1, since for j = 0, i.e., the bar is a complete row, there does not exist an SCI */
    712 for (j = lastcolumn; j > 0; --j)
    713 {
    714 bar += vals[i][j];
    715
    716 /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
    717 if ( SCIPisEfficacious(scip, bar - weights[i-1][j-1]) )
    718 {
    719#ifndef NDEBUG
    720 SCIP_Real weight = 0.0;
    721#endif
    722 SCIP_ROW* row;
    723#ifdef SCIP_DEBUG
    724 char name[SCIP_MAXSTRLEN];
    725#endif
    726 int nvars;
    727 int p1;
    728 int p2;
    729
    730 nvars = 0;
    731 p1 = i-1;
    732 p2 = j-1;
    733
    734 /* first add bar */
    735 for (l = j; l <= lastcolumn; ++l)
    736 {
    737 tmpvars[nvars] = vars[i][l];
    738 tmpvals[nvars] = 1.0;
    739 nvars++;
    740 }
    741
    742 /* then add shifted column */
    743 do
    744 {
    745 assert( cases[p1][p2] != -1 );
    746 assert( p1 >= 0 && p1 < i );
    747 assert( p2 >= 0 && p2 < j );
    748
    749 /* if case 1 */
    750 if (cases[p1][p2] == 1)
    751 p2--; /* decrease column */
    752 else
    753 {
    754 /* case 2 or 3: */
    755 assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
    756 tmpvars[nvars] = vars[p1][p2];
    757 tmpvals[nvars] = -1.0;
    758 nvars++;
    759#ifndef NDEBUG
    760 weight += vals[p1][p2];
    761#endif
    762 if ( cases[p1][p2] == 3 )
    763 break;
    764 }
    765 p1--; /* decrease row */
    766 }
    767 while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
    768 assert( cases[p1][p2] == 3 );
    769
    770 /* generate cut */
    771#ifdef SCIP_DEBUG
    772 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sci_%d_%d", i, j);
    773 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, name, -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
    774#else
    775 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, "", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
    776#endif
    777 SCIP_CALL( SCIPaddVarsToRow(scip, row, nvars, tmpvars, tmpvals) );
    778 /*SCIP_CALL( SCIPprintRow(scip, row, NULL) ); */
    779 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
    780 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    781 ++(*ncuts);
    782
    783#ifdef SHOW_SCI
    784 SCIP_CALL( printSCI(scip, nrows, ncols, cases, i, j) );
    785#endif
    786
    787 assert( SCIPisSumEQ(scip, weights[i-1][j-1], weight) );
    788 }
    789 }
    790 }
    791 return SCIP_OKAY;
    792}
    793
    794
    795/** propagation method for a single orbitope constraint */
    796static
    798 SCIP* scip, /**< SCIP data structure */
    799 SCIP_CONS* cons, /**< constraint to be processed */
    800 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the node can be cut off */
    801 int* nfixedvars /**< pointer to add up the number of found domain reductions */
    802 )
    803{
    804 SCIP_CONSDATA* consdata;
    805 SCIP_ORBITOPETYPE orbitopetype;
    806 SCIP_VAR*** vars;
    807 int* firstnonzeros;
    808 int* lastones;
    809 int* frontiersteps;
    810 int lastoneprevrow;
    811 int nrows;
    812 int ncols;
    813 int nsteps;
    814 int i;
    815 int j;
    816
    817 assert( scip != NULL );
    818 assert( cons != NULL );
    819 assert( infeasible != NULL );
    820 assert( nfixedvars != NULL );
    821
    822 consdata = SCIPconsGetData(cons);
    823 assert( consdata != NULL );
    824
    825 *nfixedvars = 0;
    826
    827 /* if the constraint is not a model constraint, check whether symmetry reductions are permitted */
    828 if( !consdata->ismodelcons && !SCIPallowStrongDualReds(scip) )
    829 return SCIP_OKAY;
    830
    831 consdata = SCIPconsGetData(cons);
    832 assert( consdata != NULL );
    833 assert( consdata->nrows > 0 );
    834 assert( consdata->ncols > 0 );
    835 assert( consdata->vars != NULL );
    836
    837 nrows = consdata->nrows;
    838 ncols = consdata->ncols;
    839 vars = consdata->vars;
    840 orbitopetype = consdata->orbitopetype;
    841
    842 assert( orbitopetype == SCIP_ORBITOPETYPE_PACKING || orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING );
    843
    844 /* fix upper right triangle if still necessary */
    845 if ( ! consdata->istrianglefixed )
    846 {
    847 int nfixed = 0;
    848 SCIP_CALL( fixTriangle(scip, cons, infeasible, &nfixed) );
    849 *nfixedvars += nfixed;
    850 }
    851
    852 /* prepare further propagation */
    853 SCIP_CALL( SCIPallocBufferArray(scip, &firstnonzeros, nrows) );
    854 SCIP_CALL( SCIPallocBufferArray(scip, &lastones, nrows) );
    855 SCIP_CALL( SCIPallocBufferArray(scip, &frontiersteps, ncols) );
    856
    857#ifdef PRINT_MATRIX
    858 SCIPdebugMsg(scip, "Matrix:\n");
    859 printMatrix(scip, consdata);
    860#endif
    861
    862 /* propagate */
    863 lastoneprevrow = 0;
    864 lastones[0] = 0;
    865
    866 if ( orbitopetype == SCIP_ORBITOPETYPE_PACKING )
    867 {
    868 /* packing case: if entry (0,0) is fixed to 0 */
    869 if ( SCIPvarGetUbLocal(vars[0][0]) < 0.5 )
    870 {
    871 lastoneprevrow = -1;
    872 lastones[0] = -1;
    873 }
    874 }
    875 nsteps = 0;
    876
    877 for (i = 1; i < nrows; ++i)
    878 {
    879 int lastcolumn;
    880 int firstnonzeroinrow;
    881 int lastoneinrow;
    882 SCIP_Bool infrontier;
    883
    884 /* last column considered as part of the bar: */
    885 lastcolumn = ncols - 1;
    886 if ( lastcolumn > i )
    887 lastcolumn = i;
    888
    889 /* find first position not fixed to 0 (partitioning) or fixed to 1 (packing) */
    890 firstnonzeroinrow = -1;
    891 for (j = 0; j <= lastcolumn; ++j)
    892 {
    893 if ( orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING )
    894 {
    895 /* partitioning case: if variable is not fixed to 0 */
    896 if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
    897 {
    898 firstnonzeroinrow = j;
    899 break;
    900 }
    901 }
    902 else
    903 {
    904 /* packing case: if variable is fixed to 1 */
    905 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
    906 {
    907 firstnonzeroinrow = j;
    908 break;
    909 }
    910 }
    911 }
    912 /* if all variables are fixed to 0 in the partitioning case - should not happen */
    913 if ( firstnonzeroinrow == -1 && orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING )
    914 {
    915 SCIPdebugMsg(scip, " -> Infeasible node: all variables in row %d are fixed to 0.\n", i);
    916 *infeasible = TRUE;
    917 /* conflict should be analyzed by setppc constraint handler */
    918 goto TERMINATE;
    919 }
    920 firstnonzeros[i] = firstnonzeroinrow;
    921 assert( orbitopetype == SCIP_ORBITOPETYPE_PACKING || firstnonzeroinrow >= 0 );
    922 assert( -1 <= firstnonzeroinrow && firstnonzeroinrow <= lastcolumn );
    923
    924 /* compute rightmost possible position for a 1 */
    925 assert( orbitopetype == SCIP_ORBITOPETYPE_PACKING || 0 <= lastoneprevrow );
    926 assert( lastoneprevrow <= lastcolumn );
    927
    928 /* if we are at right border or if entry in column lastoneprevrow+1 is fixed to 0 */
    929 infrontier = FALSE;
    930 assert( lastoneprevrow + 1 >= 0 );
    931 if ( lastoneprevrow == ncols-1 || SCIPvarGetUbLocal(vars[i][lastoneprevrow+1]) < 0.5 ) /*lint !e679*/
    932 lastoneinrow = lastoneprevrow;
    933 else
    934 {
    935 lastoneinrow = lastoneprevrow + 1;
    936 frontiersteps[nsteps++] = i;
    937 infrontier = TRUE;
    938 }
    939
    940 /* store lastoneinrow */
    941 assert( orbitopetype == SCIP_ORBITOPETYPE_PACKING || 0 <= lastoneinrow );
    942 assert( lastoneinrow <= lastcolumn );
    943 lastones[i] = lastoneinrow;
    944
    945 /* check whether we are infeasible */
    946 if ( firstnonzeroinrow > lastoneinrow )
    947 {
    948 int k;
    949
    950#ifdef SCIP_DEBUG
    951 if ( orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING )
    952 {
    953 SCIPdebugMsg(scip, " -> Infeasible node: row %d, leftmost nonzero at %d, rightmost 1 at %d\n",
    954 i, firstnonzeroinrow, lastoneinrow);
    955 }
    956 else
    957 {
    958 SCIPdebugMsg(scip, " -> Infeasible node: row %d, 1 at %d, rightmost position for 1 at %d\n",
    959 i, firstnonzeroinrow, lastoneinrow);
    960 }
    961#endif
    962
    963 /* check if conflict analysis is applicable */
    965 {
    966 /* conflict analysis only applicable in SOLVING stage */
    968
    969 /* perform conflict analysis */
    971
    972 if ( orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING )
    973 {
    974 /* add bounds (variables fixed to 0) that result in the first nonzero entry */
    975 for (j = 0; j <= lastcolumn; ++j)
    976 {
    977 /* add varaibles in row up to the first variable fixed to 0 */
    978 if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
    979 break;
    980
    981 assert( SCIPvarGetUbLocal(vars[i][j]) < 0.5 );
    982 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    983 }
    984 }
    985 else
    986 {
    987 /* add bounds that result in the last one - check top left entry for packing case */
    988 if ( lastones[0] == -1 )
    989 {
    990 assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
    991 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
    992 }
    993
    994 /* mark variable fixed to 1 */
    995 assert( SCIPvarGetLbLocal(vars[i][firstnonzeroinrow]) > 0.5 );
    996 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][firstnonzeroinrow]) );
    997 }
    998
    999 /* add bounds that result in the last one - pass through rows */
    1000 for (k = 1; k < i; ++k)
    1001 {
    1002 int l;
    1003 l = lastones[k] + 1;
    1004
    1005 /* if the frontier has not moved and we are not beyond the matrix boundaries */
    1006 if ( l <= ncols-1 && l <= k && lastones[k-1] == lastones[k] )
    1007 {
    1008 assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
    1009 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
    1010 }
    1011 }
    1013 }
    1014
    1015 *infeasible = TRUE;
    1016 goto TERMINATE;
    1017 }
    1018
    1019 /* fix entries beyond the last possible position for a 1 in the row to 0 (see Lemma 1 in the paper) */
    1020 for (j = lastoneinrow+1; j <= lastcolumn; ++j)
    1021 {
    1022 /* if the entry is not yet fixed to 0 */
    1023 if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
    1024 {
    1025 SCIP_Bool tightened;
    1026 int inferInfo;
    1027
    1028 SCIPdebugMsg(scip, " -> Fixing entry (%d,%d) to 0.\n", i, j);
    1029
    1030 tightened = FALSE;
    1031
    1032 /* fix variable to 0 and store position of (i,lastoneinrow+1) for conflict resolution */
    1033 inferInfo = i * ncols + lastoneinrow + 1;
    1034 /* correction according to Lemma 1 in the paper (second part): store (i,lastoneinrow+2) */
    1035 if ( !infrontier )
    1036 ++inferInfo;
    1037 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, inferInfo, infeasible, &tightened) );
    1038
    1039 /* if entry is fixed to one -> infeasible node */
    1040 if ( *infeasible )
    1041 {
    1042 SCIPdebugMsg(scip, " -> Infeasible node: row %d, 1 in column %d beyond rightmost position %d\n", i, j, lastoneinrow);
    1043 /* check if conflict analysis is applicable */
    1045 {
    1046 int k;
    1047
    1048 /* conflict analysis only applicable in SOLVING stage */
    1050
    1051 /* perform conflict analysis */
    1053
    1054 /* add current bound */
    1055 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
    1056
    1057 /* add bounds that result in the last one - check top left entry for packing case */
    1058 if ( orbitopetype == SCIP_ORBITOPETYPE_PACKING && lastones[0] == -1 )
    1059 {
    1060 assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
    1061 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
    1062 }
    1063
    1064 /* add bounds that result in the last one - pass through rows */
    1065 for (k = 1; k < i; ++k)
    1066 {
    1067 int l;
    1068 l = lastones[k] + 1;
    1069
    1070 /* if the frontier has not moved and we are not beyond the matrix boundaries */
    1071 if ( l <= ncols-1 && l <= k && lastones[k-1] == lastones[k] )
    1072 {
    1073 assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
    1074 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
    1075 }
    1076 }
    1078 }
    1079
    1080 goto TERMINATE;
    1081 }
    1082 if ( tightened )
    1083 ++(*nfixedvars);
    1084 }
    1085 }
    1086
    1087 lastoneprevrow = lastoneinrow;
    1088 }
    1089
    1090 /* check whether fixing any entry to 0 results in a contradiction -> loop through rows in frontiersteps (a.k.a. gamma) */
    1091 for (j = 0; j < nsteps; ++j)
    1092 {
    1093 int s;
    1094 int lastoneinrow;
    1095
    1096 s = frontiersteps[j];
    1097 lastoneinrow = lastones[s];
    1098 /* note for packing case: if we are in a frontier step then lastoneinrow >= 0 */
    1099 assert( 0 <= lastoneinrow && lastoneinrow < ncols );
    1100
    1101 /* if entry is not fixed */
    1102 if ( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 && SCIPvarGetUbLocal(vars[s][lastoneinrow]) > 0.5 )
    1103 {
    1104 int betaprev;
    1105 betaprev = lastoneinrow - 1;
    1106
    1107 /* loop through rows below s */
    1108 for (i = s+1; i < nrows; ++i)
    1109 {
    1110 int beta;
    1111
    1112 assert( betaprev + 1 >= 0 );
    1113 if ( betaprev == ncols-1 || SCIPvarGetUbLocal(vars[i][betaprev+1]) < 0.5 ) /*lint !e679*/
    1114 beta = betaprev;
    1115 else
    1116 beta = betaprev + 1;
    1117 assert( -1 <= beta && beta < ncols );
    1118
    1119 if ( firstnonzeros[i] > beta )
    1120 {
    1121 SCIP_Bool tightened = FALSE;
    1122 int inferInfo;
    1123
    1124 /* can fix (s,lastoneinrow) (a.k.a (s,alpha)) to 1 (do not need to fix other entries to 0, since they
    1125 * will be automatically fixed by SCIPtightenVarLb.)
    1126 */
    1127 assert( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 );
    1128 SCIPdebugMsg(scip, " -> Fixing entry (%d,%d) to 1.\n", s, lastoneinrow);
    1129
    1130 /* store position (i,firstnonzeros[i]) */
    1131 inferInfo = ncols * nrows + i * ncols + firstnonzeros[i];
    1132 SCIP_CALL( SCIPinferBinvarCons(scip, vars[s][lastoneinrow], TRUE, cons, inferInfo, infeasible, &tightened) );
    1133
    1134 assert( !(*infeasible) );
    1135 if ( tightened )
    1136 ++(*nfixedvars);
    1137 break;
    1138 }
    1139 betaprev = beta;
    1140 }
    1141 }
    1142 }
    1143
    1144 TERMINATE:
    1145 SCIPfreeBufferArray(scip, &frontiersteps);
    1146 SCIPfreeBufferArray(scip, &lastones);
    1147 SCIPfreeBufferArray(scip, &firstnonzeros);
    1148
    1149 return SCIP_OKAY;
    1150}
    1151
    1152
    1153/** Propagation conflict resolving method of propagator
    1154 *
    1155 * In this function we use that the propagation method above implicitly propagates SCIs, i.e., every
    1156 * fixing can also be gotten via an SCI-fixing.
    1157 *
    1158 * Since the storage of an integer is not enough to store the complete information about the fixing
    1159 * nor a complete shifted column, we have to use the linear time algorithm for SCIs.
    1160 *
    1161 * The inferinfo integer is set as follows:
    1162 *
    1163 * - If a shifted column is fixed to 0 and the corresponding bar does not necessarily has value 1
    1164 * then we fix these entries to 0 and inferinfo is i * ncols + j, where (i,j) is the leader of the
    1165 * bar. The SCI depends on whether i is in Gamma or not (see Lemma 1 in the paper and the comments
    1166 * above).
    1167 *
    1168 * - If a bar has value 1 and the shifted column has one entry that is not fixed, it can be fixed to
    1169 * 1 and inferinfo is (nrows*ncols) + i * ncols + j, where (i,j) is the leader of the bar; see
    1170 * Proposition 1 (2c).
    1171 */
    1172static
    1174 SCIP* scip, /**< SCIP data structure */
    1175 SCIP_CONS* cons, /**< constraint that inferred the bound change */
    1176 int inferinfo, /**< inference information */
    1177 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
    1178 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
    1179 )
    1180{ /*lint --e{715}*/
    1181 SCIP_CONSDATA* consdata;
    1182 SCIP_Real** vals;
    1183 SCIP_Real** weights;
    1184 SCIP_VAR*** vars;
    1185 SCIP_ORBITOPETYPE orbitopetype;
    1186 int** cases;
    1187
    1188 int i;
    1189 int j;
    1190 int nrows;
    1191 int ncols;
    1192
    1193 assert( scip != NULL );
    1194 assert( cons != NULL );
    1195 assert( result != NULL );
    1196
    1197 consdata = SCIPconsGetData(cons);
    1198 assert( consdata != NULL );
    1199 assert( consdata->nrows > 0 );
    1200 assert( consdata->ncols > 0 );
    1201 assert( consdata->vars != NULL );
    1202 assert( consdata->vals != NULL );
    1203 assert( consdata->weights != NULL );
    1204 assert( consdata->cases != NULL );
    1205 assert( consdata->istrianglefixed );
    1206
    1207 *result = SCIP_DIDNOTFIND;
    1208 if ( ! consdata->resolveprop )
    1209 return SCIP_OKAY;
    1210
    1211 nrows = consdata->nrows;
    1212 ncols = consdata->ncols;
    1213 vars = consdata->vars;
    1214 vals = consdata->vals;
    1215 weights = consdata->weights;
    1216 orbitopetype = consdata->orbitopetype;
    1217 cases = consdata->cases;
    1218
    1219 SCIPdebugMsg(scip, "Propagation resolution method of orbitope constraint using orbitopal fixing\n");
    1220
    1221 /* fill table */
    1222 for (i = 0; i < nrows; ++i)
    1223 {
    1224 int lastcolumn;
    1225
    1226 /* last column considered as part of the bar: */
    1227 lastcolumn = ncols - 1;
    1228 if ( lastcolumn > i )
    1229 lastcolumn = i;
    1230 for (j = 0; j <= lastcolumn; ++j)
    1231 {
    1232 /* if the variable was fixed to zero at conflict time */
    1233 if ( SCIPgetVarUbAtIndex(scip, vars[i][j], bdchgidx, FALSE) < 0.5 )
    1234 vals[i][j] = 0.0;
    1235 else
    1236 {
    1237 /* if the variable was fixed to one at conflict time */
    1238 if ( SCIPgetVarLbAtIndex(scip, vars[i][j], bdchgidx, FALSE) > 0.5 )
    1239 vals[i][j] = 2.0;
    1240 else
    1241 vals[i][j] = 1.0;
    1242 }
    1243 }
    1244 }
    1245
    1246#ifdef PRINT_MATRIX
    1247 SCIPdebugMsg(scip, "Matrix:\n");
    1248 printMatrix(scip, consdata);
    1249#endif
    1250
    1251 /* computation of table: this now minimizes the value of the shifted column */
    1252 assert( consdata->istrianglefixed );
    1253 computeSCTable(scip, nrows, ncols, weights, cases, vals);
    1254
    1255 /* if we fixed variables in the bar to zero */
    1256 assert( inferinfo >= 0 && inferinfo < 2 * nrows * ncols );
    1257 if ( inferinfo < nrows * ncols )
    1258 {
    1259 int p1;
    1260 int p2;
    1261#ifdef SCIP_DEBUG
    1262 char str[SCIP_MAXSTRLEN];
    1263 char tmpstr[SCIP_MAXSTRLEN];
    1264#endif
    1265
    1266 i = (int) (inferinfo / ncols);
    1267 j = inferinfo % ncols;
    1268 assert( 0 <= i && i < nrows );
    1269 assert( 0 <= j && j < ncols );
    1270
    1271 /* find SCI with value 0 */
    1272 assert( weights[i-1][j-1] < 0.5 );
    1273
    1274 SCIPdebugMsg(scip, " -> reason for x[%d][%d] = ... = x[%d][%d] = 0 was the following SC:\n", i, j, i, MIN(i,ncols));
    1275#ifdef SCIP_DEBUG
    1276 str[0] = '\0';
    1277#endif
    1278
    1279 p1 = i-1;
    1280 p2 = j-1;
    1281 do
    1282 {
    1283 assert( cases[p1][p2] != -1 );
    1284 assert( p1 >= 0 && p1 < i );
    1285 assert( p2 >= 0 && p2 < j );
    1286
    1287 /* if case 1 */
    1288 if ( cases[p1][p2] == 1 )
    1289 --p2; /* decrease column */
    1290 else
    1291 {
    1292 /* case 2 or 3: */
    1293 assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
    1294 assert( SCIPgetVarUbAtIndex(scip, vars[p1][p2], bdchgidx, FALSE) < 0.5 );
    1295 SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
    1296 *result = SCIP_SUCCESS;
    1297
    1298#ifdef SCIP_DEBUG
    1299 (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
    1300 (void) strncat(str, tmpstr, SCIP_MAXSTRLEN-1);
    1301#endif
    1302
    1303 if ( cases[p1][p2] == 3 )
    1304 break;
    1305 }
    1306 --p1; /* decrease row */
    1307 }
    1308 while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
    1309 assert( cases[p1][p2] == 3 );
    1310
    1311#ifdef SCIP_DEBUG
    1312 SCIPdebugMsg(scip, "%s\n", str);
    1313#endif
    1314 }
    1315 else
    1316 {
    1317 int k;
    1318 int p1;
    1319 int p2;
    1320#ifndef NDEBUG
    1321 int pos1;
    1322 int pos2;
    1323#endif
    1324#ifdef SCIP_DEBUG
    1325 char str[SCIP_MAXSTRLEN];
    1326 char tmpstr[SCIP_MAXSTRLEN];
    1327#endif
    1328
    1329 /* if we fixed a variable in the SC to 1 */
    1330 inferinfo -= nrows * ncols;
    1331 i = (int) inferinfo / ncols;
    1332 j = inferinfo % ncols;
    1333 assert( 0 <= i && i < nrows );
    1334 assert( 0 <= j && j < ncols );
    1335
    1336 /* In rare cases it might happen that we fixed a variable to 1, but the node later becomes infeasible by globally
    1337 * fixing variables to 0. In this case, it might happen that we find a SC with value 0 instead of 1. We then
    1338 * cannot use this SC to repropagate (and do not know how to reconstruct the original reasoning). */
    1339 if ( weights[i-1][j-1] > 0.5 && weights[i-1][j-1] < 1.5 )
    1340 {
    1341 SCIPdebugMsg(scip, " -> reason for x[%d][%d] = 1 was the following SC:\n", i, j);
    1342#ifdef SCIP_DEBUG
    1343 (void) SCIPsnprintf(str, SCIP_MAXSTRLEN, "SC:");
    1344#endif
    1345
    1346 p1 = i-1;
    1347 p2 = j-1;
    1348#ifndef NDEBUG
    1349 pos1 = -1;
    1350 pos2 = -1;
    1351#endif
    1352 do
    1353 {
    1354 assert( cases[p1][p2] != -1 );
    1355 assert( p1 >= 0 && p1 < i );
    1356 assert( p2 >= 0 && p2 < j );
    1357
    1358 /* if case 1 */
    1359 if ( cases[p1][p2] == 1 )
    1360 --p2; /* decrease column */
    1361 else
    1362 {
    1363 /* case 2 or 3: reason are formed by variables in SC fixed to 0 */
    1364 assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
    1365 if ( SCIPgetVarUbAtIndex(scip, vars[p1][p2], bdchgidx, FALSE) < 0.5 )
    1366 {
    1367 SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
    1368 *result = SCIP_SUCCESS;
    1369
    1370#ifdef SCIP_DEBUG
    1371 (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
    1372 (void) strncat(str, tmpstr, SCIP_MAXSTRLEN-1);
    1373#endif
    1374 }
    1375#ifndef NDEBUG
    1376 else
    1377 {
    1378 assert( SCIPgetVarLbAtIndex(scip, vars[p1][p2], bdchgidx, FALSE) < 0.5 );
    1379 assert( pos1 == -1 && pos2 == -1 );
    1380 pos1 = p1;
    1381 pos2 = p2;
    1382 }
    1383#endif
    1384 if ( cases[p1][p2] == 3 )
    1385 break;
    1386 }
    1387 --p1; /* decrease row */
    1388 }
    1389 while ( p1 >= 0 ); /* should always be true, i.e., the break should end the loop */
    1390 assert( cases[p1][p2] == 3 );
    1391 assert( pos1 >= 0 && pos2 >= 0 );
    1392
    1393 /* distinguish partitioning/packing */
    1394 if ( orbitopetype == SCIP_ORBITOPETYPE_PARTITIONING )
    1395 {
    1396 /* partitioning case */
    1397#ifdef SCIP_DEBUG
    1398 (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " before bar: ");
    1399 (void) strncat(str, tmpstr, SCIP_MAXSTRLEN-1);
    1400#endif
    1401 /* add variables before the bar in the partitioning case */
    1402 for (k = 0; k < j; ++k)
    1403 {
    1404 assert( SCIPgetVarUbAtIndex(scip, vars[i][k], bdchgidx, FALSE) < 0.5 );
    1405 SCIP_CALL( SCIPaddConflictUb(scip, vars[i][k], bdchgidx) );
    1406 *result = SCIP_SUCCESS;
    1407#ifdef SCIP_DEBUG
    1408 (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", i, k);
    1409 (void) strncat(str, tmpstr, SCIP_MAXSTRLEN-1);
    1410#endif
    1411 }
    1412
    1413#ifdef SCIP_DEBUG
    1414 SCIPdebugMsg(scip, "%s\n", str);
    1415#endif
    1416 }
    1417 else
    1418 {
    1419 /* packing case */
    1420 int lastcolumn;
    1421
    1422 /* last column considered as part of the bar: */
    1423 lastcolumn = ncols - 1;
    1424 if ( lastcolumn > i )
    1425 lastcolumn = i;
    1426
    1427 /* search for variable in the bar that is fixed to 1 in the packing case */
    1428 for (k = j; k <= lastcolumn; ++k)
    1429 {
    1430 if ( SCIPgetVarLbAtIndex(scip, vars[i][k], bdchgidx, FALSE) > 0.5 )
    1431 {
    1432 SCIP_CALL( SCIPaddConflictLb(scip, vars[i][k], bdchgidx) );
    1433 *result = SCIP_SUCCESS;
    1434 SCIPdebugMsg(scip, " and variable x[%d][%d] fixed to 1.\n", i, k);
    1435 break;
    1436 }
    1437 }
    1438 }
    1439 }
    1440 }
    1441
    1442 return SCIP_OKAY;
    1443}
    1444
    1445
    1446/** check packing/partitioning orbitope solution for feasibility */
    1447static
    1449 SCIP* scip, /**< SCIP data structure */
    1450 SCIP_CONS* cons, /**< pointer to orbitope constraint */
    1451 SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
    1452 )
    1453{
    1454 SCIP_CONSDATA* consdata;
    1455 SCIP_Real** weights;
    1456 SCIP_Real** vals;
    1457 int** cases;
    1458 int nrows;
    1459 int ncols;
    1460 int i;
    1461 int j;
    1462
    1463 assert( scip != NULL );
    1464 assert( cons != NULL );
    1465 consdata = SCIPconsGetData(cons);
    1466 assert( consdata != NULL );
    1467
    1468 /* do not enforce non-model constraints if strong dual reductions are not permitted */
    1469 if ( !consdata->ismodelcons && !SCIPallowStrongDualReds(scip) )
    1470 return SCIP_OKAY;
    1471
    1472 assert( consdata->nrows > 0 );
    1473 assert( consdata->ncols > 0 );
    1474 assert( consdata->vals != NULL );
    1475 assert( consdata->weights != NULL );
    1476 assert( consdata->cases != NULL );
    1477
    1478 /* check for upper right triangle */
    1479 if ( ! consdata->istrianglefixed )
    1480 {
    1481 SCIP_Bool infeasible = FALSE;
    1482 int nfixedvars = 0;
    1483
    1484 SCIP_CALL( fixTriangle(scip, cons, &infeasible, &nfixedvars) );
    1485 if ( infeasible )
    1486 {
    1487 *result = SCIP_CUTOFF;
    1488 return SCIP_OKAY;
    1489 }
    1490 if ( nfixedvars > 0 )
    1491 {
    1492 *result = SCIP_REDUCEDDOM;
    1493 return SCIP_OKAY;
    1494 }
    1495 }
    1496
    1497 nrows = consdata->nrows;
    1498 ncols = consdata->ncols;
    1499 vals = consdata->vals;
    1500 weights = consdata->weights;
    1501 cases = consdata->cases;
    1502
    1503 /* get solution */
    1504 copyValues(scip, consdata, NULL);
    1505 SCIPdebugMsg(scip, "Enforcing (pseudo solutions) for orbitope constraint <%s>\n", SCIPconsGetName(cons));
    1506
    1507 /* compute table */
    1508 assert( consdata->istrianglefixed );
    1509 computeSCTable(scip, nrows, ncols, weights, cases, vals);
    1510
    1511 /* loop through rows */
    1512 for (i = 1; i < nrows; ++i)
    1513 {
    1514 SCIP_Real bar = 0.0;
    1515 int lastcolumn;
    1516
    1517 lastcolumn = ncols - 1;
    1518
    1519 /* last column considered as part of the bar: */
    1520 if ( lastcolumn > i )
    1521 lastcolumn = i;
    1522
    1523 /* traverse row from right to left */
    1524 for (j = lastcolumn; j > 0; --j)
    1525 {
    1526 bar += vals[i][j];
    1527 assert( SCIPisIntegral(scip, vals[i][j]) );
    1528
    1529 /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
    1530 if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
    1531 {
    1532 SCIPdebugMsg(scip, "Solution is infeasible.\n");
    1533 *result = SCIP_INFEASIBLE;
    1534 return SCIP_OKAY;
    1535 }
    1536 }
    1537 }
    1538
    1539 return SCIP_OKAY;
    1540}
    1541
    1542
    1543/** check packing/partitioning orbitope solution for feasibility */
    1544static
    1546 SCIP* scip, /**< SCIP data structure */
    1547 SCIP_CONS* cons, /**< pointer to orbitope constraint */
    1548 SCIP_SOL* sol, /**< solution to be checked */
    1549 SCIP_RESULT* result, /**< pointer to store the result of the enforcing call */
    1550 SCIP_Bool printreason /**< whether reason for infeasibility should be printed */
    1551 )
    1552{
    1553 SCIP_CONSDATA* consdata;
    1554 SCIP_VAR*** vars;
    1555 SCIP_Real** vals;
    1556 SCIP_Real** weights;
    1557 int** cases;
    1558 int nrows;
    1559 int ncols;
    1560 int i;
    1561 int j;
    1562
    1563 /* get data of constraint */
    1564 assert( cons != 0 );
    1565 consdata = SCIPconsGetData(cons);
    1566 assert( consdata != NULL );
    1567 assert( consdata->nrows > 0 );
    1568 assert( consdata->ncols > 0 );
    1569 assert( consdata->vars != NULL );
    1570 assert( consdata->vals != NULL );
    1571 assert( consdata->weights != NULL );
    1572 assert( consdata->cases != NULL );
    1573
    1574 nrows = consdata->nrows;
    1575 ncols = consdata->ncols;
    1576 vars = consdata->vars;
    1577 vals = consdata->vals;
    1578 weights = consdata->weights;
    1579 cases = consdata->cases;
    1580
    1581 /* get solution */
    1582 copyValues(scip, consdata, sol);
    1583 SCIPdebugMsg(scip, "Checking orbitope constraint <%s> ...\n", SCIPconsGetName(cons));
    1584
    1585 /* check upper right triangle (if not yet fixed to zero or in debug mode */
    1586#ifdef NDEBUG
    1587 if ( ! consdata->istrianglefixed )
    1588#endif
    1589 {
    1590 int diagsize;
    1591
    1592 /* get last row of triangle */
    1593 diagsize = ncols;
    1594 if ( nrows < ncols )
    1595 diagsize = nrows;
    1596
    1597 /* check variables */
    1598 for (i = 0; i < diagsize; ++i)
    1599 {
    1600 for (j = i+1; j < ncols; ++j)
    1601 {
    1602 if ( ! SCIPisFeasZero(scip, vals[i][j]) )
    1603 {
    1604 if ( printreason )
    1605 SCIPinfoMessage(scip, NULL, "variable x[%d][%d] = %f on upper right nonzero.\n", i, j, vals[i][j]);
    1606 *result = SCIP_INFEASIBLE;
    1607
    1608 return SCIP_OKAY;
    1609 }
    1610 }
    1611 }
    1612 }
    1613
    1614 /* compute table */
    1615 computeSCTable(scip, nrows, ncols, weights, cases, vals);
    1616
    1617 /* loop through rows */
    1618 for (i = 1; i < nrows; ++i)
    1619 {
    1620 SCIP_Real bar;
    1621 int lastcolumn;
    1622
    1623 lastcolumn = ncols - 1;
    1624 bar = 0.0;
    1625 /* last column considered as part of the bar: */
    1626 if ( lastcolumn > i )
    1627 lastcolumn = i;
    1628
    1629 /* traverse row from right to left */
    1630 for (j = lastcolumn; j > 0; --j)
    1631 {
    1632 bar += vals[i][j];
    1633 assert( SCIPisFeasIntegral(scip, vals[i][j]) );
    1634
    1635 /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
    1636 if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
    1637 {
    1638 SCIPdebugMsg(scip, "Solution is infeasible.\n");
    1639 *result = SCIP_INFEASIBLE;
    1640
    1641 if ( printreason )
    1642 {
    1643 int l;
    1644 int p1;
    1645 int p2;
    1646
    1647 SCIPinfoMessage(scip, NULL, "violated SCI: bar(");
    1648
    1649 /* first output bar */
    1650 for (l = j; l < ncols; ++l)
    1651 SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[i][l]), consdata->vals[i][l]);
    1652
    1653 SCIPinfoMessage(scip, NULL, ") SC(");
    1654
    1655 /* output shifted column */
    1656 p1 = i-1;
    1657 p2 = j-1;
    1658 do
    1659 {
    1660 assert( cases[p1][p2] != -1 );
    1661 assert( p1 >= 0 && p1 < i );
    1662 assert( p2 >= 0 && p2 < j );
    1663
    1664 /* if case 1 */
    1665 if (cases[p1][p2] == 1)
    1666 --p2; /* decrease column */
    1667 else
    1668 {
    1669 /* case 2 or 3: */
    1670 assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
    1671 SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[p1][p2]), consdata->vals[p1][p2]);
    1672 if ( cases[p1][p2] == 3 )
    1673 break;
    1674 }
    1675 --p1; /* decrease row */
    1676 }
    1677 while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
    1678 assert( cases[p1][p2] == 3 );
    1679
    1680 SCIPinfoMessage(scip, NULL, ")");
    1681 }
    1682
    1683 return SCIP_OKAY;
    1684 }
    1685 }
    1686 }
    1687
    1688 return SCIP_OKAY;
    1689}
    1690
    1691
    1692/** separate or enforce constraints */
    1693static
    1695 SCIP* scip, /**< SCIP data structure */
    1696 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    1697 SCIP_CONS** conss, /**< constraints to process */
    1698 int nconss, /**< number of constraints */
    1699 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
    1700 SCIP_SOL* sol, /**< solution to separate (NULL for the LP solution) */
    1701 SCIP_RESULT* result, /**< pointer to store the result (should be initialized) */
    1702 SCIP_Bool enforce /**< whether we enforce orbitope constraints */
    1703 )
    1704{
    1705 SCIP_Bool infeasible = FALSE;
    1706 int nfixedvars = 0;
    1707 int ncuts = 0;
    1708 int c;
    1709
    1710 assert( scip != NULL );
    1711 assert( conshdlr != NULL );
    1712 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    1713 assert( result != NULL );
    1714
    1715 /* loop through constraints */
    1716 for (c = 0; c < nconss && ! infeasible; c++)
    1717 {
    1718 SCIP_CONSDATA* consdata;
    1719 int nconsfixedvars = 0;
    1720 int nconscuts = 0;
    1721
    1722 assert( conss[c] != NULL );
    1723
    1724 /* get data of constraint */
    1725 consdata = SCIPconsGetData(conss[c]);
    1726 assert( consdata != NULL );
    1727
    1728 /* skip non-model constraints if strong dual reductions are not permitted */
    1729 if ( !consdata->ismodelcons && !SCIPallowStrongDualReds(scip) )
    1730 continue;
    1731
    1732 /* do not enforce non-model constraints */
    1733 if ( enforce && !consdata->ismodelcons )
    1734 continue;
    1735
    1736 /* get solution */
    1737 copyValues(scip, consdata, sol);
    1738
    1739 /* separate */
    1740 SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nconsfixedvars, &nconscuts) );
    1741 nfixedvars += nconsfixedvars;
    1742 ncuts += nconscuts;
    1743
    1744 /* stop after the useful constraints if we found cuts of fixed variables */
    1745 if ( c >= nusefulconss && (ncuts > 0 || nfixedvars > 0) )
    1746 break;
    1747 }
    1748
    1749 if ( infeasible )
    1750 {
    1751 SCIPdebugMsg(scip, "Infeasible node.\n");
    1752 *result = SCIP_CUTOFF;
    1753 }
    1754 else if ( nfixedvars > 0 )
    1755 {
    1756 SCIPdebugMsg(scip, "Fixed %d variables.\n", nfixedvars);
    1757 *result = SCIP_REDUCEDDOM;
    1758 }
    1759 else if ( ncuts > 0 )
    1760 {
    1761 SCIPdebugMsg(scip, "Separated %dinequalities.\n", ncuts);
    1762 *result = SCIP_SEPARATED;
    1763 }
    1764 else
    1765 {
    1766 SCIPdebugMsg(scip, "No violated inequality found during separation.\n");
    1767 }
    1768
    1769 return SCIP_OKAY;
    1770}
    1771
    1772
    1773/** check whether all variables in an orbitope constraint are fixed */
    1774static
    1776 SCIP* scip, /**< SCIP data structure */
    1777 SCIP_CONS* cons, /**< constraint to be processed */
    1778 SCIP_Bool* redundant /**< pointer to store whether constraint is redundant (contains no active vars) */
    1779 )
    1780{
    1781 SCIP_CONSDATA* consdata;
    1782 SCIP_VAR*** vars;
    1783 int i;
    1784 int j;
    1785 int nrows;
    1786 int ncols;
    1787
    1788 assert( scip != NULL );
    1789 assert( cons != NULL );
    1790 assert( redundant != NULL );
    1791
    1792 *redundant = FALSE;
    1793
    1794 consdata = SCIPconsGetData(cons);
    1795 assert( consdata != NULL );
    1796 assert( consdata->vars != NULL );
    1797 assert( consdata->nrows > 0 );
    1798 assert( consdata->ncols > 0 );
    1799
    1800 vars = consdata->vars;
    1801 nrows = consdata->nrows;
    1802 ncols = consdata->ncols;
    1803
    1804 /* check whether there exists an active variable in the orbitope */
    1805 for (i = 0; i < nrows; ++i)
    1806 {
    1807 for (j = 0; j < ncols; ++j)
    1808 {
    1809 if ( SCIPvarIsActive(vars[i][j]) )
    1810 return SCIP_OKAY;
    1811 }
    1812 }
    1813 *redundant = TRUE;
    1814
    1815 return SCIP_OKAY;
    1816}
    1817
    1818/** replace aggregated variables by active variables */
    1819static
    1821 SCIP* scip, /**< SCIP data structure */
    1822 SCIP_CONS* cons /**< constraint to be processed */
    1823 )
    1824{
    1825 SCIP_CONSDATA* consdata;
    1826 SCIP_VAR*** vars;
    1827 int i;
    1828 int j;
    1829 int nrows;
    1830 int ncols;
    1831
    1832 assert( scip != NULL );
    1833 assert( cons != NULL );
    1834
    1835 consdata = SCIPconsGetData(cons);
    1836 assert( consdata != NULL );
    1837 assert( consdata->vars != NULL );
    1838 assert( consdata->nrows > 0 );
    1839 assert( consdata->ncols > 0 );
    1840
    1841 vars = consdata->vars;
    1842 nrows = consdata->nrows;
    1843 ncols = consdata->ncols;
    1844
    1845 /* check whether there exists an aggregated variable in the orbitope */
    1846 for (i = 0; i < nrows; ++i)
    1847 {
    1848 for (j = 0; j < ncols; ++j)
    1849 {
    1850 SCIP_VAR* var;
    1851 SCIP_Bool negated;
    1852
    1853 assert( SCIPvarGetStatus(vars[i][j]) != SCIP_VARSTATUS_MULTAGGR ); /* variables are marked as not to be multi-aggregated */
    1854
    1855 SCIP_CALL( SCIPgetBinvarRepresentative(scip, vars[i][j], &var, &negated) );
    1856 SCIP_UNUSED( negated );
    1858 if ( var != vars[i][j] )
    1859 {
    1860 SCIP_CALL( SCIPreleaseVar(scip, &vars[i][j]) );
    1861 vars[i][j] = var;
    1862 SCIP_CALL( SCIPcaptureVar(scip, var) );
    1863 }
    1864 }
    1865 }
    1866
    1867 return SCIP_OKAY;
    1868}
    1869
    1870
    1871/*
    1872 * Callback methods of constraint handler
    1873 */
    1874
    1875/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    1876static
    1877SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitopePP)
    1878{ /*lint --e{715}*/
    1879 assert(scip != NULL);
    1880 assert(conshdlr != NULL);
    1881 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    1882 assert(valid != NULL);
    1883
    1884 /* call inclusion method of constraint handler */
    1886
    1887 *valid = TRUE;
    1888
    1889 return SCIP_OKAY;
    1890}
    1891
    1892/** frees constraint handler */
    1893static
    1894SCIP_DECL_CONSFREE(consFreeOrbitopePP)
    1895{ /*lint --e{715}*/
    1896 SCIP_CONSHDLRDATA* conshdlrdata;
    1897
    1898 assert( scip != 0 );
    1899 assert( conshdlr != 0 );
    1900 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    1901
    1902 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    1903 assert( conshdlrdata != NULL );
    1904
    1905 SCIPfreeBlockMemory(scip, &conshdlrdata);
    1906
    1907 return SCIP_OKAY;
    1908}
    1909
    1910/** frees specific constraint data */
    1911static
    1912SCIP_DECL_CONSDELETE(consDeleteOrbitopePP)
    1913{ /*lint --e{715}*/
    1914 assert(conshdlr != NULL);
    1915 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    1916
    1917 SCIP_CALL( consdataFree(scip, consdata) );
    1918
    1919 return SCIP_OKAY;
    1920}
    1921
    1922/** transforms constraint data into data belonging to the transformed problem */
    1923static
    1924SCIP_DECL_CONSTRANS(consTransOrbitopePP)
    1925{ /*lint --e{715}*/
    1926 SCIP_CONSDATA* sourcedata;
    1927 SCIP_CONSDATA* targetdata;
    1928
    1929 assert(conshdlr != NULL);
    1930 assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
    1932 assert(sourcecons != NULL);
    1933 assert(targetcons != NULL);
    1934
    1935 sourcedata = SCIPconsGetData(sourcecons);
    1936 assert(sourcedata != NULL);
    1937
    1938 /* create linear constraint data for target constraint */
    1939 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->vars, sourcedata->nrows, sourcedata->ncols,
    1940 sourcedata->orbitopetype, sourcedata->resolveprop, sourcedata->ismodelcons) );
    1941
    1942 /* create target constraint */
    1943 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    1944 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    1945 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    1946 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    1947 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    1948
    1949 return SCIP_OKAY;
    1950}
    1951
    1952/** separation method of constraint handler for LP solutions */
    1953static
    1954SCIP_DECL_CONSSEPALP(consSepalpOrbitopePP)
    1955{ /*lint --e{715}*/
    1956 assert( scip != NULL );
    1957 assert( result != NULL );
    1958
    1959 SCIPdebugMsg(scip, "Separation of packing/partitioning orbitope constraint handler <%s> for LP solution.\n",
    1960 SCIPconshdlrGetName(conshdlr));
    1961
    1962 *result = SCIP_DIDNOTRUN;
    1963
    1964 /* if solution is integer, skip separation */
    1965 if ( SCIPgetNLPBranchCands(scip) <= 0 )
    1966 return SCIP_OKAY;
    1967
    1968 *result = SCIP_DIDNOTFIND;
    1969
    1970 /* separate constraints */
    1971 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, NULL, result, FALSE) );
    1972
    1973 return SCIP_OKAY;
    1974}
    1975
    1976/** separation method of constraint handler for arbitrary primal solutions */
    1977static
    1978SCIP_DECL_CONSSEPASOL(consSepasolOrbitopePP)
    1979{ /*lint --e{715}*/
    1980 assert( scip != NULL );
    1981 assert( result != NULL );
    1982
    1983 SCIPdebugMsg(scip, "Separation of packing/partitioning orbitope constraint handler <%s> for primal solution.\n",
    1984 SCIPconshdlrGetName(conshdlr));
    1985
    1986 *result = SCIP_DIDNOTFIND;
    1987
    1988 /* separate constraints */
    1989 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, sol, result, FALSE) );
    1990
    1991 return SCIP_OKAY;
    1992}
    1993
    1994
    1995/** constraint enforcing method of constraint handler for LP solutions */
    1996static
    1997SCIP_DECL_CONSENFOLP(consEnfolpOrbitopePP)
    1998{ /*lint --e{715}*/
    1999 assert( scip != NULL );
    2000 assert( result != NULL );
    2001
    2002 /* we have a negative priority, so we should come after the integrality conshdlr */
    2003 assert( SCIPgetNLPBranchCands(scip) == 0 );
    2004
    2005 SCIPdebugMsg(scip, "Enforcement for packing/partitioning orbitope constraint handler <%s> for LP solution.\n",
    2006 SCIPconshdlrGetName(conshdlr));
    2007
    2008 *result = SCIP_FEASIBLE;
    2009
    2010 /* separate constraints */
    2011 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, NULL, result, TRUE) );
    2012
    2013 return SCIP_OKAY;
    2014}
    2015
    2016
    2017/** constraint enforcing method of constraint handler for relaxation solutions */
    2018static
    2019SCIP_DECL_CONSENFORELAX(consEnforelaxOrbitopePP)
    2020{ /*lint --e{715}*/
    2021 assert( result != NULL );
    2022 assert( scip != NULL );
    2023
    2025 "Enforcement for packing/partitioning orbitope constraint handler <%s> for relaxation solution.\n",
    2026 SCIPconshdlrGetName(conshdlr));
    2027
    2028 *result = SCIP_FEASIBLE;
    2029
    2030 /* separate constraints */
    2031 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, sol, result, TRUE) );
    2032
    2033 return SCIP_OKAY;
    2034}
    2035
    2036
    2037/** constraint enforcing method of constraint handler for pseudo solutions */
    2038static
    2039SCIP_DECL_CONSENFOPS(consEnfopsOrbitopePP)
    2040{ /*lint --e{715}*/
    2041 int c;
    2042
    2043 assert( scip != NULL );
    2044 assert( conshdlr != NULL );
    2045 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2046 assert( result != NULL );
    2047
    2048 *result = SCIP_FEASIBLE;
    2049 if ( objinfeasible || solinfeasible )
    2050 return SCIP_OKAY;
    2051
    2052 /* loop through constraints */
    2053 for (c = 0; c < nconss; ++c)
    2054 {
    2055 SCIP_CONS* cons;
    2056 SCIP_CONSDATA* consdata;
    2057
    2058 /* get data of constraint */
    2059 cons = conss[c];
    2060 assert( cons != 0 );
    2061 consdata = SCIPconsGetData(cons);
    2062
    2063 assert( consdata != NULL );
    2064
    2065 /* do not enforce non-model constraints */
    2066 if ( ! consdata->ismodelcons )
    2067 continue;
    2068
    2070
    2071 if ( *result == SCIP_INFEASIBLE )
    2072 break;
    2073 }
    2074
    2075 return SCIP_OKAY;
    2076}
    2077
    2078
    2079/** feasibility check method of constraint handler for integral solutions */
    2080static
    2081SCIP_DECL_CONSCHECK(consCheckOrbitopePP)
    2082{ /*lint --e{715}*/
    2083 int c;
    2084 SCIP_CONSDATA* consdata;
    2085
    2086 assert( scip != NULL );
    2087 assert( conshdlr != NULL );
    2088 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2089 assert( result != NULL );
    2090
    2091 *result = SCIP_FEASIBLE;
    2092
    2093 /* loop through constraints */
    2094 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
    2095 {
    2096 assert( conss[c] != 0 );
    2097 consdata = SCIPconsGetData(conss[c]);
    2098
    2099 assert( consdata != NULL );
    2100
    2101 /* do not check non-model constraints */
    2102 if ( !consdata->ismodelcons )
    2103 continue;
    2104
    2105 SCIP_CALL( checkPackingPartitioningOrbitopeSolution(scip, conss[c], sol, result, printreason) );
    2106 }
    2107
    2108 if( *result == SCIP_FEASIBLE )
    2109 {
    2110 SCIPdebugMsg(scip, "Solution is feasible.\n");
    2111 }
    2112 else
    2113 {
    2114 SCIPdebugMsg(scip, "Solution is infeasible.\n");
    2115 }
    2116
    2117 return SCIP_OKAY;
    2118}
    2119
    2120
    2121/** domain propagation method of constraint handler */
    2122static
    2123SCIP_DECL_CONSPROP(consPropOrbitopePP)
    2124{ /*lint --e{715}*/
    2125 SCIP_Bool infeasible = FALSE;
    2126 int nfixedvars = 0;
    2127 int c;
    2128
    2129 assert( scip != NULL );
    2130 assert( conshdlr != NULL );
    2131 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2132 assert( result != NULL );
    2133
    2134 *result = SCIP_DIDNOTRUN;
    2135
    2136 /* propagate all useful constraints */
    2137 for (c = 0; c < nusefulconss && !infeasible; ++c)
    2138 {
    2139 int nfixed;
    2140
    2141 assert( conss[c] != 0 );
    2142
    2143 SCIPdebugMsg(scip, "Propagation of packing/partitioning orbitope constraint <%s> ...\n",
    2144 SCIPconsGetName(conss[c]));
    2145
    2146 SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
    2147 nfixedvars += nfixed;
    2148 }
    2149
    2150 /* return the correct result */
    2151 if ( infeasible )
    2152 {
    2153 *result = SCIP_CUTOFF;
    2154 SCIPdebugMsg(scip, "Propagation via orbitopal fixing proved node to be infeasible.\n");
    2155 }
    2156 else if ( nfixedvars > 0 )
    2157 {
    2158 *result = SCIP_REDUCEDDOM;
    2159 SCIPdebugMsg(scip, "Propagated %d variables via orbitopal fixing.\n", nfixedvars);
    2160 }
    2161 else if ( nusefulconss > 0 )
    2162 {
    2163 *result = SCIP_DIDNOTFIND;
    2164 SCIPdebugMsg(scip, "Propagation via orbitopal fixing did not find anything.\n");
    2165 }
    2166
    2167 return SCIP_OKAY;
    2168}
    2169
    2170
    2171/** presolving method of constraint handler */
    2172static
    2173SCIP_DECL_CONSPRESOL(consPresolOrbitopePP)
    2174{ /*lint --e{715}*/
    2175 SCIP_Bool infeasible = FALSE;
    2176 int noldfixedvars;
    2177 int c;
    2178 SCIP_Bool redundant;
    2179
    2180 assert( scip != NULL );
    2181 assert( conshdlr != NULL );
    2182 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2183 assert( result != NULL );
    2184
    2185 *result = SCIP_DIDNOTRUN;
    2186 noldfixedvars = *nfixedvars;
    2187
    2188 /* propagate all useful constraints
    2189 *
    2190 * @todo use an event handler to only propagate if a variable in the orbitope has been fixed
    2191 */
    2192 for (c = 0; c < nconss && !infeasible; ++c)
    2193 {
    2194 int nfixed = 0;
    2195
    2196 assert( conss[c] != 0 );
    2197
    2198 SCIPdebugMsg(scip, "Presolving of packing/partitioning orbitope constraint <%s> ...\n",
    2199 SCIPconsGetName(conss[c]));
    2200
    2201 /* first propagate */
    2202 SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
    2203 *nfixedvars += nfixed;
    2204
    2205 if ( ! infeasible )
    2206 {
    2207 SCIP_CALL( checkRedundantCons(scip, conss[c], &redundant) );
    2208
    2209 if ( redundant )
    2210 {
    2212 "Packing/Partitioning orbitope constraint <%s> is redundant: it does not contain active variables\n",
    2213 SCIPconsGetName(conss[c]));
    2214 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
    2215 assert( ! SCIPconsIsActive(conss[c]) );
    2216 (*ndelconss)++;
    2217 continue;
    2218 }
    2219 }
    2220 }
    2221
    2222 if ( infeasible )
    2223 {
    2224 *result = SCIP_CUTOFF;
    2225 SCIPdebugMsg(scip, "Presolving detected infeasibility.\n");
    2226 }
    2227 else if ( *nfixedvars > noldfixedvars )
    2228 {
    2229 *result = SCIP_SUCCESS;
    2230 }
    2231 else if ( nconss > 0 )
    2232 {
    2233 *result = SCIP_DIDNOTFIND;
    2234 SCIPdebugMsg(scip, "Presolving via orbitopal fixing did not find anything.\n");
    2235 }
    2236
    2237 return SCIP_OKAY;
    2238}
    2239
    2240
    2241/** propagation conflict resolving method of constraint handler */
    2242static
    2243SCIP_DECL_CONSRESPROP(consRespropOrbitopePP)
    2244{ /*lint --e{715}*/
    2245 assert( scip != NULL );
    2246 assert( cons != NULL );
    2247 assert( infervar != NULL );
    2248 assert( bdchgidx != NULL );
    2249 assert( result != NULL );
    2250
    2251 SCIP_CALL( resolvePropagation(scip, cons, inferinfo, bdchgidx, result) );
    2252
    2253 return SCIP_OKAY;
    2254}
    2255
    2256
    2257/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    2258static
    2259SCIP_DECL_CONSEXITPRE(consExitpreOrbitopePP)
    2260{
    2261 int c;
    2262
    2263 assert( scip != NULL );
    2264 assert( conshdlr != NULL );
    2265 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2266
    2267 for (c = 0; c < nconss; ++c)
    2268 {
    2269 /* replace aggregated variables by active variables */
    2271 }
    2272 return SCIP_OKAY;
    2273}
    2274
    2275
    2276/** variable rounding lock method of constraint handler */
    2277static
    2278SCIP_DECL_CONSLOCK(consLockOrbitopePP)
    2279{ /*lint --e{715}*/
    2280 SCIP_CONSDATA* consdata;
    2281 SCIP_VAR*** vars;
    2282 int i;
    2283 int j;
    2284 int nrows;
    2285 int ncols;
    2286
    2287 assert( scip != NULL );
    2288 assert( conshdlr != NULL );
    2289 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2290 assert( cons != NULL );
    2291 assert( locktype == SCIP_LOCKTYPE_MODEL );
    2292
    2293 consdata = SCIPconsGetData(cons);
    2294 assert( consdata != NULL );
    2295 assert( consdata->nrows > 0 );
    2296 assert( consdata->ncols > 0 );
    2297 assert( consdata->vars != NULL );
    2298
    2299 SCIPdebugMsg(scip, "Locking method for packing/partitioning orbitope constraint handler\n");
    2300
    2301 nrows = consdata->nrows;
    2302 ncols = consdata->ncols;
    2303 vars = consdata->vars;
    2304
    2305 /* add up locks and down locks on each variable */
    2306 for (i = 0; i < nrows; ++i)
    2307 {
    2308 for (j = 0; j < ncols; ++j)
    2309 SCIP_CALL( SCIPaddVarLocksType(scip, vars[i][j], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    2310 }
    2311
    2312 return SCIP_OKAY;
    2313}
    2314
    2315
    2316/** constraint display method of constraint handler */
    2317static
    2318SCIP_DECL_CONSPRINT(consPrintOrbitopePP)
    2319{
    2320 SCIP_CONSDATA* consdata;
    2321 SCIP_VAR*** vars;
    2322 int i;
    2323 int j;
    2324 int nrows;
    2325 int ncols;
    2326 SCIP_ORBITOPETYPE orbitopetype;
    2327
    2328 assert( scip != NULL );
    2329 assert( conshdlr != NULL );
    2330 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
    2331 assert( cons != NULL );
    2332
    2333 consdata = SCIPconsGetData(cons);
    2334 assert( consdata != NULL );
    2335 assert( consdata->nrows > 0 );
    2336 assert( consdata->ncols > 0 );
    2337 assert( consdata->vars != NULL );
    2338
    2339 nrows = consdata->nrows;
    2340 ncols = consdata->ncols;
    2341 vars = consdata->vars;
    2342 orbitopetype = consdata->orbitopetype;
    2343
    2344 SCIPdebugMsg(scip, "Printing method for packing/partitioning orbitope constraint handler\n");
    2345
    2346 switch ( orbitopetype )
    2347 {
    2349 SCIPinfoMessage(scip, file, "partOrbitope(");
    2350 break;
    2352 SCIPinfoMessage(scip, file, "packOrbitope(");
    2353 break;
    2354 default:
    2355 SCIPABORT();
    2356 } /*lint !e788*/
    2357
    2358 for (i = 0; i < nrows; ++i)
    2359 {
    2360 for (j = 0; j < ncols; ++j)
    2361 {
    2362 if ( j > 0 )
    2363 SCIPinfoMessage(scip, file, ",");
    2364 SCIP_CALL( SCIPwriteVarName(scip, file, vars[i][j], TRUE) );
    2365 }
    2366 if ( i < nrows-1 )
    2367 SCIPinfoMessage(scip, file, ".");
    2368 }
    2369 SCIPinfoMessage(scip, file, ")");
    2370
    2371 return SCIP_OKAY;
    2372}
    2373
    2374
    2375/** constraint copying method of constraint handler */
    2376static
    2377SCIP_DECL_CONSCOPY(consCopyOrbitopePP)
    2378{
    2379 SCIP_CONSHDLRDATA* conshdlrdata;
    2380 SCIP_CONSDATA* sourcedata;
    2381 SCIP_VAR*** sourcevars;
    2382 SCIP_VAR*** vars;
    2383 int nrows;
    2384 int ncols;
    2385 int i;
    2386 int k;
    2387 int j;
    2388
    2389 assert( scip != NULL );
    2390 assert( cons != NULL );
    2391 assert( sourcescip != NULL );
    2392 assert( sourceconshdlr != NULL );
    2393 assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
    2394 assert( sourcecons != NULL );
    2395 assert( varmap != NULL );
    2396 assert( valid != NULL );
    2397
    2398 *valid = TRUE;
    2399
    2400 SCIPdebugMsg(scip, "Copying method for packing/partOrbitope orbitope constraint handler.\n");
    2401
    2402 sourcedata = SCIPconsGetData(sourcecons);
    2403 assert( sourcedata != NULL );
    2404 assert( sourcedata->nrows > 0 );
    2405 assert( sourcedata->ncols > 0 );
    2406 assert( sourcedata->vars != NULL );
    2407
    2408 conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
    2409 assert( conshdlrdata != NULL );
    2410
    2411 /* do not copy non-model constraints */
    2412 if ( !sourcedata->ismodelcons && !conshdlrdata->forceconscopy )
    2413 {
    2414 *valid = FALSE;
    2415
    2416 return SCIP_OKAY;
    2417 }
    2418
    2419 nrows = sourcedata->nrows;
    2420 ncols = sourcedata->ncols;
    2421 sourcevars = sourcedata->vars;
    2422
    2423 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nrows) );
    2424 for (i = 0; i < nrows && *valid; ++i)
    2425 {
    2426 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), ncols) ); /*lint !e866*/
    2427
    2428 for (j = 0; j < ncols && *valid; ++j)
    2429 {
    2430 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &(vars[i][j]), varmap, consmap, global, valid) );
    2431 assert( !(*valid) || vars[i][j] != NULL );
    2432 }
    2433 }
    2434
    2435 /* only create the target constraint, if all variables could be copied */
    2436 if ( *valid )
    2437 {
    2438 /* create copied constraint */
    2439 if ( name == NULL )
    2440 name = SCIPconsGetName(sourcecons);
    2441
    2442 SCIP_CALL( SCIPcreateConsOrbitopePP(scip, cons, name, vars,
    2443 sourcedata->orbitopetype, nrows, ncols, sourcedata->resolveprop, sourcedata->ismodelcons,
    2444 initial, separate, enforce, check, propagate,
    2445 local, modifiable, dynamic, removable, stickingatnode) );
    2446 }
    2447
    2448 /* free space; only up to row i if copying failed */
    2449 assert( 0 <= i && i <= nrows );
    2450 for (k = i - 1; k >= 0; --k)
    2451 SCIPfreeBufferArray(scip, &vars[k]);
    2452 SCIPfreeBufferArray(scip, &vars);
    2453
    2454 return SCIP_OKAY;
    2455}
    2456
    2457
    2458/** constraint parsing method of constraint handler */
    2459static
    2460SCIP_DECL_CONSPARSE(consParseOrbitopePP)
    2461{ /*lint --e{715}*/
    2462 const char* s;
    2463 char* endptr;
    2464 SCIP_ORBITOPETYPE orbitopetype;
    2465 SCIP_VAR*** vars;
    2466 SCIP_VAR* var;
    2467 int nrows;
    2468 int maxnrows;
    2469 int ncols;
    2470 int maxncols;
    2471 int k;
    2472 int j;
    2473
    2474 assert( success != NULL );
    2475
    2476 *success = TRUE;
    2477 s = str;
    2478
    2479 /* skip white space */
    2480 SCIP_CALL( SCIPskipSpace((char**)&s) );
    2481
    2482 if( strncmp(s, "partOrbitope(", 13) == 0 )
    2483 orbitopetype = SCIP_ORBITOPETYPE_PARTITIONING;
    2484 else
    2485 {
    2486 if( strncmp(s, "packOrbitope(", 13) != 0 )
    2487 {
    2488 SCIPerrorMessage("Syntax error - expected \"partOrbitope\" or \"packOrbitope\": %s\n", s);
    2489 *success = FALSE;
    2490 return SCIP_OKAY;
    2491 }
    2492 orbitopetype = SCIP_ORBITOPETYPE_PACKING;
    2493 }
    2494 s += 13;
    2495
    2496 /* loop through string */
    2497 nrows = 0;
    2498 ncols = 0;
    2499 maxnrows = 10;
    2500 maxncols = 10;
    2501
    2502 SCIP_CALL( SCIPallocBufferArray(scip, &vars, maxnrows) );
    2503
    2504 j = 0;
    2505 do
    2506 {
    2507 /* parse variable name */
    2508 SCIP_CALL( SCIPparseVarName(scip, s, &var, &endptr) );
    2509
    2510 if( var == NULL )
    2511 {
    2512 endptr = strchr(endptr, ')');
    2513
    2514 if( endptr == NULL || j > 0 )
    2515 {
    2516 SCIPerrorMessage("not enough variables.\n");
    2517 *success = FALSE;
    2518 }
    2519
    2520 break;
    2521 }
    2522
    2523 s = endptr;
    2524 assert( s != NULL );
    2525
    2526 /* skip white space */
    2527 SCIP_CALL( SCIPskipSpace((char**)&s) );
    2528
    2529 /* begin new row if required */
    2530 if( j == 0 )
    2531 {
    2532 ++nrows;
    2533
    2534 if( nrows > maxnrows )
    2535 {
    2536 maxnrows = SCIPcalcMemGrowSize(scip, nrows);
    2537 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, maxnrows) );
    2538 assert( nrows <= maxnrows );
    2539 }
    2540
    2541 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[nrows-1]), nrows == 1 ? maxncols : ncols) ); /*lint !e866*/
    2542 }
    2543
    2544 /* determine number of columns */
    2545 if( nrows == 1 )
    2546 {
    2547 ncols = j + 1;
    2548
    2549 if( *s == '.' || *s == ')' )
    2550 SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nrows-1]), ncols) ); /*lint !e866*/
    2551 else if( ncols > maxncols )
    2552 {
    2553 maxncols = SCIPcalcMemGrowSize(scip, ncols);
    2554 SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nrows-1]), maxncols) ); /*lint !e866*/
    2555 assert( ncols <= maxncols );
    2556 }
    2557 }
    2558 else if( ( j < ncols-1 ) == ( *s == '.' || *s == ')' ) )
    2559 {
    2560 SCIPerrorMessage("variables per row do not match.\n");
    2561 *success = FALSE;
    2562 break;
    2563 }
    2564
    2565 vars[nrows-1][j] = var;
    2566
    2567 if( *s == '.' )
    2568 j = 0;
    2569 else
    2570 ++j;
    2571
    2572 /* skip ',' or '.' */
    2573 if( *s == ',' || *s == '.' )
    2574 ++s;
    2575 }
    2576 while( *s != ')' );
    2577
    2578 if( *success )
    2579 {
    2580 SCIP_CALL( SCIPcreateConsOrbitopePP(scip, cons, name, vars, orbitopetype, nrows, ncols, TRUE, TRUE,
    2581 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    2582 }
    2583
    2584 for( k = nrows - 1; k >= 0; --k )
    2585 SCIPfreeBufferArray(scip, &vars[k]);
    2586 SCIPfreeBufferArray(scip, &vars);
    2587
    2588 return SCIP_OKAY;
    2589}
    2590
    2591
    2592/** constraint method of constraint handler which returns the variables (if possible) */
    2593static
    2594SCIP_DECL_CONSGETVARS(consGetVarsOrbitopePP)
    2595{ /*lint --e{715}*/
    2596 SCIP_CONSDATA* consdata;
    2597
    2598 assert( cons != NULL );
    2599 assert( success != NULL );
    2600 assert( vars != NULL );
    2601
    2602 consdata = SCIPconsGetData(cons);
    2603 assert( consdata != NULL );
    2604
    2605 if ( varssize < consdata->ncols * consdata->nrows )
    2606 *success = FALSE;
    2607 else
    2608 {
    2609 int cnt = 0;
    2610 int i;
    2611 int j;
    2612
    2613 for (i = 0; i < consdata->nrows; ++i)
    2614 {
    2615 for (j = 0; j < consdata->ncols; ++j)
    2616 vars[cnt++] = consdata->vars[i][j];
    2617 }
    2618 *success = TRUE;
    2619 }
    2620
    2621 return SCIP_OKAY;
    2622}
    2623
    2624
    2625/** constraint method of constraint handler which returns the number of variables (if possible) */
    2626static
    2627SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitopePP)
    2628{ /*lint --e{715}*/
    2629 SCIP_CONSDATA* consdata;
    2630
    2631 assert( cons != NULL );
    2632
    2633 consdata = SCIPconsGetData(cons);
    2634 assert( consdata != NULL );
    2635
    2636 *nvars = consdata->ncols * consdata->nrows;
    2637 *success = TRUE;
    2638
    2639 return SCIP_OKAY;
    2640}
    2641
    2642
    2643/*
    2644 * constraint specific interface methods
    2645 */
    2646
    2647/** creates the handler for packing/partitioning orbitope constraints and includes it in SCIP */
    2649 SCIP* scip /**< SCIP data structure */
    2650 )
    2651{
    2652 SCIP_CONSHDLRDATA* conshdlrdata;
    2653 SCIP_CONSHDLR* conshdlr;
    2654
    2655 /* create orbitope constraint handler data */
    2656 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
    2657
    2658 /* include constraint handler */
    2662 consEnfolpOrbitopePP, consEnfopsOrbitopePP, consCheckOrbitopePP, consLockOrbitopePP,
    2663 conshdlrdata) );
    2664 assert(conshdlr != NULL);
    2665
    2666 /* set non-fundamental callbacks via specific setter functions */
    2667 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbitopePP, consCopyOrbitopePP) );
    2668 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrbitopePP) );
    2669 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbitopePP) );
    2670 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbitopePP) );
    2671 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbitopePP) );
    2672 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOrbitopePP) );
    2674 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreOrbitopePP) );
    2675 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbitopePP) );
    2678 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbitopePP) );
    2679 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbitopePP, consSepasolOrbitopePP, CONSHDLR_SEPAFREQ,
    2681 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbitopePP) );
    2682 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOrbitopePP) );
    2683
    2684 SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/forceconscopy",
    2685 "Whether orbitope constraints should be forced to be copied to sub SCIPs.",
    2686 &conshdlrdata->forceconscopy, TRUE, DEFAULT_FORCECONSCOPY, NULL, NULL) );
    2687
    2688 return SCIP_OKAY;
    2689}
    2690
    2691
    2692/** creates and captures a packing/partitioning orbitope constraint
    2693 *
    2694 * @pre This constraint handler assumes that constraints which enforce the packing/partitioning constraints are
    2695 * contained in the problem. It does not implement, e.g., separation and propagation of set packing/partitioning
    2696 * constraints, since this would just copy large parts of the code of the setppc constraint handler.
    2697 *
    2698 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    2699 */
    2701 SCIP* scip, /**< SCIP data structure */
    2702 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    2703 const char* name, /**< name of constraint */
    2704 SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
    2705 SCIP_ORBITOPETYPE orbitopetype, /**< type of orbitope constraint */
    2706 int nrows, /**< number of rows in orbitope matrix <=> p */
    2707 int ncols, /**< number of columns in orbitope matrix <=> q */
    2708 SCIP_Bool resolveprop, /**< should propagation be resolved? */
    2709 SCIP_Bool ismodelcons, /**< whether the orbitope is a model constraint */
    2710 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    2711 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    2712 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    2713 * Usually set to TRUE. */
    2714 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    2715 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    2716 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    2717 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    2718 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    2719 * Usually set to TRUE. */
    2720 SCIP_Bool local, /**< is constraint only valid locally?
    2721 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    2722 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    2723 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    2724 * adds coefficients to this constraint. */
    2725 SCIP_Bool dynamic, /**< is constraint subject to aging?
    2726 * Usually set to FALSE. Set to TRUE for own cuts which
    2727 * are separated as constraints. */
    2728 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    2729 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    2730 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    2731 * if it may be moved to a more global node?
    2732 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    2733 )
    2734{
    2735 SCIP_CONSHDLR* conshdlr;
    2736 SCIP_CONSDATA* consdata;
    2737
    2738 /* find the orbitope constraint handler */
    2739 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    2740 if ( conshdlr == NULL )
    2741 {
    2742 SCIPerrorMessage("packing/partitioning orbitope constraint handler not found\n");
    2743 return SCIP_PLUGINNOTFOUND;
    2744 }
    2745 assert( nrows > 0 );
    2746 assert( ncols > 0 );
    2747
    2748 /* run some checks */
    2749#ifndef NDEBUG
    2750 {
    2751 SCIP_Real obj;
    2752 int i;
    2753 int j;
    2754 for (i = 0; i < nrows; ++i)
    2755 {
    2756 /* initialize obj to infinity */
    2757 obj = SCIPinfinity(scip);
    2758 for (j = 0; j < ncols; ++j)
    2759 {
    2760 SCIP_Bool fixedZero;
    2761 SCIP_VAR* var;
    2762
    2763 var = vars[i][j];
    2764 assert(var != NULL);
    2765
    2766 if ( SCIPvarIsNegated(var) )
    2767 var = SCIPvarGetNegatedVar(var);
    2768
    2769 /* all variables need to be binary */
    2770 assert( SCIPvarIsBinary(var) );
    2771
    2772 /* fixed variables have obj = 0; for variables fixed to 0, we assume that there is no
    2773 problem (but we cannot always check it, e.g., when in the original problem
    2774 variables were fixed and this problem was copied.) */
    2775 fixedZero = ( SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisZero(scip, SCIPvarGetUbGlobal(var)) );
    2776
    2777 /* @todo adapt correctness of the following check for sub-scips */
    2778 if ( SCIPgetSubscipDepth(scip) == 0 )
    2779 {
    2780 /* check whether all variables in a row have the same objective */
    2781 if ( ! fixedZero && SCIPisInfinity(scip, obj) )
    2782 obj = SCIPvarGetObj(var);
    2783 else
    2784 {
    2785 assert( fixedZero || ! SCIPvarIsActive(var) || SCIPisEQ(scip, obj, SCIPvarGetObj(var)) );
    2786 }
    2787 }
    2788 }
    2789 }
    2790 }
    2791#endif
    2792
    2793 /* create constraint data */
    2794 SCIP_CALL( consdataCreate(scip, &consdata, vars, nrows, ncols, orbitopetype, resolveprop, ismodelcons) );
    2795
    2796 /* create constraint */
    2797 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    2798 local, modifiable, dynamic, removable, stickingatnode) );
    2799
    2800 return SCIP_OKAY;
    2801}
    2802
    2803/** creates and captures a packing/partitioning orbitope constraint in its most basic variant, i. e., with all
    2804 * constraint flags set to their default values, which can be set afterwards using SCIPsetConsFLAGNAME()
    2805 *
    2806 * @see SCIPcreateConsOrbitopePP() for the default constraint flag configuration
    2807 *
    2808 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
    2809 */
    2811 SCIP* scip, /**< SCIP data structure */
    2812 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    2813 const char* name, /**< name of constraint */
    2814 SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
    2815 SCIP_ORBITOPETYPE orbitopetype, /**< type of orbitope constraint */
    2816 int nrows, /**< number of rows in orbitope matrix <=> p */
    2817 int ncols, /**< number of columns in orbitope matrix <=> q */
    2818 SCIP_Bool resolveprop, /**< should propagation be resolved? */
    2819 SCIP_Bool ismodelcons /**< whether the orbitope is a model constraint */
    2820 )
    2821{
    2822 SCIP_CALL( SCIPcreateConsOrbitopePP(scip, cons, name, vars, orbitopetype, nrows, ncols,
    2823 resolveprop, ismodelcons, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
    2824
    2825 return SCIP_OKAY;
    2826}
    static SCIP_RETCODE checkRedundantCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *redundant)
    static SCIP_RETCODE replaceAggregatedVarsOrbitopePP(SCIP *scip, SCIP_CONS *cons)
    #define CONSHDLR_NEEDSCONS
    static SCIP_DECL_CONSENFORELAX(consEnforelaxOrbitopePP)
    #define CONSHDLR_SEPAFREQ
    #define CONSHDLR_CHECKPRIORITY
    #define CONSHDLR_DESC
    static SCIP_RETCODE enfopsPackingPartitioningOrbitopeSolution(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result)
    static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, int inferinfo, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
    static SCIP_RETCODE separateConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result, SCIP_Bool enforce)
    static SCIP_RETCODE checkPackingPartitioningOrbitopeSolution(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_RESULT *result, SCIP_Bool printreason)
    #define CONSHDLR_PROP_TIMING
    static SCIP_DECL_CONSPROP(consPropOrbitopePP)
    static SCIP_RETCODE separateSCIs(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *infeasible, int *nfixedvars, int *ncuts)
    #define DEFAULT_FORCECONSCOPY
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_DECL_CONSCHECK(consCheckOrbitopePP)
    #define CONSHDLR_SEPAPRIORITY
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *nfixedvars)
    static SCIP_DECL_CONSLOCK(consLockOrbitopePP)
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitopePP)
    static SCIP_DECL_CONSRESPROP(consRespropOrbitopePP)
    static SCIP_DECL_CONSPRESOL(consPresolOrbitopePP)
    static SCIP_DECL_CONSSEPALP(consSepalpOrbitopePP)
    static SCIP_DECL_CONSTRANS(consTransOrbitopePP)
    static SCIP_DECL_CONSDELETE(consDeleteOrbitopePP)
    static SCIP_DECL_CONSEXITPRE(consExitpreOrbitopePP)
    static SCIP_DECL_CONSSEPASOL(consSepasolOrbitopePP)
    static SCIP_DECL_CONSGETVARS(consGetVarsOrbitopePP)
    static SCIP_DECL_CONSCOPY(consCopyOrbitopePP)
    #define CONSHDLR_PROPFREQ
    static void computeSCTable(SCIP *scip, int nrows, int ncols, SCIP_Real **weights, int **cases, SCIP_Real **vals)
    static SCIP_DECL_CONSPARSE(consParseOrbitopePP)
    static SCIP_DECL_CONSFREE(consFreeOrbitopePP)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitopePP)
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
    #define CONSHDLR_EAGERFREQ
    static SCIP_DECL_CONSENFOPS(consEnfopsOrbitopePP)
    #define CONSHDLR_ENFOPRIORITY
    static SCIP_RETCODE fixTriangle(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *nfixedvars)
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR ***vars, int nrows, int ncols, SCIP_ORBITOPETYPE orbitopetype, SCIP_Bool resolveprop, SCIP_Bool ismodelcons)
    #define CONSHDLR_DELAYSEPA
    static void copyValues(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
    #define CONSHDLR_NAME
    static SCIP_DECL_CONSENFOLP(consEnfolpOrbitopePP)
    #define CONSHDLR_DELAYPROP
    static SCIP_DECL_CONSPRINT(consPrintOrbitopePP)
    constraint handler for partitioning/packing orbitope constraints w.r.t. the full symmetric group
    Constraint handler for the set partitioning / packing / covering constraints .
    #define NULL
    Definition: def.h:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_UNUSED(x)
    Definition: def.h:409
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPcreateConsOrbitopePP(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_ORBITOPETYPE orbitopetype, int nrows, int ncols, SCIP_Bool resolveprop, SCIP_Bool ismodelcons, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPcreateConsBasicOrbitopePP(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_ORBITOPETYPE orbitopetype, int nrows, int ncols, SCIP_Bool resolveprop, SCIP_Bool ismodelcons)
    SCIP_RETCODE SCIPincludeConshdlrOrbitopePP(SCIP *scip)
    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
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    int SCIPgetNLPBranchCands(SCIP *scip)
    Definition: scip_branch.c:436
    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_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
    SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
    Definition: scip_cons.c:831
    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
    SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
    Definition: scip_cons.c:372
    SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
    Definition: scip_cons.c:323
    const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4316
    SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
    Definition: scip_cons.c:516
    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_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4336
    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 SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
    Definition: scip_cons.c:854
    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_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8588
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8578
    SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
    Definition: cons.c:8450
    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
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #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 SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    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 SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_lp.c:1672
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisSumEQ(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 SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
    Definition: var.c:23868
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
    Definition: scip_var.c:728
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    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_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
    Definition: var.c:23443
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:11057
    SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
    Definition: scip_var.c:10318
    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 SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
    Definition: scip_var.c:2236
    SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
    Definition: scip_var.c:2078
    SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:1853
    SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
    Definition: scip_var.c:10984
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    memory allocation routines
    public methods for managing constraints
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public methods for problem variables
    SCIP callable library.
    public methods for branching rule plugins and branching
    public methods for conflict handler plugins and conflict analysis
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for cuts and aggregation rows
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    public methods for SCIP variables
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1221
    methods for handling symmetries
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    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
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ 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_STAGE_SOLVING
    Definition: type_set.h:53
    @ SCIP_STAGE_TRANSFORMING
    Definition: type_set.h:46
    type definitions for symmetry computations
    @ SCIP_ORBITOPETYPE_PACKING
    @ SCIP_ORBITOPETYPE_PARTITIONING
    enum SCIP_OrbitopeType SCIP_ORBITOPETYPE
    @ SCIP_VARSTATUS_FIXED
    Definition: type_var.h:54
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    @ SCIP_VARSTATUS_NEGATED
    Definition: type_var.h:57
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141