SCIP

    Solving Constraint Integer Programs

    cons_optcumulative.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file cons_optcumulative.c
    26 * @ingroup CONSHDLRS
    27 * @brief constraint handler for cumulative constraints with optional activities
    28 * @author Chris Beck
    29 * @author Stefan Heinz
    30 *
    31 * Given a set of jobs \f$J\f$. Each job~\f$j\f$ has a binary variables \f$x_j\f$ which is one if this job is scheduled
    32 * on that machine (otherwise it is zero), an integer start time variables \f$S_j\f$, a processing time \f$p_j\f$, and a
    33 * demands \f$d_j\f$. Besides that an integer resource capacity \f$C\f$.
    34 *
    35 * The optcumulative enforces the cumulative conditions for those jobs which are assigned to that machine. Let \f$J'\f$
    36 * be the subset of jobs assigned to that optcumulative constraint, then the cumulative constraint ensures that for
    37 * each point in time \f$t\f$ \f$\sum_{j\in J': S_j \leq t < S_j + p_j} d_j \leq C\f$ holds.
    38 *
    39 *
    40 * Propagation:
    41 *
    42 *
    43 * LP Relaxation:
    44 *
    45 * - let est(J) the earliest start time of all jobs of set \f$J\f$ and lct(J) the latest completion time for all jobs of
    46 * set \f$J\f$, then the following linear constraint has to hold
    47 * \f$\sum_{j\in J} p_j \cdot d_j \leq (lct(J) - est(J)) \cdot C\f$
    48 *
    49 */
    50
    51/*
    52 * @todo Find subsets \f$J'\f$ of jobs which are together not schedulable and create knapsack constraint
    53 * \f$\sum_{j\in J'} p_j \cdot d_j \leq (lct(J') - est(J')) \cdot C\f$
    54 * @todo Use a rectangle relaxation to determine if jobs which run in a certain interval can be packed feasible. this
    55 * relaxation ignores the actual start and end time of a job.
    56 * @todo Adjust relaxation after jobs are removed during search
    57 *
    58 */
    59
    60
    61/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    62
    63#include "cons_optcumulative.h"
    64
    66#include "scip/cons_knapsack.h"
    67#include "scip/scipdefplugins.h"
    68
    69/**@name Constraint handler properties
    70 *
    71 * @{
    72 */
    73
    74/* constraint handler properties */
    75#define CONSHDLR_NAME "optcumulative"
    76#define CONSHDLR_DESC "constraint handler for cumulative constraints with optional activities"
    77#define CONSHDLR_SEPAPRIORITY 0 /**< priority of the constraint handler for separation */
    78#define CONSHDLR_ENFOPRIORITY -2060000 /**< priority of the constraint handler for constraint enforcing */
    79#define CONSHDLR_CHECKPRIORITY -3100000 /**< priority of the constraint handler for checking feasibility */
    80#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
    81#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
    82#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
    83 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
    84#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
    85#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
    86#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
    87#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
    88
    89#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
    90#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM
    91
    92/**@} */
    93
    94/**@name Event handler properties
    95 *
    96 * @{
    97 */
    98
    99#define EVENTHDLR_BINVARS_NAME "optcumulativebinvars"
    100#define EVENTHDLR_BINVARS_DESC "bound change event handler for binary variables of optcumulative constraints"
    101
    102#define EVENTHDLR_INTVARS_NAME "optcumulativeintvars"
    103#define EVENTHDLR_INTVARS_DESC "bound change event handler for integer variables of optcumulative constraints"
    104
    105/**@} */
    106
    107/**@name Default parameter values
    108 *
    109 * @{
    110 */
    111
    112#define DEFAULT_ROWRELAX FALSE /**< add linear relaxation as LP row (otherwise a knapsack constraint is created)? */
    113#define DEFAULT_CONFLICTANALYSIS TRUE /**< participate in conflict analysis?" */
    114#define DEFAULT_INTERVALRELAX TRUE /**< create a relaxation for each start and end time point interval */
    115
    116/**@} */
    117
    118
    119/*
    120 * Data structures
    121 */
    122
    123/** constraint data for optcumulative constraints */
    124struct SCIP_ConsData
    125{
    126 SCIP_VAR** vars; /**< array of variable representing the start time of each job */
    127 SCIP_VAR** binvars; /**< array of variable representing if the job has to be processed on this machine */
    128 SCIP_Bool* downlocks; /**< array to store if the start time variable has a down lock */
    129 SCIP_Bool* uplocks; /**< array to store if the start time variable has an up lock */
    130 SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
    131 SCIP_CONS* cons; /**< knapsack relaxation, if created */
    132 int* demands; /**< array containing corresponding demands */
    133 int* durations; /**< array containing corresponding durations */
    134 int nvars; /**< number of variables */
    135 int varssize; /**< number of available slots in variable arrays */
    136 int capacity; /**< available cumulative capacity */
    137
    138 int hmin; /**< left bound of time axis to be considered (including hmin) */
    139 int hmax; /**< right bound of time axis to be considered (not including hmax) */
    140
    141 int nglbfixedzeros; /**< number of binary variable globally fixed to zero */
    142 int nglbfixedones; /**< number of binary variable globally fixed to one */
    143 int nfixedzeros; /**< number of binary variable fixed to zero */
    144 int nfixedones; /**< number of binary variable fixed to one */
    145 int est; /**< used earliest start time for the relaxation */
    146 int lct; /**< used latest completion time for the relaxation */
    147 unsigned int propagated:1; /**< is constraint already propagated? */
    148 unsigned int relaxadded:1; /**< was relaxation added? */
    149 unsigned int triedsolving:1; /**< bool to store if it was tried to solve the cumulative sub-problem */
    150 unsigned int normalized:1; /**< is the constraint normalized */
    151 unsigned int triedredundant:1; /**< bool to store if the redundancy check was applied */
    152};
    153
    154/** constraint handler data */
    155struct SCIP_ConshdlrData
    156{
    157 SCIP_EVENTHDLR* eventhdlrbinvars; /**< event handler for bound change events on binary variables */
    158 SCIP_EVENTHDLR* eventhdlrintvars; /**< event handler for bound change events on integer variables */
    159 SCIP_HEUR* heurtrysol; /**< trysol heuristic */
    160 SCIP_Bool rowrelax; /**< add linear relaxation as LP row (otherwise a knapsack constraint is created)? */
    161 SCIP_Bool conflictanalysis; /**< participate in conflict analysis? */
    162 SCIP_Bool intervalrelax; /**< create a relaxation for each start and end time point interval */
    163};
    164
    165/**@name Debug Methods
    166 *
    167 * @{
    168 */
    169
    170#ifndef NDEBUG
    171/** check constraint state (nglbfixedones and nglbfixedzeros) */
    172static
    174 SCIP_CONSDATA* consdata /**< optcumulative constraint data */
    175 )
    176{
    177 int nglbfixedones;
    178 int nglbfixedzeors;
    179 int nfixedones;
    180 int nfixedzeors;
    181 int v;
    182
    183 nglbfixedones = 0;
    184 nglbfixedzeors = 0;
    185 nfixedones = 0;
    186 nfixedzeors = 0;
    187
    188 for( v = 0; v < consdata->nvars; ++v )
    189 {
    190 if( SCIPvarGetLbGlobal(consdata->binvars[v]) > 0.5 )
    191 nglbfixedones++;
    192
    193 if( SCIPvarGetUbGlobal(consdata->binvars[v]) < 0.5 )
    194 nglbfixedzeors++;
    195
    196 if( SCIPvarGetLbLocal(consdata->binvars[v]) > 0.5 )
    197 nfixedones++;
    198
    199 if( SCIPvarGetUbLocal(consdata->binvars[v]) < 0.5 )
    200 nfixedzeors++;
    201 }
    202
    203 assert(nglbfixedones == consdata->nglbfixedones);
    204 assert(nglbfixedzeors == consdata->nglbfixedzeros);
    205 assert(nfixedones == consdata->nfixedones);
    206 assert(nfixedzeors == consdata->nfixedzeros);
    207}
    208#else
    209#define checkCounters(x) /* */
    210#endif
    211
    212/**@} */
    213
    214/**@name Miscellaneous Methods
    215 *
    216 * @{
    217 */
    218
    219#ifndef NDEBUG
    220/** converts the given double bound which is integral to an int; in optimized mode the function gets inlined for
    221 * performance; in debug mode we check some additional conditions
    222 */
    223static
    225 SCIP* scip, /**< SCIP data structure */
    226 SCIP_Real bound /**< double bound to convert */
    227 )
    228{
    229 assert(SCIPisIntegral(scip, bound));
    230 assert(SCIPisEQ(scip, bound, (SCIP_Real)(int)(bound + 0.5)));
    231
    232 return (int)(bound + 0.5);
    233}
    234#else
    235#define convertBoundToInt(x, y) ((int)((y) + 0.5))
    236#endif
    237
    238/**@} */
    239
    240/**@name Constraint data methods
    241 *
    242 * @{
    243 */
    244
    245/** creates constraint data of optcumulative constraint */
    246static
    248 SCIP* scip, /**< SCIP data structure */
    249 SCIP_CONSDATA** consdata, /**< pointer to consdata */
    250 int nvars, /**< number of variables */
    251 SCIP_VAR** vars, /**< array of integer variables */
    252 SCIP_VAR** binvars, /**< array of variable representing if the job has to be processed on this machine */
    253 int* durations, /**< array containing corresponding durations */
    254 int* demands, /**< array containing corresponding demands */
    255 int capacity, /**< available cumulative capacity */
    256 SCIP_Bool check /**< is the corresponding constraint a check constraint */
    257 )
    258{
    259 assert(scip != NULL);
    260 assert(consdata != NULL);
    261 assert(vars != NULL || nvars > 0);
    262 assert(binvars != NULL || nvars > 0);
    263 assert(demands != NULL);
    264 assert(durations != NULL);
    265 assert(capacity >= 0);
    266
    267 /* create constraint data */
    268 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
    269
    270 (*consdata)->capacity = capacity;
    271 (*consdata)->nvars = nvars;
    272 (*consdata)->varssize = nvars;
    273 (*consdata)->hmin = 0;
    274 (*consdata)->hmax = INT_MAX;
    275 (*consdata)->nglbfixedzeros = 0;
    276 (*consdata)->est = -1;
    277 (*consdata)->lct = INT_MAX;
    278 (*consdata)->row = NULL;
    279 (*consdata)->cons = NULL;
    280 (*consdata)->nglbfixedzeros = 0;
    281 (*consdata)->nglbfixedones = 0;
    282 (*consdata)->nfixedzeros = 0;
    283 (*consdata)->nfixedones = 0;
    284 (*consdata)->propagated = FALSE;
    285 (*consdata)->relaxadded = FALSE;
    286 (*consdata)->triedsolving = FALSE;
    287 (*consdata)->normalized = FALSE;
    288 (*consdata)->triedredundant = FALSE;
    289
    290 if( nvars > 0 )
    291 {
    292 int v;
    293
    294 assert(vars != NULL); /* for flexelint */
    295 assert(binvars != NULL); /* for flexelint */
    296
    297 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
    298 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->binvars, binvars, nvars) );
    299 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->downlocks, demands, nvars) );
    300 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->uplocks, demands, nvars) );
    301 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->demands, demands, nvars) );
    302 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->durations, durations, nvars) );
    303
    304 /* initialize locking arrays */
    305 for( v = 0; v < nvars; ++v )
    306 {
    307 /* the locks are only used if the contraint is a check constraint */
    308 (*consdata)->downlocks[v] = check;
    309 (*consdata)->uplocks[v] = check;
    310 }
    311
    312 /* transform variables, if they are not yet transformed */
    314 {
    315 SCIPdebugMessage("get tranformed variables and constraints\n");
    316
    317 /* get transformed variables and do NOT captures these */
    318 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
    319 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->binvars, (*consdata)->binvars) );
    320
    321 for( v = 0; v < nvars; ++v )
    322 {
    323 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[v]) );
    324 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->binvars[v]) );
    325 }
    326 }
    327 }
    328 else
    329 {
    330 (*consdata)->vars = NULL;
    331 (*consdata)->binvars = NULL;
    332 (*consdata)->downlocks = NULL;
    333 (*consdata)->uplocks = NULL;
    334 (*consdata)->demands = NULL;
    335 (*consdata)->durations = NULL;
    336 }
    337
    338 return SCIP_OKAY;
    339}
    340
    341
    342/** frees a optcumulative constraint data */
    343static
    345 SCIP* scip, /**< SCIP data structure */
    346 SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
    347 )
    348{
    349 int varssize;
    350
    351 assert(consdata != NULL);
    352 assert(*consdata != NULL);
    353
    354 /* release the row */
    355 if( (*consdata)->row != NULL )
    356 {
    357 SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
    358 }
    359
    360 /* release the row */
    361 if( (*consdata)->cons != NULL )
    362 {
    363 SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->cons) );
    364 }
    365
    366 varssize = (*consdata)->varssize;
    367
    368 if( varssize > 0 )
    369 {
    370 /* free arrays */
    371 SCIPfreeBlockMemoryArray(scip, &(*consdata)->durations, varssize);
    372 SCIPfreeBlockMemoryArray(scip, &(*consdata)->demands, varssize);
    373 SCIPfreeBlockMemoryArray(scip, &(*consdata)->uplocks, varssize);
    374 SCIPfreeBlockMemoryArray(scip, &(*consdata)->downlocks, varssize);
    375 SCIPfreeBlockMemoryArray(scip, &(*consdata)->binvars, varssize);
    376 SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, varssize);
    377 }
    378
    379 /* free memory */
    380 SCIPfreeBlockMemory(scip, consdata);
    381
    382 return SCIP_OKAY;
    383}
    384
    385/** prints optcumulative constraint to file stream */
    386static
    388 SCIP* scip, /**< SCIP data structure */
    389 SCIP_CONSDATA* consdata, /**< optcumulative constraint data */
    390 FILE* file /**< output file (or NULL for standard output) */
    391 )
    392{
    393 int v;
    394
    395 assert(consdata != NULL);
    396
    397 SCIPinfoMessage( scip, file, "optcumulative(");
    398
    399 for( v = 0; v < consdata->nvars; ++v )
    400 {
    401 assert(consdata->vars[v] != NULL);
    402 if( v > 0 )
    403 SCIPinfoMessage(scip, file, ", ");
    404
    405 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], FALSE) );
    406
    407 SCIPinfoMessage(scip, file, "[%g,%g](%d)[%d]", SCIPvarGetLbLocal(consdata->vars[v]),
    408 SCIPvarGetUbLocal(consdata->vars[v]), consdata->durations[v], consdata->demands[v]);
    409
    410 SCIP_CALL( SCIPwriteVarName(scip, file, consdata->binvars[v], FALSE) );
    411
    412 }
    413 SCIPinfoMessage(scip, file, ")[%d,%d)<= %d", consdata->hmin, consdata->hmax, consdata->capacity);
    414
    415 return SCIP_OKAY;
    416}
    417
    418/**@} */
    419
    420/**@name Constraint handler data
    421 *
    422 * Method used to create and free the constraint handler data when including and removing the cumulative constraint
    423 * handler.
    424 *
    425 * @{
    426 */
    427
    428/** creates constaint handler data for set partitioning / packing / covering constraint handler */
    429static
    431 SCIP* scip, /**< SCIP data structure */
    432 SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
    433 SCIP_EVENTHDLR* eventhdlrbinvars, /**< used event handler for tracing bound changes on binary variables */
    434 SCIP_EVENTHDLR* eventhdlrintvars /**< used event handler for tracing bound changes on integer variables */
    435 )
    436{
    437 assert(scip != NULL);
    438 assert(conshdlrdata != NULL);
    439 assert(eventhdlrbinvars != NULL);
    440 assert(eventhdlrintvars != NULL);
    441
    442 SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
    443
    444 (*conshdlrdata)->eventhdlrbinvars = eventhdlrbinvars;
    445 (*conshdlrdata)->eventhdlrintvars = eventhdlrintvars;
    446 (*conshdlrdata)->heurtrysol = NULL;
    447
    448 return SCIP_OKAY;
    449}
    450
    451/** frees constraint handler data for set partitioning / packing / covering constraint handler */
    452static
    454 SCIP* scip, /**< SCIP data structure */
    455 SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
    456 )
    457{
    458 assert(conshdlrdata != NULL);
    459 assert(*conshdlrdata != NULL);
    460
    461 SCIPfreeBlockMemory(scip, conshdlrdata);
    462
    463 return SCIP_OKAY;
    464}
    465
    466/**@} */
    467
    468/** removes rounding locks for the given variable in the given optcumulative constraint */
    469static
    471 SCIP* scip, /**< SCIP data structure */
    472 SCIP_CONS* cons, /**< optcumulative constraint */
    473 SCIP_VAR* binvar, /**< decision variable */
    474 SCIP_VAR* var, /**< start time variable */
    475 SCIP_Bool downlock, /**< has the integer start time variable a down lock */
    476 SCIP_Bool uplock /**< has the integer start time variable an up lock */
    477 )
    478{
    479 /* rounding up may violate the constraint */
    480 SCIP_CALL( SCIPunlockVarCons(scip, binvar, cons, FALSE, TRUE) );
    481
    482 /* rounding in both directions may violate the constraint */
    483 SCIP_CALL( SCIPunlockVarCons(scip, var, cons, downlock, uplock) );
    484
    485 return SCIP_OKAY;
    486}
    487
    488/** catches events for binary variable at given position */
    489static
    491 SCIP* scip, /**< SCIP data structure */
    492 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    493 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    494 int pos /**< array position of variable to catch bound change events for */
    495 )
    496{
    497 SCIP_CONSDATA* consdata;
    498 SCIP_EVENTTYPE eventtype;
    499 SCIP_VAR* binvar;
    500
    501 consdata = SCIPconsGetData(cons);
    502 assert(consdata != NULL);
    503 assert(eventhdlr != NULL);
    504 assert(0 <= pos && pos < consdata->nvars);
    505 assert(consdata->binvars != NULL);
    506
    507 binvar = consdata->binvars[pos];
    508 assert(binvar != NULL);
    509
    510 /* we are catching the following events for the binary variables:
    511 *
    512 * - SCIP_EVENTTYPE_BOUNDRELAXED: This allows for counting locally fixed variables to one or zero
    513 * - SCIP_EVENTTYPE_GBDCHANGED: This allows to check if the optcumulative can be converted into an cumulative
    514 * constraint
    515 * - SCIP_EVENTTYPE_BOUNDRELAXED: This allows us to detect the moment when we can retry to solve a local cumulative
    516 * constraint again
    517 */
    519
    520 /* catch bound change events on variable */
    521 SCIP_CALL( SCIPcatchVarEvent(scip, binvar, eventtype, eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    522
    523 assert(consdata->nglbfixedzeros >= 0);
    524 assert(consdata->nglbfixedones >= 0);
    525
    526 /* update the globally fixed variables counter for this variable */
    527 if( SCIPvarGetUbGlobal(binvar) < 0.5)
    528 consdata->nglbfixedzeros++;
    529 else if( SCIPvarGetLbGlobal(binvar) > 0.5 )
    530 consdata->nglbfixedones++;
    531
    532 /* update the locally fixed variables counter for this variable */
    533 if( SCIPvarGetUbLocal(binvar) < 0.5)
    534 consdata->nfixedzeros++;
    535 else if( SCIPvarGetLbLocal(binvar) > 0.5 )
    536 consdata->nfixedones++;
    537
    538 assert(consdata->nglbfixedzeros + consdata->nglbfixedones <= consdata->nvars);
    539 assert(consdata->nfixedzeros + consdata->nfixedones <= consdata->nvars);
    540
    541 return SCIP_OKAY;
    542}
    543
    544/** drops events for binary variable at given position */
    545static
    547 SCIP* scip, /**< SCIP data structure */
    548 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    549 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    550 int pos /**< array position of variable to catch bound change events for */
    551 )
    552{
    553 SCIP_CONSDATA* consdata;
    554 SCIP_EVENTTYPE eventtype;
    555 SCIP_VAR* binvar;
    556
    557 consdata = SCIPconsGetData(cons);
    558 assert(consdata != NULL);
    559 assert(eventhdlr != NULL);
    560 assert(0 <= pos && pos < consdata->nvars);
    561 assert(consdata->binvars != NULL);
    562
    563 binvar = consdata->binvars[pos];
    564 assert(binvar != NULL);
    565
    567
    568 /* drop events on variable */
    569 SCIP_CALL( SCIPdropVarEvent(scip, binvar, eventtype, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    570
    571 /* update the globally fixed variables counter for this variable */
    572 if( SCIPvarGetUbGlobal(binvar) < 0.5)
    573 consdata->nglbfixedzeros--;
    574 else if( SCIPvarGetLbGlobal(binvar) > 0.5 )
    575 consdata->nglbfixedones--;
    576
    577 /* update the locally fixed variables counter for this variable */
    578 if( SCIPvarGetUbLocal(binvar) < 0.5)
    579 consdata->nfixedzeros--;
    580 else if( SCIPvarGetLbLocal(binvar) > 0.5 )
    581 consdata->nfixedones--;
    582
    583 assert(consdata->nglbfixedzeros >= 0);
    584 assert(consdata->nglbfixedones >= 0);
    585
    586 return SCIP_OKAY;
    587}
    588
    589/** catches events for integer variable at given position */
    590static
    592 SCIP* scip, /**< SCIP data structure */
    593 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    594 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    595 int pos /**< array position of variable to catch bound change events for */
    596 )
    597{
    598 SCIP_CONSDATA* consdata;
    599 SCIP_EVENTTYPE eventtype;
    600 SCIP_VAR* var;
    601
    602 consdata = SCIPconsGetData(cons);
    603 assert(consdata != NULL);
    604 assert(eventhdlr != NULL);
    605 assert(0 <= pos && pos < consdata->nvars);
    606 assert(consdata->vars != NULL);
    607
    608 var = consdata->vars[pos];
    609 assert(var != NULL);
    610
    611 /* we are catching the following events for the integer variables:
    612 *
    613 * - SCIP_EVENTTYPE_GBDCHANGED: This allows to check if the optcumulative can be converted into an cumulative
    614 * constraint
    615 */
    617
    618 /* catch bound change events on variable */
    619 SCIP_CALL( SCIPcatchVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
    620
    621 return SCIP_OKAY;
    622}
    623
    624/** drops events for integer variable at given position */
    625static
    627 SCIP* scip, /**< SCIP data structure */
    628 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    629 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
    630 int pos /**< array position of variable to catch bound change events for */
    631 )
    632{
    633 SCIP_CONSDATA* consdata;
    634 SCIP_EVENTTYPE eventtype;
    635 SCIP_VAR* var;
    636
    637 consdata = SCIPconsGetData(cons);
    638 assert(consdata != NULL);
    639 assert(eventhdlr != NULL);
    640 assert(0 <= pos && pos < consdata->nvars);
    641 assert(consdata->vars != NULL);
    642
    643 var = consdata->vars[pos];
    644 assert(var != NULL);
    645
    647
    648 /* drop events on variable */
    649 SCIP_CALL( SCIPdropVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
    650
    651 return SCIP_OKAY;
    652}
    653
    654/** catches bound change events for all variables in transformed optcumulative constraint */
    655static
    657 SCIP* scip, /**< SCIP data structure */
    658 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    659 SCIP_EVENTHDLR* eventhdlrbinvars, /**< event handler to call for the event processing on binary variables */
    660 SCIP_EVENTHDLR* eventhdlrintvars /**< event handler to call for the event processing on integer variables */
    661 )
    662{
    663 SCIP_CONSDATA* consdata;
    664 int v;
    665
    666 consdata = SCIPconsGetData(cons);
    667 assert(consdata != NULL);
    668
    669 /* check that the global constraint state is clean */
    670 assert(consdata->nglbfixedzeros == 0);
    671 assert(consdata->nglbfixedones == 0);
    672
    673 /* catch event for every single variable */
    674 for( v = 0; v < consdata->nvars; ++v )
    675 {
    676 SCIP_CALL( catchEventBinvar(scip, cons, eventhdlrbinvars, v) );
    677
    678 SCIP_CALL( catchEventIntvar(scip, cons, eventhdlrintvars, v) );
    679 }
    680
    681 /* (debug) check if the counter of the constraint are correct */
    682 checkCounters(consdata);
    683
    684 return SCIP_OKAY;
    685}
    686
    687/** drops bound change events for all variables in transformed optcumulative constraint */
    688static
    690 SCIP* scip, /**< SCIP data structure */
    691 SCIP_CONS* cons, /**< set partitioning / packing / covering constraint */
    692 SCIP_EVENTHDLR* eventhdlrbinvars, /**< event handler to call for the event processing on binary variables */
    693 SCIP_EVENTHDLR* eventhdlrintvars /**< event handler to call for the event processing on integer variables */
    694 )
    695{
    696 SCIP_CONSDATA* consdata;
    697 int v;
    698
    699 consdata = SCIPconsGetData(cons);
    700 assert(consdata != NULL);
    701
    702 /* drop event of every single variable */
    703 for( v = 0; v < consdata->nvars; ++v )
    704 {
    705 SCIP_CALL( dropEventBinvar(scip, cons, eventhdlrbinvars, v) );
    706
    707 SCIP_CALL( dropEventIntvar(scip, cons, eventhdlrintvars, v) );
    708 }
    709
    710 /* check that the global constraint state is reset */
    711 assert(consdata->nglbfixedzeros == 0);
    712 assert(consdata->nglbfixedones == 0);
    713
    714 return SCIP_OKAY;
    715}
    716
    717/** initialize the sorted event point arrays */
    718static
    720 SCIP* scip, /**< SCIP data structure */
    721 SCIP_CONSDATA* consdata, /**< constraint data */
    722 int* starttimes, /**< array to store sorted start events */
    723 int* endtimes, /**< array to store sorted end events */
    724 int* startindices, /**< permutation with rspect to the start times */
    725 int* endindices, /**< permutation with rspect to the end times */
    726 SCIP_Bool local /**< shall local bounds be used */
    727 )
    728{
    729 SCIP_VAR* var;
    730 int nvars;
    731 int j;
    732
    733 nvars = consdata->nvars;
    734
    735 /* assign variables, start and endpoints to arrays */
    736 for ( j = 0; j < nvars; ++j )
    737 {
    738 var = consdata->vars[j];
    739 if( local )
    740 starttimes[j] = convertBoundToInt(scip, SCIPvarGetLbLocal(var));
    741 else
    742 starttimes[j] = convertBoundToInt(scip, SCIPvarGetLbGlobal(var));
    743
    744 startindices[j] = j;
    745
    746 if( local )
    747 endtimes[j] = convertBoundToInt(scip, SCIPvarGetUbLocal(var)) + consdata->durations[j];
    748 else
    749 endtimes[j] = convertBoundToInt(scip, SCIPvarGetUbGlobal(var)) + consdata->durations[j];
    750
    751 endindices[j] = j;
    752 }
    753
    754 /* sort the arrays not-decreasing according to startsolvalues and endsolvalues (and sort the indices in the same way) */
    755 SCIPsortIntInt(starttimes, startindices, nvars);
    756 SCIPsortIntInt(endtimes, endindices, nvars);
    757}
    758
    759/** computes the maximum energy for all variables which correspond to jobs which start between the given start time and
    760 * end time
    761 *
    762 * @return Maximum energy for the given time window
    763 */
    764static
    766 SCIP* scip, /**< SCIP data structure */
    767 SCIP_CONSDATA* consdata, /**< optcumulative constraint data */
    768 int starttime, /**< start time */
    769 int endtime /**< end time */
    770 )
    771{
    772 SCIP_VAR* var;
    773 SCIP_Longint maxenergy;
    774 int v;
    775
    776 assert(starttime < endtime);
    777 maxenergy = 0LL;
    778
    779 for( v = 0; v < consdata->nvars; ++v )
    780 {
    781 var = consdata->vars[v];
    782
    783 /* collect jobs which run between the start and end time */
    784 if( convertBoundToInt(scip, SCIPvarGetUbGlobal(var)) + consdata->durations[v] <= endtime
    785 && convertBoundToInt(scip, SCIPvarGetLbGlobal(var)) >= starttime)
    786 {
    787 maxenergy += (SCIP_Longint)(consdata->durations[v] * consdata->demands[v]); /*lint !e647*/
    788 }
    789 }
    790
    791 return maxenergy;
    792}
    793
    794/** collects all variables which correspond to jobs which start between the given start time and end time */
    795static
    797 SCIP* scip, /**< SCIP data structure */
    798 SCIP_CONSDATA* consdata, /**< optcumulative constraint data */
    799 SCIP_VAR** vars, /**< array to store the variables */
    800 SCIP_Longint* weights, /**< array to store the weights */
    801 int* nvars, /**< pointer to store the number of collected variables */
    802 int starttime, /**< start time */
    803 int endtime /**< end time */
    804 )
    805{
    806 SCIP_VAR* var;
    807 int v;
    808
    809 assert(starttime < endtime);
    810 (*nvars) = 0;
    811
    812 for( v = 0; v < consdata->nvars; ++v )
    813 {
    814 var = consdata->vars[v];
    815
    816 /* collect jobs which run between the start and end time */
    817 if( convertBoundToInt(scip, SCIPvarGetUbGlobal(var)) + consdata->durations[v] <= endtime
    818 && convertBoundToInt(scip, SCIPvarGetLbGlobal(var)) >= starttime)
    819 {
    820 vars[*nvars] = consdata->binvars[v];
    821 weights[*nvars] = (SCIP_Longint)(consdata->durations[v] * consdata->demands[v]); /*lint !e647*/
    822 (*nvars)++;
    823 }
    824 }
    825
    826 return SCIP_OKAY;
    827}
    828
    829/** remove row which have a tightness which is smaller or equal to the given one
    830 *
    831 * @return The number of remaining rows
    832 */
    833static
    835 SCIP_Longint* rowtightness, /**< array containing the tightness for the previously selected rows */
    836 int* startidxs, /**< array containing for each row the index for the start event */
    837 int nrows, /**< current number of rows */
    838 SCIP_Longint tightness /**< tightness to use to detect redundant rows */
    839 )
    840{
    841 int keptrows;
    842 int j;
    843
    844 keptrows = 0;
    845
    846 for( j = 0; j < nrows; ++j )
    847 {
    848 rowtightness[keptrows] = rowtightness[j];
    849 startidxs[keptrows] = startidxs[j];
    850
    851 /* only keep this row if the tightness is better as the (current) given one */
    852 if( rowtightness[j] > tightness )
    853 keptrows++;
    854 }
    855
    856 return keptrows;
    857}
    858
    859/** depending on the parameters setting a row or an knapsack constraint is created */
    860static
    862 SCIP* scip, /**< SCIP data structure */
    863 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    864 const char* name, /**< name of the row */
    865 SCIP_VAR** vars, /**< array of variable representing if the job has to be processed on this machine */
    866 SCIP_Longint* weights, /**< start time variables of the activities which are assigned */
    867 int nvars, /**< number of variables */
    868 SCIP_Longint capacity, /**< available cumulative capacity */
    869 SCIP_Bool local, /**< create local row */
    870 SCIP_Bool* rowadded, /**< pointer to store if a row was added */
    871 SCIP_Bool* consadded, /**< pointer to store if a constraint was added */
    872 SCIP_Bool* cutoff /**< pointer to store whether a cutoff occurred */
    873 )
    874{
    875 SCIP_CONSHDLRDATA* conshdlrdata;
    876
    877 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    878 assert(conshdlrdata != NULL);
    879
    880 *cutoff = FALSE;
    881 if( conshdlrdata->rowrelax || SCIPgetDepth(scip) > 0 )
    882 {
    883 SCIP_ROW* row;
    884 int v;
    885
    886 /* create empty row */
    887 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, name, -SCIPinfinity(scip), (SCIP_Real)capacity, local, FALSE, FALSE) );
    888
    889 /* w.r.t. performance we cache the row extension and flush them in the end */
    891
    892 for( v = 0; v < nvars; ++v )
    893 {
    894 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[v], (SCIP_Real)weights[v]) );
    895 }
    896
    897 /* w.r.t. performance we flush the row extension in the end */
    899
    900 assert(!SCIProwIsInLP(row));
    901
    902 if( SCIPgetDepth(scip) == 0 || SCIPisCutEfficacious(scip, NULL, row) )
    903 {
    905 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
    906 (*rowadded) = TRUE;
    907 }
    908
    909 SCIP_CALL( SCIPreleaseRow(scip, &row) );
    910 }
    911 else
    912 {
    913 SCIP_CONS* cons;
    914
    915 /* create knapsack constraint */
    916 SCIP_CALL( SCIPcreateConsKnapsack(scip, &cons, name, nvars, vars, weights, capacity,
    917 FALSE, TRUE, TRUE, FALSE, TRUE, local, FALSE, FALSE, TRUE, FALSE) );
    918
    920
    921 /* add and releasse knapsack constraint */
    922 SCIP_CALL( SCIPaddCons(scip, cons) );
    923 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    924 (*consadded) = TRUE;
    925 }
    926
    927 return SCIP_OKAY;
    928}
    929
    930/** adds linear relaxation as cut to the LP */
    931static
    933 SCIP* scip, /**< SCIP data structure */
    934 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
    935 SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data structure */
    936 SCIP_CONS* cons, /**< optcumulative constraint */
    937 SCIP_Bool* rowadded, /**< pointer to store if a row was added */
    938 SCIP_Bool* consadded, /**< pointer to store if a constraint was added */
    939 SCIP_Bool* cutoff /**< pointer to store whether a cutoff occurred */
    940 )
    941{
    942 SCIP_CONSDATA* consdata;
    943
    944 assert(scip != NULL);
    945 assert(cons != NULL);
    946
    947 consdata = SCIPconsGetData(cons);
    948 assert(consdata != NULL);
    949 assert( cutoff != NULL );
    950
    951 *cutoff = FALSE;
    952 if( consdata->relaxadded )
    953 return SCIP_OKAY;
    954
    955 SCIPdebugMessage("add relaxation for optcumulative constraint <%s>\n", SCIPconsGetName(cons));
    956
    957 if( conshdlrdata->intervalrelax )
    958 {
    959 SCIP_Longint** rowtightness;
    960 int** startidxs;
    961 int* nrows;
    962 int* starttimes;
    963 int* endtimes;
    964 int* startindices;
    965 int* endindices;
    966 int starttime;
    967 int endtime;
    968 int i;
    969 int j;
    970
    971 SCIP_CALL( SCIPallocBufferArray(scip, &starttimes, consdata->nvars) );
    972 SCIP_CALL( SCIPallocBufferArray(scip, &startindices, consdata->nvars) );
    973 SCIP_CALL( SCIPallocBufferArray(scip, &endtimes, consdata->nvars) );
    974 SCIP_CALL( SCIPallocBufferArray(scip, &endindices, consdata->nvars) );
    975
    976 SCIP_CALL( SCIPallocBufferArray(scip, &nrows, consdata->nvars) );
    977 BMSclearMemoryArray(nrows, consdata->nvars);
    978 SCIP_CALL( SCIPallocBufferArray(scip, &rowtightness, consdata->nvars) );
    979 SCIP_CALL( SCIPallocBufferArray(scip, &startidxs, consdata->nvars) );
    980 for( j = 0; j < consdata->nvars; ++j )
    981 {
    982 SCIP_CALL( SCIPallocBufferArray(scip, &rowtightness[j], consdata->nvars) ); /*lint !e866*/
    983 SCIP_CALL( SCIPallocBufferArray(scip, &startidxs[j], consdata->nvars) ); /*lint !e866*/
    984 }
    985
    986 createSortedEventpoints(scip, consdata, starttimes, endtimes, startindices, endindices, TRUE);
    987
    988 starttime = -INT_MAX;
    989
    990 /* check each startpoint of a job whether the capacity is kept or not */
    991 for( j = 0; j < consdata->nvars; ++j )
    992 {
    993 SCIP_Longint besttightness;
    994
    995 assert(starttime <= starttimes[j]);
    996
    997 /* if we hit the same start time again we skip the loop */
    998 if( starttime == starttimes[j])
    999 continue;
    1000
    1001 starttime = starttimes[j];
    1002 endtime = -INT_MAX;
    1003 besttightness = 0LL;
    1004
    1005 for( i = 0; i < consdata->nvars; ++i )
    1006 {
    1007 SCIP_Longint energy;
    1008 SCIP_Longint maxenergy;
    1009 SCIP_Longint tightness;
    1010
    1011 assert(endtime <= endtimes[i]);
    1012
    1013 /* if we hit the same end time again we skip the loop */
    1014 if( endtime == endtimes[i] )
    1015 continue;
    1016
    1017 endtime = endtimes[i];
    1018
    1019 /* skip all end times which are smaller than the start time */
    1020 if( endtime <= starttime )
    1021 continue;
    1022
    1023 maxenergy = computeMaxEnergy(scip, consdata, starttime, endtime);
    1024
    1025 energy = (endtime - starttime) * consdata->capacity; /*lint !e647*/
    1026 tightness = maxenergy - energy;
    1027
    1028 /* check if the linear constraint is not trivially redundant */
    1029 if( tightness > besttightness )
    1030 {
    1031 besttightness = tightness;
    1032
    1033 nrows[i] = removeRedundantRows(rowtightness[i], startidxs[i], nrows[i], tightness);
    1034
    1035 /* add row information */
    1036 rowtightness[i][nrows[i]] = tightness;
    1037 startidxs[i][nrows[i]] = j;
    1038 nrows[i]++;
    1039 }
    1040 }
    1041 }
    1042
    1043 for( j = consdata->nvars-1; j >= 0 && ! (*cutoff); --j )
    1044 {
    1045 for( i = 0; i < nrows[j] && ! (*cutoff); ++i )
    1046 {
    1047 SCIP_VAR** vars;
    1048 SCIP_Longint* weights;
    1049 SCIP_Longint energy;
    1050 char name[SCIP_MAXSTRLEN];
    1051 int nvars;
    1052
    1053 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    1054 SCIP_CALL( SCIPallocBufferArray(scip, &weights, consdata->nvars) );
    1055
    1056 starttime = starttimes[startidxs[j][i]];
    1057 endtime = endtimes[j];
    1058
    1059 energy = (endtime - starttime) * consdata->capacity; /*lint !e647*/
    1060
    1061 SCIP_CALL( collectVars(scip, consdata, vars, weights, &nvars, starttime, endtime) );
    1062
    1063 SCIPdebugMessage("create linear relaxation for <%s> time interval [%d,%d] <= %"SCIP_LONGINT_FORMAT" (tightness %"SCIP_LONGINT_FORMAT")\n",
    1064 SCIPconsGetName(cons), starttime, endtime, energy, rowtightness[j][i]);
    1065
    1066 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d,%d]", SCIPconsGetName(cons), starttime, endtime);
    1067 SCIP_CALL( createRow(scip, conshdlr, name, vars, weights, nvars, energy, TRUE, rowadded, consadded, cutoff) );
    1068
    1069 SCIPfreeBufferArray(scip, &weights);
    1070 SCIPfreeBufferArray(scip, &vars);
    1071 }
    1072 }
    1073
    1074 /* free buffers */
    1075 for( j = consdata->nvars-1; j >= 0; --j )
    1076 {
    1077 SCIPfreeBufferArray(scip, &startidxs[j]);
    1078 SCIPfreeBufferArray(scip, &rowtightness[j]);
    1079 }
    1080 SCIPfreeBufferArray(scip, &startidxs);
    1081 SCIPfreeBufferArray(scip, &rowtightness);
    1082 SCIPfreeBufferArray(scip, &nrows);
    1083
    1084 SCIPfreeBufferArray(scip, &endindices);
    1085 SCIPfreeBufferArray(scip, &endtimes);
    1086 SCIPfreeBufferArray(scip, &startindices);
    1087 SCIPfreeBufferArray(scip, &starttimes);
    1088 }
    1089 else
    1090 {
    1091 SCIP_VAR** vars;
    1092 SCIP_Longint* weights;
    1093 SCIP_Longint maxenergy;
    1094 SCIP_Longint energy;
    1095 int* durations;
    1096 int* demands;
    1097 int est;
    1098 int lct;
    1099 int nvars;
    1100 int v;
    1101
    1102 nvars = consdata->nvars;
    1103 vars = consdata->vars;
    1104 durations = consdata->durations;
    1105 demands = consdata->demands;
    1106 maxenergy = 0LL;
    1107
    1108 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    1109
    1110 est = INT_MAX;
    1111 lct = 0;
    1112
    1113 for( v = 0; v < nvars; ++v )
    1114 {
    1115 weights[v] = (SCIP_Longint)(durations[v] * demands[v]); /*lint !e647*/
    1116 maxenergy += weights[v];
    1117
    1118 /* adjust earlier start time */
    1119 est = MIN(est, convertBoundToInt(scip, SCIPvarGetLbLocal(vars[v]))); /*lint !e666*/
    1120
    1121 /* adjust latest completion */
    1122 lct = MAX(lct, convertBoundToInt(scip, SCIPvarGetUbLocal(vars[v]) + durations[v])); /*lint !e666*/
    1123 }
    1124
    1125 energy = (lct - est) * consdata->capacity; /*lint !e647*/
    1126
    1127 if( maxenergy > energy )
    1128 {
    1129 char name[SCIP_MAXSTRLEN];
    1130
    1131 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s[%d,%d]", SCIPconsGetName(cons), est, lct);
    1132
    1133 SCIPdebugMessage("create linear relaxation for <%s> (nvars %d) time interval [%d,%d] <= %"SCIP_LONGINT_FORMAT"\n",
    1134 SCIPconsGetName(cons), nvars, est, lct, energy);
    1135
    1136 SCIP_CALL( createRow(scip, conshdlr, name, consdata->binvars, weights, nvars, energy, TRUE, rowadded, consadded, cutoff) );
    1137 }
    1138
    1139 /* free buffer */
    1140 SCIPfreeBufferArray(scip, &weights);
    1141 }
    1142
    1143 consdata->relaxadded = TRUE;
    1144
    1145 return SCIP_OKAY;
    1146}
    1147
    1148/** collect all activities which are locally (that means in the current branch and bound node) assigned to that
    1149 * machine
    1150 */
    1151static
    1153 SCIP_CONSDATA* consdata, /**< constraint data */
    1154 SCIP_VAR** binvars, /**< array of variable representing if the job has to be processed on this machine */
    1155 SCIP_VAR** vars, /**< start time variables of the activities which are assigned */
    1156 int* durations, /**< durations of the activities */
    1157 int* demands, /**< demands of the activities */
    1158 int* nfixedones, /**< pointer to store number of activities assigned to that machine */
    1159 int* nfixedzeros, /**< pointer to store number of binary variables fixed to zero */
    1160 SCIP_Bool* auxiliary /**< pointer to store if the integer start time variables of the assigned
    1161 * activities are auxiliary variables; that is the case if the optcumulative
    1162 * choice constraints is the only one having locks on these variables */
    1163 )
    1164{
    1165 int v;
    1166
    1167 /* collect all jobs which have to be processed */
    1168 (*auxiliary) = TRUE;
    1169 (*nfixedones) = 0;
    1170 (*nfixedzeros) = 0;
    1171
    1172 for( v = 0; v < consdata->nvars; ++v )
    1173 {
    1174 if( SCIPvarGetLbLocal(consdata->binvars[v]) > 0.5 )
    1175 {
    1176 /* binary variable is fixed one */
    1177
    1178 SCIPdebugMessage("collect variable <%s>[%g,%g](%d)\n",
    1179 SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbGlobal(consdata->vars[v]), consdata->durations[v]);
    1180
    1181 binvars[*nfixedones] = consdata->binvars[v];
    1182 vars[*nfixedones] = consdata->vars[v];
    1183 durations[*nfixedones] = consdata->durations[v];
    1184 demands[*nfixedones] = consdata->demands[v];
    1185
    1186 (*nfixedones)++;
    1187
    1188 /* check the locks on the integer start time variable to determine if its a auxiliary variable (only locked by
    1189 * this constraint)
    1190 */
    1191 if( SCIPvarGetNLocksDown(consdata->vars[v]) > (int)consdata->downlocks[v]
    1192 || SCIPvarGetNLocksUp(consdata->vars[v]) > (int)consdata->uplocks[v] )
    1193 {
    1194 (*auxiliary) = FALSE;
    1195 }
    1196 }
    1197 else if( SCIPvarGetUbLocal(consdata->binvars[v]) < 0.5 )
    1198 (*nfixedzeros)++;
    1199 }
    1200
    1201 assert(consdata->nfixedzeros == *nfixedzeros);
    1202 assert(consdata->nfixedones == *nfixedones);
    1203}
    1204
    1205/** collect all activities which are assigned to that machine in the given solution */
    1206static
    1208 SCIP* scip, /**< SCIP data structure */
    1209 SCIP_CONSDATA* consdata, /**< constraint data */
    1210 SCIP_SOL* sol, /**< primal solution, or NULL for current LP/pseudo solution */
    1211 SCIP_VAR** binvars, /**< array of variable representing if the job has to be processed on this machine */
    1212 SCIP_VAR** vars, /**< start time variables of the activities which are assigned */
    1213 int* durations, /**< durations of the activities */
    1214 int* demands, /**< demands of the activities */
    1215 int* nvars, /**< pointer to store number of activities assigned to that machine */
    1216 int* nfixedones, /**< pointer to store number of binary variables locally fixed to one */
    1217 int* nfixedzeros, /**< pointer to store number of binary variables locally fixed to zero */
    1218 SCIP_Bool* auxiliary /**< pointer to store if the integer start time variables of the assigned
    1219 * activities are auxiliary variables; that is the case if the machine
    1220 * choice constraints is the only one having locks on these variables */
    1221 )
    1222{
    1223 int v;
    1224
    1225 (*nvars) = 0;
    1226 (*nfixedones) = 0;
    1227 (*nfixedzeros) = 0;
    1228 (*auxiliary) = TRUE;
    1229
    1230 /* collect all jobs which have to be processed */
    1231 for( v = 0; v < consdata->nvars; ++v )
    1232 {
    1233 if( SCIPgetSolVal(scip, sol, consdata->binvars[v]) > 0.5 )
    1234 {
    1235 SCIPdebugMessage("collect variable <%s>\n", SCIPvarGetName(consdata->vars[v]));
    1236 binvars[*nvars] = consdata->binvars[v];
    1237 vars[*nvars] = consdata->vars[v];
    1238 durations[*nvars] = consdata->durations[v];
    1239 demands[*nvars] = consdata->demands[v];
    1240 (*nvars)++;
    1241
    1242 /* check the locks on the integer start time variable to determine if its a auxiliary variable */
    1243 if( SCIPvarGetNLocksDown(consdata->vars[v]) > (int)consdata->downlocks[v]
    1244 || SCIPvarGetNLocksUp(consdata->vars[v]) > (int)consdata->uplocks[v]
    1245 )
    1246 (*auxiliary) = FALSE;
    1247 }
    1248
    1249 if( SCIPvarGetLbLocal(consdata->binvars[v]) > 0.5 )
    1250 nfixedones++;
    1251 else if( SCIPvarGetUbLocal(consdata->binvars[v]) < 0.5 )
    1252 nfixedzeros++;
    1253 }
    1254}
    1255
    1256/** solves given cumulative condition as independent sub problem
    1257 *
    1258 * @note The time and memory limit of the SCIP environment in transferred to sub solver
    1259 *
    1260 * @note If the problem was solved to the earliest start times (ests) and latest start times (lsts) array contain the
    1261 * solution values; If the problem was not solved these two arrays contain the global bounds at the time the sub
    1262 * solver was interrupted.
    1263 */
    1264static
    1266 SCIP* scip, /**< SCIP data structure */
    1267 int nvars, /**< number of start time variables (activities) */
    1268 SCIP_VAR** vars, /**< start time variables */
    1269 int* durations, /**< array of durations */
    1270 int* demands, /**< array of demands */
    1271 int capacity, /**< cumulative capacity */
    1272 int hmin, /**< left bound of time axis to be considered (including hmin) */
    1273 int hmax, /**< right bound of time axis to be considered (not including hmax) */
    1274 SCIP_Bool local, /**< use local bounds, otherwise global */
    1275 SCIP_Real* ests, /**< array to store the earlier start time for each job */
    1276 SCIP_Real* lsts, /**< array to store the latest start time for each job */
    1277 SCIP_Longint maxnodes, /**< maximum number of branch-and-bound nodes to solve the single cumulative constraint (-1: no limit) */
    1278 SCIP_Bool* solved, /**< pointer to store if the problem is solved (to optimality) */
    1279 SCIP_Bool* infeasible, /**< pointer to store if the problem is infeasible */
    1280 SCIP_Bool* unbounded, /**< pointer to store if the problem is unbounded */
    1281 SCIP_Bool* error /**< pointer to store if an error occurred */
    1282 )
    1283{
    1284 SCIP_Real* objvals;
    1285 SCIP_Real timelimit;
    1286 SCIP_Real memorylimit;
    1287 int v;
    1288
    1289 SCIP_CALL( SCIPallocBufferArray(scip, &objvals, nvars) );
    1290
    1291 for( v = 0; v < nvars; ++v )
    1292 {
    1293 SCIP_VAR* var;
    1294
    1295 var = vars[v];
    1296 assert(var != NULL);
    1297
    1298 if( local )
    1299 {
    1300 ests[v] = SCIPvarGetLbLocal(var);
    1301 lsts[v] = SCIPvarGetUbLocal(var);
    1302 }
    1303 else
    1304 {
    1305 ests[v] = SCIPvarGetLbGlobal(var);
    1306 lsts[v] = SCIPvarGetUbGlobal(var);
    1307 }
    1308
    1309 objvals[v] = SCIPvarGetObj(var);
    1310 }
    1311
    1312 /* check whether there is enough time and memory left */
    1313 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    1314 if( !SCIPisInfinity(scip, timelimit) )
    1315 timelimit -= SCIPgetSolvingTime(scip);
    1316 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
    1317
    1318 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    1319 if( !SCIPisInfinity(scip, memorylimit) )
    1320 {
    1321 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    1322 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    1323 }
    1324
    1325 SCIP_CALL( SCIPsolveCumulative(scip, nvars, ests, lsts, objvals, durations, demands,
    1326 capacity, hmin, hmax, timelimit, memorylimit, maxnodes,
    1327 solved, infeasible, unbounded, error) );
    1328
    1329 SCIPfreeBufferArray(scip, &objvals);
    1330
    1331 return SCIP_OKAY;
    1332}
    1333
    1334
    1335/** create a logicor constraint which ensures that the jobs related to binary variables are not assigned in the same
    1336 * time to this optional cumulative constraint
    1337 */
    1338static
    1340 SCIP* scip, /**< SCIP data structure */
    1341 const char* name, /**< name of conflict constraint */
    1342 SCIP_VAR** binvars, /**< array of binary variables */
    1343 int nvars /**< number of variables */
    1344 )
    1345{
    1346 SCIP_CONS* cons;
    1347 SCIP_VAR* negatedvar;
    1348 int v;
    1349
    1350 /* one of the jobs cannot be processed on that resource */
    1351 SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, 0, NULL,
    1353
    1354 for( v = 0; v < nvars; ++v )
    1355 {
    1356 if( SCIPvarGetLbGlobal(binvars[v]) > 0.5 )
    1357 continue;
    1358
    1359 SCIP_CALL( SCIPgetNegatedVar(scip, binvars[v], &negatedvar) );
    1360
    1361 SCIP_CALL( SCIPaddCoefLogicor(scip, cons, negatedvar) );
    1362 }
    1363
    1364 /* add and release to constraint */
    1365 SCIP_CALL( SCIPaddCons(scip, cons) );
    1366 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    1367
    1368 return SCIP_OKAY;
    1369}
    1370
    1371/** check of the given constraint is redundant */
    1372static
    1374 SCIP* scip, /**< SCIP data structure */
    1375 SCIP_CONS* cons, /**< optcumulative constraint which collapsed to a cumulative constraint locally */
    1376 int* ndelconss, /**< pointer to store the number of deleted constraints */
    1377 SCIP_Bool* redundant /**< pointer to store if the constraint is redundant */
    1378 )
    1379{
    1380 SCIP_CONSDATA* consdata;
    1381 SCIP_Bool solved;
    1382 SCIP_Bool infeasible;
    1383 SCIP_Bool unbounded;
    1384 SCIP_Bool error;
    1385 SCIP_Real* lbs;
    1386 SCIP_Real* ubs;
    1387 int nvars;
    1388 int v;
    1389
    1390 assert(scip != NULL);
    1391 assert(!SCIPinProbing(scip));
    1392
    1393 (*redundant) = FALSE;
    1394
    1395 consdata = SCIPconsGetData(cons);
    1396 assert(consdata != NULL);
    1397 assert(consdata->nglbfixedzeros == 0);
    1398
    1399 if( consdata->triedredundant )
    1400 return SCIP_OKAY;
    1401
    1402 consdata->triedredundant = TRUE;
    1403
    1404 nvars = consdata->nvars;
    1405
    1406 /* check the locks on the integer start time variable to determine if its a auxiliary variable */
    1407 for( v = 0; v < nvars; ++v )
    1408 {
    1409 if( SCIPvarGetNLocksDown(consdata->vars[v]) > (int)consdata->downlocks[v]
    1410 || SCIPvarGetNLocksUp(consdata->vars[v]) > (int)consdata->uplocks[v]
    1411 )
    1412 return SCIP_OKAY;
    1413 }
    1414
    1415 SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nvars) );
    1416 SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
    1417
    1418 /* solve the cumulative condition separately */
    1419 SCIP_CALL( solveCumulative(scip, nvars, consdata->vars, consdata->durations, consdata->demands,
    1420 consdata->capacity, consdata->hmin, consdata->hmax, FALSE,
    1421 lbs, ubs, 2000LL, &solved, &infeasible, &unbounded, &error) );
    1422 assert(!unbounded);
    1423
    1424 if( !error )
    1425 {
    1426 if( infeasible )
    1427 {
    1428 SCIP_VAR** binvars;
    1429 SCIP_VAR** vars;
    1430 int* durations;
    1431 int* demands;
    1432 SCIP_Real* weights;
    1433
    1434 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
    1435 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    1436 SCIP_CALL( SCIPallocBufferArray(scip, &durations, nvars) );
    1437 SCIP_CALL( SCIPallocBufferArray(scip, &demands, nvars) );
    1438 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    1439
    1440 for( v = 0; v < nvars; ++v )
    1441 {
    1442 SCIP_VAR* var;
    1443 int est;
    1444 int lst;
    1445
    1446 var = consdata->vars[v];
    1447 assert(var != NULL);
    1448
    1451
    1452 if( consdata->demands[v] == 0.0 || consdata->durations[v] == 0.0 )
    1453 return SCIP_ERROR;
    1454
    1455 weights[v] = (lst - est) / (consdata->demands[v] * consdata->durations[v]); /*lint !e653*/
    1456
    1457 binvars[v] = consdata->binvars[v];
    1458 vars[v] = var;
    1459 durations[v] = consdata->durations[v];
    1460 demands[v] = consdata->demands[v];
    1461 }
    1462 SCIPsortRealPtrPtrIntInt(weights, (void*)binvars, (void*)vars, durations, demands, nvars);
    1463
    1464 while( nvars > 1 )
    1465 {
    1466 SCIP_CALL( solveCumulative(scip, nvars-1, vars, consdata->durations, consdata->demands, consdata->capacity, consdata->hmin, consdata->hmax, TRUE,
    1467 lbs, ubs, 2000LL, &solved, &infeasible, &unbounded, &error) );
    1468
    1469 if( !infeasible )
    1470 break;
    1471
    1472 nvars--;
    1473 }
    1474
    1475 SCIP_CALL( createConflictCons(scip, SCIPconsGetName(cons), binvars, nvars) );
    1476
    1477 SCIPfreeBufferArray(scip, &weights);
    1478 SCIPfreeBufferArray(scip, &demands);
    1479 SCIPfreeBufferArray(scip, &durations);
    1480 SCIPfreeBufferArray(scip, &vars);
    1481 SCIPfreeBufferArray(scip, &binvars);
    1482 }
    1483 else if( solved )
    1484 {
    1485 for( v = 0; v < nvars; ++v )
    1486 {
    1487 SCIP_VAR* var;
    1488
    1489 /* check if variable is fixed */
    1490 assert(lbs[v] + 0.5 > ubs[v]);
    1491
    1492 var = consdata->vars[v];
    1493 assert(var != NULL);
    1494
    1495 if( SCIPvarGetLbGlobal(var) + 0.5 < lbs[v] )
    1496 {
    1497 SCIP_CALL( SCIPchgVarLbGlobal(scip, var, lbs[v]) );
    1498 }
    1499
    1500 if( SCIPvarGetUbGlobal(var) - 0.5 > lbs[v] )
    1501 {
    1502 SCIP_CALL( SCIPchgVarUbGlobal(scip, var, lbs[v]) );
    1503 }
    1504 }
    1505
    1507 (*ndelconss)++;
    1508 (*redundant) = TRUE;
    1509 }
    1510 }
    1511
    1514
    1515 return SCIP_OKAY;
    1516}
    1517
    1518/** solve the cumulative sub problem */
    1519static
    1521 SCIP* scip, /**< SCIP data structure */
    1522 SCIP_CONS* cons, /**< optcumulative constraint which collapsed to a cumulative constraint locally */
    1523 SCIP_Bool conflictanalysis, /**< should conflict analysis be called for infeasible subproblems */
    1524 SCIP_CONSDATA* consdata, /**< constraint data */
    1525 SCIP_VAR** binvars, /**< array of variable representing if the job has to be processed on this machine */
    1526 SCIP_VAR** vars, /**< start time variables of the activities which are assigned */
    1527 int* durations, /**< durations of the activities */
    1528 int* demands, /**< demands of the activities */
    1529 int nvars, /**< number of activities assigned to that machine */
    1530 int* nfixedvars, /**< pointer to store the number of fixed variables */
    1531 int* nchgbds, /**< pointer to store the number of changed bounds */
    1532 int* ndelconss, /**< pointer to store the number of deleted constraints */
    1533 SCIP_Bool* cutoff /**< pointer to store if the constraint is violated */
    1534 )
    1535{
    1536 SCIP_Bool unbounded;
    1537 SCIP_Bool solved;
    1538 SCIP_Bool error;
    1539 SCIP_Real* lbs;
    1540 SCIP_Real* ubs;
    1541
    1542 assert(scip != NULL);
    1543 assert(!SCIPinProbing(scip));
    1544
    1545 /* if we already tried solving this subproblem we do not do it again */
    1546 if( consdata->triedsolving )
    1547 return SCIP_OKAY;
    1548
    1549 consdata->triedsolving = TRUE;
    1550
    1551 if( nvars == 0 )
    1552 return SCIP_OKAY;
    1553
    1554 SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nvars) );
    1555 SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
    1556
    1557 /* solve the cumulative condition separately */
    1558 SCIP_CALL( solveCumulative(scip, nvars, vars, durations, demands, consdata->capacity, consdata->hmin, consdata->hmax, TRUE,
    1559 lbs, ubs, 2000LL, &solved, cutoff, &unbounded, &error) );
    1560 assert(!unbounded);
    1561
    1562 if( !error )
    1563 {
    1564 if( *cutoff && conflictanalysis )
    1565 {
    1566 SCIP_Real* weights;
    1567 SCIP_Bool infeasible;
    1568 int v;
    1569
    1570 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    1571
    1572 for( v = 0; v < nvars; ++v )
    1573 {
    1574 int est;
    1575 int lst;
    1576
    1577 est = convertBoundToInt(scip, SCIPvarGetLbLocal(vars[v]));
    1578 lst = convertBoundToInt(scip, SCIPvarGetUbLocal(vars[v]));
    1579
    1580 if( demands[v] == 0.0 || durations[v] == 0.0 )
    1581 return SCIP_ERROR;
    1582
    1583 weights[v] = (lst - est) / (demands[v] * durations[v]); /*lint !e653*/
    1584 }
    1585 SCIPsortRealPtrPtrIntInt(weights, (void*)binvars, (void*)vars, durations, demands, nvars);
    1586
    1587 SCIPfreeBufferArray(scip, &weights);
    1588
    1589 while( nvars > 1 )
    1590 {
    1591 SCIP_CALL( solveCumulative(scip, nvars-1, vars, durations, demands, consdata->capacity, consdata->hmin, consdata->hmax, TRUE,
    1592 lbs, ubs, 2000LL, &solved, &infeasible, &unbounded, &error) );
    1593
    1594 if( !infeasible )
    1595 break;
    1596 nvars--;
    1597 }
    1598
    1599 /**@todo try to shrink the initial explanation */
    1600
    1602
    1603 for( v = 0; v < nvars; ++v )
    1604 {
    1605 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[v]) );
    1606
    1607 /* we have to add the lower and upper bounds of of the start time variable to have a valid reason */
    1608 SCIP_CALL( SCIPaddConflictLb(scip, vars[v], NULL) );
    1609 SCIP_CALL( SCIPaddConflictUb(scip, vars[v], NULL) );
    1610 }
    1611
    1612 /* perform conflict analysis */
    1614 }
    1615 else
    1616 {
    1617 SCIP_Bool infeasible;
    1618 SCIP_Bool tightened;
    1619 SCIP_Bool allfixed;
    1620 int v;
    1621
    1622 allfixed = TRUE;
    1623
    1624 for( v = 0; v < nvars; ++v )
    1625 {
    1626 /* check if variable is fixed */
    1627 if( lbs[v] + 0.5 > ubs[v] )
    1628 {
    1629 SCIP_CALL( SCIPfixVar(scip, vars[v], lbs[v], &infeasible, &tightened) );
    1630 assert(!infeasible);
    1631
    1632 if( tightened )
    1633 {
    1634 (*nfixedvars)++;
    1635 consdata->triedsolving = FALSE;
    1636 }
    1637 }
    1638 else
    1639 {
    1640 SCIP_CALL( SCIPtightenVarLb(scip, vars[v], lbs[v], TRUE, &infeasible, &tightened) );
    1641 assert(!infeasible);
    1642
    1643 if( tightened )
    1644 {
    1645 (*nchgbds)++;
    1646 consdata->triedsolving = FALSE;
    1647 }
    1648
    1649 SCIP_CALL( SCIPtightenVarUb(scip, vars[v], ubs[v], TRUE, &infeasible, &tightened) );
    1650 assert(!infeasible);
    1651
    1652 if( tightened )
    1653 {
    1654 (*nchgbds)++;
    1655 consdata->triedsolving = FALSE;
    1656 }
    1657
    1658 allfixed = FALSE;
    1659 }
    1660 }
    1661
    1662 /* if all variables are fixed, remove the optcumulative constraint since it is redundant */
    1663 if( allfixed )
    1664 {
    1666 (*ndelconss)++;
    1667 }
    1668 }
    1669 }
    1670
    1673
    1674 return SCIP_OKAY;
    1675}
    1676
    1677/** check if the given constraint is valid; checks each starting point of a job whether the remaining capacity is at
    1678 * least zero or not. If not (*violated) is set to TRUE
    1679 */
    1680static
    1682 SCIP* scip, /**< SCIP data structure */
    1683 SCIP_CONS* cons, /**< constraint to be checked */
    1684 SCIP_SOL* sol, /**< primal solution, or NULL for current LP/pseudo solution */
    1685 SCIP_Bool* violated, /**< pointer to store if the constraint is violated */
    1686 SCIP_Bool printreason /**< should the reason for the violation be printed? */
    1687 )
    1688{
    1689 SCIP_CONSDATA* consdata;
    1690 SCIP_VAR** binvars;
    1691 SCIP_VAR** vars;
    1692 SCIP_Bool auxiliary;
    1693 int* demands;
    1694 int* durations;
    1695 int nfixedones;
    1696 int nfixedzeros;
    1697 int nvars;
    1698
    1699 assert(scip != NULL);
    1700 assert(cons != NULL);
    1701 assert(violated != NULL);
    1702
    1703 consdata = SCIPconsGetData(cons);
    1704 assert(consdata != NULL);
    1705
    1706 SCIPdebugMessage("check optcumulative constraints <%s>\n", SCIPconsGetName(cons));
    1707
    1708 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, consdata->nvars) );
    1709 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    1710 SCIP_CALL( SCIPallocBufferArray(scip, &durations, consdata->nvars) );
    1711 SCIP_CALL( SCIPallocBufferArray(scip, &demands, consdata->nvars) );
    1712
    1713 /* collect information of all activities which are assigned to that machine in the given solution */
    1714 collectSolActivities(scip, consdata, sol, binvars, vars, durations, demands, &nvars, &nfixedones, &nfixedzeros, &auxiliary);
    1715
    1716 if( nvars > 0 )
    1717 {
    1718 /* check the cumulative condition */
    1719 SCIP_CALL( SCIPcheckCumulativeCondition(scip, sol, nvars, vars,
    1720 durations, demands, consdata->capacity, consdata->hmin, consdata->hmax, violated, cons, printreason) );
    1721 }
    1722
    1723 /* free all buffers */
    1724 SCIPfreeBufferArray(scip, &demands);
    1725 SCIPfreeBufferArray(scip, &durations);
    1726 SCIPfreeBufferArray(scip, &vars);
    1727 SCIPfreeBufferArray(scip, &binvars);
    1728
    1729 return SCIP_OKAY;
    1730}
    1731
    1732/** check if the given constraint is valid; checks each starting point of a job whether the remaining capacity is at
    1733 * least zero or not. If not (*violated) is set to TRUE
    1734 */
    1735static
    1737 SCIP* scip, /**< SCIP data structure */
    1738 SCIP_CONS* cons, /**< constraint to be checked */
    1739 SCIP_SOL* trysol, /**< primal solution to construct, or NULL */
    1740 SCIP_Bool* violated, /**< pointer to store if the constraint is violated/infeasible */
    1741 SCIP_Bool* consadded, /**< pointer to store if a constraint was added */
    1742 SCIP_Bool* solfeasible /**< pointer to store if the constraint solution is potentially feasible */
    1743 )
    1744{
    1745 SCIP_CONSDATA* consdata;
    1746 SCIP_VAR** binvars;
    1747 SCIP_VAR** vars;
    1748 SCIP_Bool auxiliary;
    1749 int* demands;
    1750 int* durations;
    1751 int nfixedones;
    1752 int nfixedzeros;
    1753 int nvars;
    1754
    1755 assert(scip != NULL);
    1756 assert(cons != NULL);
    1757 assert(violated != NULL);
    1758
    1759 consdata = SCIPconsGetData(cons);
    1760 assert(consdata != NULL);
    1761
    1762 SCIPdebugMessage("enforce optcumulative constraints <%s>\n", SCIPconsGetName(cons));
    1763
    1764 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, consdata->nvars) );
    1765 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    1766 SCIP_CALL( SCIPallocBufferArray(scip, &durations, consdata->nvars) );
    1767 SCIP_CALL( SCIPallocBufferArray(scip, &demands, consdata->nvars) );
    1768
    1769 /* collect information of all activities which are assigned to that machine in the given solution */
    1770 collectSolActivities(scip, consdata, NULL, binvars, vars, durations, demands, &nvars, &nfixedones, &nfixedzeros, &auxiliary);
    1771
    1772 (*violated) = FALSE;
    1773
    1774 if( nvars > 0 )
    1775 {
    1776 /* check the cumulative condition */
    1778 durations, demands, consdata->capacity, consdata->hmin, consdata->hmax, violated, cons, FALSE) );
    1779
    1780 if( *violated && auxiliary && !consdata->triedsolving )
    1781 {
    1782 SCIP_Real* lbs;
    1783 SCIP_Real* ubs;
    1784 SCIP_Bool infeasible;
    1785 SCIP_Bool unbounded;
    1786 SCIP_Bool error;
    1787 SCIP_Bool solved;
    1788
    1789 if( nfixedones == nvars )
    1790 consdata->triedsolving = TRUE;
    1791
    1792 SCIP_CALL( SCIPallocBufferArray(scip, &lbs, nvars) );
    1793 SCIP_CALL( SCIPallocBufferArray(scip, &ubs, nvars) );
    1794
    1795 /* solve the cumulative condition separately */
    1796 SCIP_CALL( solveCumulative(scip, nvars, vars, durations, demands, consdata->capacity, consdata->hmin, consdata->hmax,
    1797 FALSE, lbs, ubs, 1000LL, &solved, &infeasible, &unbounded, &error) );
    1798 assert(!unbounded);
    1799
    1800 if( !error )
    1801 {
    1802 if( infeasible )
    1803 {
    1804
    1805#ifdef SCIP_DISABLED_CODE
    1806 SCIP_Real* weights;
    1807 int v;
    1808
    1809 SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
    1810
    1811 for( v = 0; v < nvars; ++v )
    1812 {
    1813 int est;
    1814 int lst;
    1815
    1816 est = convertBoundToInt(scip, SCIPvarGetLbGlobal(vars[v]));
    1817 lst = convertBoundToInt(scip, SCIPvarGetUbGlobal(vars[v]));
    1818 weights[v] = (lst - est) / (consdata->demands[v] * consdata->durations[v]);
    1819 }
    1820 SCIPsortRealPtrPtrIntInt(weights, (void*)binvars, (void*)vars, durations, demands, nvars);
    1821
    1822 SCIPfreeBufferArray(scip, &weights);
    1823
    1824 while( nvars > 1 && !SCIPisStopped(scip) )
    1825 {
    1826 SCIP_CALL( solveCumulative(scip, nvars-1, vars, durations, demands, consdata->capacity, consdata->hmin, consdata->hmax,
    1827 FALSE, lbs, ubs, 1000LL, &solved, &infeasible, &unbounded, &error) );
    1828
    1829 if( !infeasible )
    1830 break;
    1831
    1832 nvars--;
    1833 }
    1834#endif
    1835
    1836 /* create and adds a conflict constraint (logicor constraint) */
    1837 SCIP_CALL( createConflictCons(scip, SCIPconsGetName(cons), binvars, nvars) );
    1838
    1839 (*solfeasible) = FALSE;
    1840 (*consadded) = TRUE;
    1841 }
    1842 else if( solved && *solfeasible && trysol != NULL )
    1843 {
    1844 int v;
    1845
    1846 for(v = 0; v < nvars; ++v )
    1847 {
    1848 SCIP_CALL( SCIPsetSolVal(scip, trysol, vars[v], lbs[v]) );
    1849 }
    1850 }
    1851 else
    1852 (*solfeasible) = FALSE;
    1853 }
    1854
    1857 }
    1858 }
    1859
    1860 /* free all buffers */
    1861 SCIPfreeBufferArray(scip, &demands);
    1862 SCIPfreeBufferArray(scip, &durations);
    1863 SCIPfreeBufferArray(scip, &vars);
    1864 SCIPfreeBufferArray(scip, &binvars);
    1865
    1866 return SCIP_OKAY;
    1867}
    1868
    1869/** upgrade constraints to an cumulative constraint */
    1870static
    1872 SCIP* scip, /**< SCIP data structure */
    1873 SCIP_CONS* cons, /**< constraint to be checked */
    1874 int* ndelconss, /**< pointer to store the number of deleted constraints */
    1875 int* nupgdconss, /**< pointer to store the number of upgrade constraints */
    1876 SCIP_Bool* mustpropagate /**< pointer to store if the constraints has to be propagated */
    1877 )
    1878{
    1879 SCIP_CONSDATA* consdata;
    1880 int nvars;
    1881
    1882 consdata = SCIPconsGetData(cons);
    1883 assert(consdata != NULL);
    1884
    1885 nvars = consdata->nvars;
    1886
    1887 /* (debug) check if the counter of the constraint are correct */
    1888 checkCounters(consdata);
    1889
    1890 if( nvars == 0 && consdata->nfixedzeros == nvars )
    1891 {
    1892 SCIPdebugMessage("delete optcumulative constraint <%s> since it contains no jobs\n", SCIPconsGetName(cons));
    1893 SCIP_CALL( SCIPdelCons(scip, cons) );
    1894 (*ndelconss)++;
    1895 (*mustpropagate) = FALSE;
    1896 }
    1897 else if( nvars == 1 )
    1898 {
    1899 SCIPdebugMessage("delete optcumulative constraint <%s> since it contains only one jobs\n", SCIPconsGetName(cons));
    1900
    1901 if( consdata->capacity < consdata->demands[0] )
    1902 {
    1903 SCIP_Bool infeasible;
    1904 SCIP_Bool tightened;
    1905
    1906 SCIP_CALL( SCIPfixVar(scip, consdata->binvars[0], 0.0, &infeasible, &tightened) );
    1907 assert(!infeasible);
    1908 assert(tightened);
    1909 }
    1910
    1911 SCIP_CALL( SCIPdelCons(scip, cons) );
    1912 (*ndelconss)++;
    1913 (*mustpropagate) = FALSE;
    1914 }
    1915 else if( consdata->nglbfixedones == nvars )
    1916 {
    1917 SCIP_CONS* cumulativecons;
    1918 char name[SCIP_MAXSTRLEN];
    1919
    1920 SCIPdebugMessage("upgrade optcumulative constraint <%s> to cumulative constraint\n", SCIPconsGetName(cons));
    1921
    1922 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_cumulative", SCIPconsGetName(cons));
    1923
    1924 SCIP_CALL( SCIPcreateConsCumulative(scip, &cumulativecons, name, consdata->nvars, consdata->vars, consdata->durations, consdata->demands, consdata->capacity,
    1927 SCIP_CALL( SCIPsetHminCumulative(scip, cumulativecons, consdata->hmin) );
    1928 SCIP_CALL( SCIPsetHmaxCumulative(scip, cumulativecons, consdata->hmax) );
    1929 SCIP_CALL( SCIPaddCons(scip, cumulativecons) );
    1930 SCIP_CALL( SCIPreleaseCons(scip, &cumulativecons) );
    1931
    1932 assert(!SCIPconsIsDeleted(cons));
    1933 SCIP_CALL( SCIPdelCons(scip, cons) );
    1934
    1935 (*nupgdconss)++;
    1936 (*mustpropagate) = FALSE;
    1937 }
    1938 else if( consdata->nfixedones + consdata->nfixedzeros == nvars && consdata->nfixedones > 0 )
    1939 {
    1940 SCIP_CONS* cumulativecons;
    1941
    1942 SCIP_VAR** binvars;
    1943 SCIP_VAR** vars;
    1944 int* durations;
    1945 int* demands;
    1946 int nfixedzeros;
    1947 int nfixedones;
    1948
    1949 SCIP_Bool auxiliary;
    1950
    1951 char name[SCIP_MAXSTRLEN];
    1952
    1953 SCIPdebugMessage("upgrade optcumulative constraint <%s> to cumulative constraint (locally)\n", SCIPconsGetName(cons));
    1954
    1955 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_cumulative", SCIPconsGetName(cons));
    1956
    1957 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    1958 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, consdata->nvars) );
    1959 SCIP_CALL( SCIPallocBufferArray(scip, &demands, consdata->nvars) );
    1960 SCIP_CALL( SCIPallocBufferArray(scip, &durations, consdata->nvars) );
    1961
    1962 /* collect all activities which are locally assigned to that machine */
    1963 collectActivities(consdata, binvars, vars, durations, demands, &nfixedones, &nfixedzeros, &auxiliary);
    1964
    1965 SCIP_CALL( SCIPcreateConsCumulative(scip, &cumulativecons, name, nfixedones, vars, durations, demands, consdata->capacity,
    1968 SCIP_CALL( SCIPsetHminCumulative(scip, cumulativecons, consdata->hmin) );
    1969 SCIP_CALL( SCIPsetHmaxCumulative(scip, cumulativecons, consdata->hmax) );
    1970 SCIP_CALL( SCIPaddConsLocal(scip, cumulativecons, NULL) );
    1971 SCIP_CALL( SCIPreleaseCons(scip, &cumulativecons) );
    1972
    1973 /* free all buffers */
    1974 SCIPfreeBufferArray(scip, &durations);
    1975 SCIPfreeBufferArray(scip, &demands);
    1976 SCIPfreeBufferArray(scip, &binvars);
    1977 SCIPfreeBufferArray(scip, &vars);
    1978
    1979 assert(!SCIPconsIsDeleted(cons));
    1981
    1982 (*nupgdconss)++;
    1983 (*mustpropagate) = FALSE;
    1984 }
    1985 else
    1986 assert(consdata->nvars > 1);
    1987
    1988 return SCIP_OKAY;
    1989}
    1990
    1991/** since the binary variable is fixed to zero, depending in the objective coefficient of the integer variable and the
    1992 * rounding locks, we might can fix the integer variable
    1993 */
    1994static
    1996 SCIP* scip, /**< SCIP data structure */
    1997 SCIP_VAR* var, /**< integer variable to fix */
    1998 SCIP_Bool downlock, /**< does the variable has down lock given by the optcumulative constraint */
    1999 SCIP_Bool uplock, /**< does the variable has up lock given by the optcumulative constraint */
    2000 int* nchgbds /**< pointer to store the number changed variable bounds */
    2001 )
    2002{
    2003 SCIP_Real objval;
    2004 SCIP_Real fixvalue;
    2005 SCIP_Bool infeasible;
    2006 SCIP_Bool tightened;
    2007
    2008 objval = SCIPvarGetObj(var);
    2009 fixvalue = SCIP_INVALID;
    2010
    2011 /* if SCIP is in probing mode or during repropagation we cannot perform this dual reductions since this dual
    2012 * reduction would end in an implication which can lead to cutoff the optimal solution
    2013 */
    2015 return SCIP_OKAY;
    2016
    2017 assert(SCIPvarGetNLocksDown(var) >= (int)downlock);
    2018 assert(SCIPvarGetNLocksUp(var) >= (int)uplock);
    2019
    2020 if( SCIPisZero(scip, objval) )
    2021 {
    2022 /* the integer start time variable has a zero objective value; if only the optcumulative constraint
    2023 * handler has a problem with rounding it down or up, then this issue is obsolete since binary
    2024 * variable is fixed zero; therefore, rounding the integer down or up is a feasible dual reduction
    2025 */
    2026 if( SCIPvarGetNLocksDown(var) == (int)downlock )
    2027 fixvalue = SCIPvarGetLbLocal(var);
    2028 else if( SCIPvarGetNLocksUp(var) == (int)uplock )
    2029 fixvalue = SCIPvarGetUbLocal(var);
    2030 else
    2031 return SCIP_OKAY;
    2032 }
    2033 else if( SCIPisNegative(scip, objval) && SCIPvarGetNLocksUp(var) == (int)uplock )
    2034 {
    2035 /* the integer start time variable has a negative objective value and only the optcumulative constraint
    2036 * handler has a problem with rounding it up; since the binary variable is fixed the rounding up
    2037 * issue is obsolete; there rounding it to the upper bound is the best thing we can do
    2038 */
    2039 fixvalue = SCIPvarGetUbLocal(var);
    2040 }
    2041 else if( SCIPisPositive(scip, objval) && SCIPvarGetNLocksDown(var) == (int)downlock )
    2042 {
    2043 /* the integer start time variable has a positive objective value and only the optcumulative
    2044 * constraint handler has a problem with rounding it down; since the binary variable is fixed the
    2045 * rounding down issue is obsolete; there rounding it to the lower bound is the best thing we can do
    2046 */
    2047 fixvalue = SCIPvarGetLbLocal(var);
    2048 }
    2049 else
    2050 return SCIP_OKAY;
    2051
    2052 /* the integer start time variable has a positive objective value and only the optcumulative
    2053 * constraint handler has a problem with rounding it down; since the binary variable is fixed the
    2054 * rounding down issue is obsolete; there rounding it to the lower bound is the best thing we can do
    2055 */
    2056 assert(fixvalue < SCIP_INVALID);
    2057 SCIP_CALL( SCIPfixVar(scip, var, fixvalue, &infeasible, &tightened) );
    2058 assert(!infeasible);
    2059
    2060 if( tightened )
    2061 (*nchgbds)++;
    2062
    2063 return SCIP_OKAY;
    2064}
    2065
    2066/** deletes coefficient at given position from constraint data */
    2067static
    2069 SCIP* scip, /**< SCIP data structure */
    2070 SCIP_CONSDATA* consdata, /**< cumulative constraint data */
    2071 SCIP_CONS* cons, /**< knapsack constraint */
    2072 int pos /**< position of coefficient to delete */
    2073 )
    2074{
    2075 assert(consdata != NULL);
    2076 assert(pos < consdata->nvars);
    2077
    2078 /* remove the rounding locks for the deleted variable */
    2079 SCIP_CALL( unlockRounding(scip, cons, consdata->binvars[pos],
    2080 consdata->vars[pos], consdata->downlocks[pos], consdata->uplocks[pos]) );
    2081
    2082 consdata->downlocks[pos] = FALSE;
    2083 consdata->uplocks[pos] = FALSE;
    2084
    2085 if( SCIPconsIsTransformed(cons) )
    2086 {
    2087 SCIP_CONSHDLR* conshdlr;
    2088 SCIP_CONSHDLRDATA* conshdlrdata;
    2089
    2090 /* get event handler */
    2091 conshdlr = SCIPconsGetHdlr(cons);
    2092 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2093 assert(conshdlrdata != NULL);
    2094 assert(conshdlrdata->eventhdlrbinvars != NULL);
    2095 assert(conshdlrdata->eventhdlrintvars != NULL);
    2096
    2097 /* drop bound change events of variable */
    2098 SCIP_CALL( dropEventBinvar(scip, cons, conshdlrdata->eventhdlrbinvars, pos) );
    2099 SCIP_CALL( dropEventIntvar(scip, cons, conshdlrdata->eventhdlrintvars, pos) );
    2100 }
    2101
    2102 assert(consdata->nglbfixedzeros >= 0);
    2103 assert(consdata->nglbfixedones >= 0);
    2104 assert(consdata->nfixedzeros >= 0);
    2105 assert(consdata->nfixedones >= 0);
    2106
    2107 SCIPdebugMessage("remove variable <%s> from optcumulative constraint <%s>\n",
    2108 SCIPvarGetName(consdata->binvars[pos]), SCIPconsGetName(cons));
    2109
    2110 if( pos != consdata->nvars - 1 )
    2111 {
    2112 consdata->binvars[pos] = consdata->binvars[consdata->nvars-1];
    2113 consdata->vars[pos] = consdata->vars[consdata->nvars-1];
    2114 consdata->demands[pos] = consdata->demands[consdata->nvars-1];
    2115 consdata->durations[pos] = consdata->durations[consdata->nvars-1];
    2116 consdata->downlocks[pos] = consdata->downlocks[consdata->nvars-1];
    2117 consdata->uplocks[pos] = consdata->uplocks[consdata->nvars-1];
    2118 }
    2119
    2120 consdata->nvars--;
    2121
    2122 /* (debug) check if the counter of the constraint are correct */
    2123 checkCounters(consdata);
    2124
    2125 consdata->relaxadded = FALSE;
    2126 consdata->normalized = FALSE;
    2127
    2128 return SCIP_OKAY;
    2129}
    2130
    2131/** remove all jobs for which the binary variable is globally fixed to zero */
    2132static
    2134 SCIP* scip, /**< SCIP data structure */
    2135 SCIP_CONS* cons, /**< constraint to be checked */
    2136 int* nchgcoefs, /**< pointer to store the number changed coefficients */
    2137 int* nchgbds /**< pointer to store the number changed variable bounds */
    2138 )
    2139{
    2140 SCIP_CONSDATA* consdata;
    2141 int v;
    2142
    2143 consdata = SCIPconsGetData(cons);
    2144 assert(consdata != NULL);
    2145
    2146 for( v = consdata->nvars-1; v >= 0 && consdata->nglbfixedzeros > 0; --v )
    2147 {
    2148 assert(consdata->binvars[v] != NULL);
    2149 if( SCIPvarGetUbGlobal(consdata->binvars[v]) < 0.5 )
    2150 {
    2151 SCIPdebugMessage("variable <%s> is globally fixed to zero\n", SCIPvarGetName(consdata->binvars[v]));
    2152
    2153 /* fix integer start time variable if possible */
    2154 if( SCIPconsIsChecked(cons) )
    2155 {
    2156 SCIP_CALL( fixIntegerVariable(scip, consdata->vars[v], consdata->downlocks[v], consdata->uplocks[v], nchgbds) );
    2157 }
    2158
    2159 /* remove the job */
    2160 SCIP_CALL( consdataDeletePos(scip, consdata, cons, v) );
    2161 (*nchgcoefs)++;
    2162
    2163 /* mark constraint to be checked for redundancy */
    2164 consdata->triedredundant = TRUE;
    2165 }
    2166 }
    2167
    2168 /* (debug) check if the counter of the constraint are correct */
    2169 checkCounters(consdata);
    2170
    2171 /* check that all variables fixed to zero are removed */
    2172 assert(consdata->nglbfixedzeros == 0);
    2173
    2174 return SCIP_OKAY;
    2175}
    2176
    2177/** remove jobs which have a duration or demand of zero (zero energy) or lay outside the efficient horizon [hmin, hmax);
    2178 * this is done in the SCIP_DECL_CONSINITPRE() callback
    2179 */
    2180static
    2182 SCIP* scip, /**< SCIP data structure */
    2183 SCIP_CONS* cons /**< constraint to propagate */
    2184 )
    2185{
    2186 SCIP_CONSDATA* consdata;
    2187 SCIP_VAR* var;
    2188 int demand;
    2189 int duration;
    2190 int hmin;
    2191 int hmax;
    2192 int est;
    2193 int lct;
    2194 int j;
    2195
    2196 assert(scip != NULL);
    2197 assert(cons != NULL);
    2198
    2199 consdata = SCIPconsGetData(cons);
    2200 assert(consdata != NULL);
    2201
    2202 hmin = consdata->hmin;
    2203 hmax = consdata->hmax;
    2204
    2205 SCIPdebugMessage("check for irrelevant jobs within cumulative constraint <%s>[%d,%d)\n",
    2206 SCIPconsGetName(cons), hmin, hmax);
    2207
    2208 for( j = consdata->nvars-1; j >= 0; --j )
    2209 {
    2210 var = consdata->vars[j];
    2211 demand = consdata->demands[j];
    2212 duration = consdata->durations[j];
    2213
    2214 /* earliest completion time (ect) and latest start time (lst) */
    2216 lct = convertBoundToInt(scip, SCIPvarGetUbGlobal(var)) + duration;
    2217
    2218 if( demand == 0 || duration == 0 )
    2219 {
    2220 /* jobs with zero demand or zero duration can be removed */
    2221 SCIPdebugMessage(" remove variable <%s> due to zero %s\n",
    2222 SCIPvarGetName(var), demand == 0 ? "demand" : "duration");
    2223
    2224 /* remove variable form constraint */
    2225 SCIP_CALL( consdataDeletePos(scip, consdata, cons, j) );
    2226 }
    2227 else if( est >= hmax || lct <= hmin )
    2228 {
    2229 SCIPdebugMessage(" remove variable <%s>[%d,%d] with duration <%d>\n",
    2230 SCIPvarGetName(var), est, lct - duration, duration);
    2231
    2232 /* delete variable at the given position */
    2233 SCIP_CALL( consdataDeletePos(scip, consdata, cons, j) );
    2234 }
    2235 }
    2236
    2237 return SCIP_OKAY;
    2238}
    2239
    2240/** presolve cumulative condition w.r.t. effective horizon by detecting irrelevant variables */
    2241static
    2243 SCIP* scip, /**< SCIP data structure */
    2244 SCIP_CONS* cons, /**< constraint to be checked */
    2245 int* nfixedvars, /**< pointer to store the number of fixed variables */
    2246 int* nchgcoefs, /**< pointer to store the number of changed coefficients */
    2247 int* nchgsides, /**< pointer to store the number of changed sides */
    2248 SCIP_Bool* cutoff /**< buffer to store whether a cutoff is detected */
    2249 )
    2250{
    2251 SCIP_CONSDATA* consdata;
    2252 SCIP_Bool* irrelevants;
    2253 int nvars;
    2254 int v;
    2255
    2256 consdata = SCIPconsGetData(cons);
    2257 assert(consdata != NULL);
    2258
    2259 nvars = consdata->nvars;
    2260 assert(nvars > 1);
    2261
    2262 SCIP_CALL( SCIPallocBufferArray(scip, &irrelevants, nvars) );
    2263 BMSclearMemoryArray(irrelevants, nvars);
    2264
    2265 /* use presolving of cumulative constraint handler to process cumulative condition */
    2266 SCIP_CALL( SCIPpresolveCumulativeCondition(scip, nvars, consdata->vars, consdata->durations,
    2267 consdata->hmin, consdata->hmax, consdata->downlocks, consdata->uplocks, cons,
    2268 irrelevants, nfixedvars, nchgsides, cutoff) );
    2269
    2270 /* remove all variable which are irrelevant; note we have to iterate backwards do to the functionality of of
    2271 * consdataDeletePos()
    2272 */
    2273 for( v = nvars-1; v >= 0; --v )
    2274 {
    2275 SCIP_VAR* var;
    2276 int ect;
    2277 int lst;
    2278
    2279 if( !irrelevants[v] )
    2280 continue;
    2281
    2282 var = consdata->vars[v];
    2283 assert(var != NULL);
    2284
    2285 ect = convertBoundToInt(scip, SCIPvarGetLbGlobal(var)) + consdata->durations[v];
    2287
    2288 /* check if the jobs runs completely during the effective horizon */
    2289 if( lst <= consdata->hmin && ect >= consdata->hmax )
    2290 {
    2291 assert(!consdata->downlocks[v]);
    2292 assert(!consdata->uplocks[v]);
    2293
    2294 if( consdata->capacity < consdata->demands[v] )
    2295 {
    2296 SCIP_Bool infeasible;
    2297 SCIP_Bool tightened;
    2298
    2299 SCIP_CALL( SCIPfixVar(scip, consdata->binvars[0], 0.0, &infeasible, &tightened) );
    2300 assert(!infeasible);
    2301 assert(tightened);
    2302 (*nfixedvars)++;
    2303
    2304 consdata->capacity -= consdata->demands[v];
    2305
    2306 SCIP_CALL( consdataDeletePos(scip, consdata, cons, v) );
    2307 (*nchgcoefs)++;
    2308 }
    2309 }
    2310 else
    2311 {
    2312 SCIP_CALL( consdataDeletePos(scip, consdata, cons, v) );
    2313 (*nchgcoefs)++;
    2314 }
    2315 }
    2316
    2317 SCIPdebugMessage("constraint <%s>[%d,%d) <= %d has %d variables left\n", SCIPconsGetName(cons),
    2318 consdata->hmin, consdata->hmax, consdata->capacity, nvars);
    2319
    2320 SCIPfreeBufferArray(scip, &irrelevants);
    2321
    2322 return SCIP_OKAY;
    2323}
    2324
    2325/** create an an set partitioning constraint */
    2326static
    2328 SCIP* scip, /**< SCIP data structure */
    2329 SCIP_VAR* var1, /**< first variable */
    2330 SCIP_VAR* var2 /**< second variable */
    2331 )
    2332{
    2333 SCIP_CONS* cons;
    2334
    2335 SCIP_CALL( SCIPcreateConsBasicSetpack(scip, &cons, "implication", 0, NULL) );
    2336 SCIP_CALL( SCIPaddCons(scip, cons) );
    2337
    2338 SCIP_CALL( SCIPaddCoefSetppc(scip, cons, var1) );
    2339 SCIP_CALL( SCIPaddCoefSetppc(scip, cons, var2) );
    2341 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2342
    2343 return SCIP_OKAY;
    2344}
    2345
    2346/** create variable bound constraint */
    2347static
    2349 SCIP* scip, /**< SCIP data structure */
    2350 SCIP_VAR* binvar, /**< binary variable x */
    2351 SCIP_VAR* intvar, /**< integer variable y */
    2352 int bound, /**< variable bound */
    2353 SCIP_Bool lower /**< variable lower bound? (Otherwise upper bound) */
    2354 )
    2355{
    2356 SCIP_CONS* cons;
    2357 SCIP_Real coef;
    2358 SCIP_Real lhs;
    2359 SCIP_Real rhs;
    2360
    2361 assert(scip != NULL);
    2362
    2363 if( lower )
    2364 {
    2365 lhs = SCIPvarGetLbGlobal(intvar);
    2366 rhs = SCIPinfinity(scip);
    2367 coef = lhs - bound;
    2368 }
    2369 else
    2370 {
    2371 lhs = -SCIPinfinity(scip);
    2372 rhs = SCIPvarGetUbGlobal(intvar);
    2373 coef = rhs - bound;
    2374 }
    2375
    2376 SCIP_CALL( SCIPcreateConsBasicVarbound(scip, &cons, "implication", intvar, binvar, coef, lhs, rhs) );
    2377 SCIP_CALL( SCIPaddCons(scip, cons) );
    2379 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2380
    2381 return SCIP_OKAY;
    2382}
    2383
    2384/** create bound disjunction constraint */
    2385static
    2387 SCIP* scip, /**< SCIP data structure */
    2388 SCIP_VAR* binvar, /**< binary variable x */
    2389 SCIP_VAR* intvar, /**< integer variable y */
    2390 int lb, /**< lower bound */
    2391 int ub /**< lower bound */
    2392 )
    2393{
    2394 SCIP_CONS* cons;
    2395 SCIP_VAR** vars;
    2396 SCIP_BOUNDTYPE* boundtypes;
    2397 SCIP_Real* bounds;
    2398
    2399 SCIP_CALL( SCIPallocBufferArray(scip, &vars, 3) );
    2400 SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, 3) );
    2401 SCIP_CALL( SCIPallocBufferArray(scip, &bounds, 3) );
    2402
    2403 /* intvar >= ub */
    2404 vars[0] = intvar;
    2405 boundtypes[0] = SCIP_BOUNDTYPE_LOWER;
    2406 bounds[0] = ub;
    2407
    2408 /* intvar <= lb */
    2409 vars[1] = intvar;
    2410 boundtypes[1] = SCIP_BOUNDTYPE_UPPER;
    2411 bounds[1] = lb;
    2412
    2413 /* binvar <= 0.0 */
    2414 vars[2] = binvar;
    2415 boundtypes[2] = SCIP_BOUNDTYPE_LOWER;
    2416 bounds[2] = 0.0;
    2417
    2418 SCIP_CALL( SCIPcreateConsBasicBounddisjunction(scip, &cons, "implication", 3, vars, boundtypes, bounds) );
    2419 SCIP_CALL( SCIPaddCons(scip, cons) );
    2421 SCIP_CALL( SCIPreleaseCons(scip, &cons) );
    2422
    2423 SCIPfreeBufferArray(scip, &vars);
    2424 SCIPfreeBufferArray(scip, &boundtypes);
    2425 SCIPfreeBufferArray(scip, &bounds);
    2426
    2427 return SCIP_OKAY;
    2428}
    2429
    2430/** detect implication */
    2431static
    2433 SCIP* scip, /**< SCIP data structure */
    2434 SCIP_CONS* cons, /**< optcumulative constraint */
    2435 int* nchgcoefs, /**< pointer to store the number of changed coefficients */
    2436 int* naddconss /**< pointer to store the number of added constraints */
    2437 )
    2438{
    2439 SCIP_CONSDATA* consdata;
    2440 SCIP_VAR** binvars;
    2441 SCIP_VAR** vars;
    2442 int* durations;
    2443 int hmin;
    2444 int hmax;
    2445 int v;
    2446
    2447 consdata = SCIPconsGetData(cons);
    2448 assert(consdata != NULL);
    2449
    2450 vars = consdata->vars;
    2451 binvars = consdata->binvars;
    2452 durations = consdata->durations;
    2453
    2454 hmin = consdata->hmin;
    2455 hmax = consdata->hmax;
    2456 assert(hmin < hmax);
    2457
    2458 SCIPdebugMessage("search for implications <%s>[%d,%d) <= %d\n", SCIPconsGetName(cons), hmin, hmax, consdata->capacity);
    2459
    2460 /* we loop backwards since we are deleting variable out of the constraint */
    2461 for( v = consdata->nvars-1; v >= 0; --v )
    2462 {
    2463 SCIP_VAR* var;
    2464 int start;
    2465 int end;
    2466
    2467 var = vars[v];
    2468 assert(var != NULL);
    2469
    2470 /* skip start time variables which are not globally fixed */
    2471 if( SCIPvarGetLbGlobal(var) + 0.5 < SCIPvarGetUbGlobal(var) )
    2472 continue;
    2473
    2474 /* adjust the code for resources with capacity larger than one ??????????????? */
    2475 if( consdata->demands[v] < consdata->capacity )
    2476 continue;
    2477
    2479 assert(start < hmax);
    2480
    2481 end = start + durations[v];
    2482 assert(end > hmin);
    2483
    2484 SCIPdebugMessage("candidate <%s> (start %d, end %d, demand %d)\n", SCIPvarGetName(var), start, end, consdata->demands[v]);
    2485
    2486 if( start <= hmin && end >= hmax )
    2487 {
    2488 int j;
    2489
    2490 /* job runs during the complete time horizon */
    2491 for( j = 0; j < consdata->nvars; ++j )
    2492 {
    2493 SCIP_VAR* implvar;
    2494 int est;
    2495 int ect;
    2496 int lst;
    2497
    2498 if( j == v )
    2499 continue;
    2500
    2501 implvar = vars[j];
    2502 assert(implvar != NULL);
    2503
    2504 est = convertBoundToInt(scip, SCIPvarGetLbGlobal(implvar));
    2505 ect = est + durations[j];
    2506 lst = convertBoundToInt(scip, SCIPvarGetUbGlobal(implvar));
    2507
    2508 SCIPdebugMessage("variable <%s>[%d,%d] (duration %d, demand %d)\n", SCIPvarGetName(implvar), est, lst, durations[j], consdata->demands[j]);
    2509
    2510 /* check if the job will overlap with effective horizon, hence, only one of the two jobs can be scheduled on
    2511 * that machine
    2512 */
    2513 if( ect > hmin && lst < hmax )
    2514 {
    2515 SCIP_CALL( createSetPackingCons(scip, binvars[v], binvars[j]) );
    2516 (*naddconss)++;
    2517 }
    2518 else if( lst < hmax )
    2519 {
    2520 SCIP_CALL( createVarboundCons(scip, binvars[v], implvar, hmin - durations[j], FALSE) );
    2521 (*naddconss)++;
    2522 }
    2523 else if( ect > hmin )
    2524 {
    2525 SCIP_CALL( createVarboundCons(scip, binvars[v], implvar, hmax, TRUE) );
    2526 (*naddconss)++;
    2527 }
    2528 else
    2529 {
    2530 SCIP_CALL( createBounddisjunctionCons(scip, binvars[v], implvar, hmin - durations[j], hmax) );
    2531 (*naddconss)++;
    2532 }
    2533 }
    2534 }
    2535 else if( start <= hmin )
    2536 {
    2537 int j;
    2538
    2539 assert(end > hmin);
    2540
    2541 /* job overlaps with hmin */
    2542 for( j = 0; j < consdata->nvars; ++j )
    2543 {
    2544 SCIP_VAR* implvar;
    2545 int est;
    2546 int ect;
    2547 int lst;
    2548
    2549 if( j == v )
    2550 continue;
    2551
    2552 implvar = vars[j];
    2553 assert(implvar != NULL);
    2554
    2555 est = convertBoundToInt(scip, SCIPvarGetLbGlobal(implvar));
    2556 ect = est + durations[j];
    2557 lst = convertBoundToInt(scip, SCIPvarGetUbGlobal(implvar));
    2558
    2559 SCIPdebugMessage("variable <%s>[%d,%d] (duration %d, demand %d)\n", SCIPvarGetName(implvar), est, lst, durations[j], consdata->demands[j]);
    2560
    2561 if( lst < ect && hmin < ect && lst < end )
    2562 {
    2563 /* job j has a core which overlaps with job v within the effective horizon, hence, both jobs cannot run
    2564 * at same time on that machine
    2565 */
    2566 SCIP_CALL( createSetPackingCons(scip, binvars[v], binvars[j]) );
    2567 (*naddconss)++;
    2568 }
    2569 else if( end > lst )
    2570 {
    2571 SCIP_CALL( createSetPackingCons(scip, binvars[v], binvars[j]) );
    2572 (*naddconss)++;
    2573 }
    2574 else if( est < end )
    2575 {
    2576 SCIP_CALL( createVarboundCons(scip, binvars[v], implvar, end, TRUE) );
    2577 (*naddconss)++;
    2578 }
    2579 }
    2580 }
    2581 else if( end >= hmax )
    2582 {
    2583 int j;
    2584
    2585 assert(start < hmax);
    2586
    2587 /* job overlaps with hmax; that means if the job is scheduled on that machine all other jobs have to finish
    2588 * before that job starts
    2589 */
    2590 for( j = 0; j < consdata->nvars; ++j )
    2591 {
    2592 SCIP_VAR* implvar;
    2593 int ect;
    2594 int lst;
    2595 int lct;
    2596
    2597 if( j == v )
    2598 continue;
    2599
    2600 implvar = vars[j];
    2601 assert(implvar != NULL);
    2602
    2603 ect = convertBoundToInt(scip, SCIPvarGetLbGlobal(implvar)) + durations[j];
    2604 lst = convertBoundToInt(scip, SCIPvarGetUbGlobal(implvar));
    2605 lct = lst + durations[j];
    2606
    2607 SCIPdebugMessage("variable <%s>[%d,%d] (duration %d, demand %d)\n", SCIPvarGetName(implvar), ect - durations[j], lst, durations[j], consdata->demands[j]);
    2608
    2609 if( lst < ect && start < ect && lst < hmax )
    2610 {
    2611 /* job j has a core which overlaps with job v within the effective horizon, hence, both jobs cannot run
    2612 * at same time on that machine
    2613 */
    2614 SCIP_CALL( createSetPackingCons(scip, binvars[v], binvars[j]) );
    2615 (*naddconss)++;
    2616 }
    2617 else if( start < ect )
    2618 {
    2619 SCIP_CALL( createSetPackingCons(scip, binvars[v], binvars[j]) );
    2620 (*naddconss)++;
    2621 }
    2622 else if( lct > start )
    2623 {
    2624 /* job j potentially finishes to late, hence, if job v runs on that machine we can bound the start time
    2625 * variable of job j form above
    2626 */
    2627 SCIP_CALL( createVarboundCons(scip, binvars[v], implvar, start - durations[j], FALSE) );
    2628 (*naddconss)++;
    2629 }
    2630 }
    2631 }
    2632 else
    2633 continue;
    2634
    2635 SCIP_CALL( consdataDeletePos(scip, consdata, cons, v) );
    2636 (*nchgcoefs)++;
    2637 }
    2638
    2639 return SCIP_OKAY;
    2640}
    2641
    2642/** propgates given constraint */
    2643static
    2645 SCIP* scip, /**< SCIP data structure */
    2646 SCIP_CONS* cons, /**< constraint to be checked */
    2647 SCIP_Bool conflictanalysis, /**< should conflict analysis be called for infeasible subproblems */
    2648 int* nfixedvars, /**< pointer to store the number of fixed variables */
    2649 int* nchgbds, /**< pointer to store the number changed variable bounds */
    2650 int* ndelconss, /**< pointer to store the number of deleted constraints */
    2651 SCIP_Bool* cutoff /**< pointer to store if a cutoff (infeasibility) was detected */
    2652 )
    2653{
    2654 SCIP_CONSDATA* consdata;
    2655 SCIP_VAR** binvars;
    2656 SCIP_VAR** vars;
    2657 SCIP_Bool auxiliary;
    2658 int* durations;
    2659 int* demands;
    2660 int nfixedones;
    2661 int nfixedzeros;
    2662 int v;
    2663
    2664 assert(cutoff != NULL);
    2665 assert(*cutoff == FALSE);
    2666
    2667 consdata = SCIPconsGetData(cons);
    2668 assert(consdata != NULL);
    2669 assert(consdata->nvars > 1);
    2670
    2671 /* (debug) check if the counter of the constraint are correct */
    2672 checkCounters(consdata);
    2673
    2674 if( consdata->propagated && (consdata->nfixedones + consdata->nfixedzeros < consdata->nvars || consdata->triedsolving) )
    2675 return SCIP_OKAY;
    2676
    2677 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    2678 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, consdata->nvars) );
    2679 SCIP_CALL( SCIPallocBufferArray(scip, &demands, consdata->nvars) );
    2680 SCIP_CALL( SCIPallocBufferArray(scip, &durations, consdata->nvars) );
    2681
    2682 /* collect all activities which are locally assigned to that machine */
    2683 collectActivities(consdata, binvars, vars, durations, demands, &nfixedones, &nfixedzeros, &auxiliary);
    2684
    2685 /* if more than one variable is assigned to that machine propagate the cumulative condition */
    2686 if( !consdata->propagated && nfixedones > 1 )
    2687 {
    2688 SCIP_Bool* explanation;
    2689 SCIP_Bool initialized;
    2690
    2691 initialized = FALSE;
    2692
    2693 SCIP_CALL( SCIPallocBufferArray(scip, &explanation, nfixedones) );
    2694 BMSclearMemoryArray(explanation, nfixedones);
    2695
    2696 /* propagate cumulative condition */
    2698 durations, demands, consdata->capacity, consdata->hmin, consdata->hmax, cons, nchgbds, &initialized, explanation, cutoff) );
    2699
    2700 /* in case of a conflict we have to extend the initial reason before the conflict analysis starts */
    2701 if( initialized && conflictanalysis )
    2702 {
    2703 assert(*cutoff == TRUE);
    2704
    2705 for( v = 0; v < nfixedones; ++v )
    2706 {
    2707 if( explanation[v] )
    2708 {
    2709 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[v]) );
    2710 }
    2711 }
    2712
    2713 /* perform conflict analysis */
    2715 }
    2716
    2717 SCIPfreeBufferArray(scip, &explanation);
    2718 }
    2719 assert(consdata->nvars > 1);
    2720
    2721 /* if we are still feasible we can try to perform dual reductions; Note that we have to avoid dual reductions during
    2722 * probing since these dual reductions can lead to wrong implications; the same hold in case of repropagating
    2723 */
    2724 if( !(*cutoff) && !SCIPinProbing(scip) && !SCIPinRepropagation(scip) )
    2725 {
    2726 if( nfixedzeros + nfixedones == consdata->nvars )
    2727 {
    2728 /* all binary variables are fixed */
    2729
    2730 if( auxiliary )
    2731 {
    2732 /* we have an independent subproblems since all binary variables are fixed and the integer start time
    2733 * variables belonging to the binary variables which are fixed to one are only locked by this constraint
    2734 */
    2735 SCIP_CALL( solveSubproblem(scip, cons, conflictanalysis, consdata, binvars, vars, durations, demands,
    2736 nfixedones, nfixedvars, nchgbds, ndelconss, cutoff) );
    2737 }
    2738 }
    2739 else if( !consdata->propagated && nfixedones < consdata->nvars )
    2740 {
    2741 SCIP_PROFILE* profile;
    2742 int hmin;
    2743 int est;
    2744 int lct;
    2745 int pos;
    2746
    2747 /* create empty resource profile with infinity resource capacity */
    2748 SCIP_CALL( SCIPprofileCreate(&profile, INT_MAX) );
    2749
    2750 /* create worst case resource profile */
    2751 SCIP_CALL( SCIPcreateWorstCaseProfile(scip, profile, nfixedones, vars, durations, demands) );
    2752
    2753 hmin = SCIPcomputeHmin(scip, profile, consdata->capacity);
    2754
    2755 if( hmin < INT_MAX )
    2756 {
    2757 /* check if the not selected variables can be discard from the machine */
    2758 for( v = 0; v < consdata->nvars && !(*cutoff) && !SCIPisStopped(scip) ; ++v )
    2759 {
    2760 SCIP_VAR* binvar;
    2761 SCIP_VAR* var;
    2762
    2763 binvar = consdata->binvars[v];
    2764 assert(binvar != NULL);
    2765
    2766 var = consdata->vars[v];
    2767 assert(var != NULL);
    2768
    2769 /* check if the binary choice variable is not fixed yet */
    2770 if( SCIPvarGetLbLocal(binvar) + 0.5 < SCIPvarGetUbLocal(binvar) )
    2771 {
    2772 SCIP_Real lb;
    2773 SCIP_Real ub;
    2774 SCIP_Bool infeasible;
    2775
    2776 assert(SCIPvarGetLbLocal(binvar) < 0.5);
    2777 assert(SCIPvarGetUbLocal(binvar) > 0.5);
    2778
    2780 lct = convertBoundToInt(scip, SCIPvarGetUbLocal(var)) + consdata->durations[v];
    2781
    2782 SCIP_CALL( SCIPprofileInsertCore(profile, est, lct, consdata->demands[v], &pos, &infeasible) );
    2783 assert(!infeasible);
    2784 assert(pos == -1);
    2785
    2786 hmin = SCIPcomputeHmin(scip, profile, consdata->capacity);
    2787
    2788 SCIP_CALL( SCIPprofileDeleteCore(profile, est, lct, consdata->demands[v]) );
    2789
    2790 if( hmin == INT_MAX )
    2791 continue;
    2792
    2793 /* start probing mode */
    2794 SCIPdebugMessage("start probing\n");
    2796
    2798
    2799 SCIPdebugMessage(" fix variables <%s>[%g,%g] to 1.0\n",
    2800 SCIPvarGetName(binvar), SCIPvarGetLbLocal(binvar), SCIPvarGetUbLocal(binvar));
    2801
    2802 SCIP_CALL( SCIPfixVarProbing(scip, binvar, 1.0) );
    2803
    2804 SCIPdebugMessage(" run propagation\n");
    2805 SCIP_CALL( SCIPpropagateProbing(scip, 0, &infeasible, NULL) );
    2806
    2807 lb = SCIPvarGetLbLocal(var);
    2808 ub = SCIPvarGetUbLocal(var);
    2809
    2810 /* end probing mode */
    2812 SCIPdebugMessage("end probing\n");
    2813
    2814 if( infeasible )
    2815 {
    2816 SCIP_Bool tightened;
    2817
    2818 /* propagation detected infeasibility, therefore, job cannot be processed by that machine */
    2819 SCIPdebugMessage(" probing detect infeasibility\n");
    2820 SCIPdebugMessage(" fix variable <%s> to 0.0\n", SCIPvarGetName(binvar));
    2821
    2822 /* since this bound change is dual reduction we have to avoid that this bound change is analyzed
    2823 * during the conflict analysis; otherwise all optimal solution might be removed: therefore, we
    2824 * SCIPtightenVarUb instead of SCIPinferBinvarCons()
    2825 */
    2826 SCIP_CALL( SCIPtightenVarUb(scip, binvar, 0.0, FALSE, &infeasible, &tightened) );
    2827 if( infeasible )
    2828 (*cutoff) = TRUE;
    2829 else if( tightened )
    2830 {
    2831 (*nchgbds)++;
    2832
    2833 /* fix integer start time variable if possible (before calling that method we have to leave the
    2834 * probing mode)
    2835 */
    2836 if( SCIPconsIsChecked(cons) )
    2837 {
    2838 SCIP_CALL( fixIntegerVariable(scip, var, consdata->downlocks[v], consdata->uplocks[v], nchgbds) );
    2839 }
    2840 }
    2841 }
    2842 else
    2843 {
    2844 SCIP_Bool tightened;
    2845
    2846 /* probing was feasible, therefore, we can adjust the bounds of the start time variable for that job */
    2847 SCIPdebugMessage(" probing stayed feasible\n");
    2848
    2849 assert(SCIPvarGetNLocksUp(var) >= (int)consdata->uplocks[v]);
    2850 if( SCIPvarGetNLocksUp(var) == (int)consdata->uplocks[v] )
    2851 {
    2852 SCIPdebugMessage(" variable <%s> change lower bound from <%g> to <%g>\n", SCIPvarGetName(var), SCIPvarGetLbLocal(var), lb);
    2853
    2854 /* for this bound change there is no inference information needed since no other constraint can
    2855 * use this bound change to reason something
    2856 */
    2857 SCIP_CALL( SCIPtightenVarLb(scip, var, lb, FALSE, &infeasible, &tightened) );
    2858 assert(!infeasible);
    2859
    2860 if( tightened )
    2861 (*nchgbds)++;
    2862 }
    2863
    2864 assert(SCIPvarGetNLocksDown(var) >= (int)consdata->downlocks[v]);
    2865 if( SCIPvarGetNLocksDown(var) == (int)consdata->downlocks[v] )
    2866 {
    2867 SCIPdebugMessage(" variable <%s> change upper bound from <%g> to <%g>\n", SCIPvarGetName(var), SCIPvarGetUbLocal(var), ub);
    2868
    2869 /* for this boound change there is no inference information needed since no other constraint can
    2870 * use this bound change to reason something
    2871 */
    2872 SCIP_CALL( SCIPtightenVarUb(scip, var, ub, FALSE, &infeasible, &tightened) );
    2873 assert(!infeasible);
    2874
    2875 if( tightened )
    2876 (*nchgbds)++;
    2877 }
    2878 }
    2879 }
    2880 else if( SCIPvarGetUbLocal(binvar) < 0.5 && SCIPconsIsChecked(cons) )
    2881 {
    2882 /* if the binary choice variable is fixed to zero we can try to perform a dual reductions */
    2883 SCIP_CALL( fixIntegerVariable(scip, var, consdata->downlocks[v], consdata->uplocks[v], nchgbds) );
    2884 }
    2885 }
    2886 }
    2887
    2888 /* free worst case profile */
    2889 SCIPprofileFree(&profile);
    2890 }
    2891 }
    2892
    2893 /* mark constraint to be propagated */
    2894 if( !SCIPinProbing(scip) )
    2895 consdata->propagated = TRUE;
    2896
    2897 /* free all buffers */
    2898 SCIPfreeBufferArray(scip, &durations);
    2899 SCIPfreeBufferArray(scip, &demands);
    2900 SCIPfreeBufferArray(scip, &binvars);
    2901 SCIPfreeBufferArray(scip, &vars);
    2902
    2903 return SCIP_OKAY;
    2904}
    2905
    2906
    2907/*
    2908 * Callback methods of constraint handler
    2909 */
    2910
    2911/** copy method for constraint handler plugins (called when SCIP copies plugins) */
    2912static
    2913SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOptcumulative)
    2914{ /*lint --e{715}*/
    2915 assert(scip != NULL);
    2916 assert(conshdlr != NULL);
    2917
    2919
    2920 /* call inclusion method of constraint handler */
    2922
    2923 *valid = TRUE;
    2924
    2925 return SCIP_OKAY;
    2926}
    2927
    2928/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
    2929static
    2930SCIP_DECL_CONSFREE(consFreeOptcumulative)
    2931{ /*lint --e{715}*/
    2932 SCIP_CONSHDLRDATA* conshdlrdata;
    2933
    2934 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2935 assert(conshdlrdata != NULL);
    2936
    2937 SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
    2938
    2939 SCIPconshdlrSetData(conshdlr, NULL);
    2940
    2941 return SCIP_OKAY;
    2942}
    2943
    2944
    2945/** initialization method of constraint handler (called after problem was transformed) */
    2946#define consInitOptcumulative NULL
    2947
    2948
    2949/** deinitialization method of constraint handler (called before transformed problem is freed) */
    2950#define consExitOptcumulative NULL
    2951
    2952
    2953/** presolving initialization method of constraint handler (called when presolving is about to begin) */
    2954static
    2955SCIP_DECL_CONSINITPRE(consInitpreOptcumulative)
    2956{ /*lint --e{715}*/
    2957 SCIP_CONSHDLRDATA* conshdlrdata;
    2958 int c;
    2959
    2960 assert( scip != NULL );
    2961 assert( conshdlr != NULL );
    2962
    2964
    2965 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    2966 assert(conshdlrdata != NULL);
    2967
    2968 for( c = 0; c < nconss; ++c )
    2969 {
    2970 /* remove jobs which have a duration or demand of zero (zero energy) or lay outside the effective horizon [hmin,
    2971 * hmax)
    2972 */
    2973 SCIP_CALL( removeIrrelevantJobs(scip, conss[c]) );
    2974 }
    2975
    2976 /* find trysol heuristic */
    2977 if( conshdlrdata->heurtrysol == NULL )
    2978 {
    2979 conshdlrdata->heurtrysol = SCIPfindHeur(scip, "trysol");
    2980 }
    2981
    2982 return SCIP_OKAY;
    2983}
    2984
    2985/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
    2986#define consExitpreOptcumulative NULL
    2987
    2988
    2989/** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
    2990#define consInitsolOptcumulative NULL
    2991
    2992/** constraint enforcing method of constraint handler for relaxation solutions */
    2993#define consEnforelaxOptcomulative NULL
    2994
    2995/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
    2996static
    2997SCIP_DECL_CONSEXITSOL(consExitsolOptcumulative)
    2998{ /*lint --e{715}*/
    2999 int c;
    3000
    3001 assert(scip != NULL);
    3002
    3003 /* release the rows of all constraints */
    3004 for( c = 0; c < nconss; ++c )
    3005 {
    3006 SCIP_CONSDATA* consdata;
    3007
    3008 consdata = SCIPconsGetData(conss[c]);
    3009 assert(consdata != NULL);
    3010
    3011 if( consdata->row != NULL )
    3012 {
    3013 SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
    3014 }
    3015 }
    3016
    3017 return SCIP_OKAY;
    3018}
    3019
    3020
    3021/** frees specific constraint data */
    3022static
    3023SCIP_DECL_CONSDELETE(consDeleteOptcumulative)
    3024{ /*lint --e{715}*/
    3025 SCIP_CONSHDLRDATA* conshdlrdata;
    3026
    3027 assert(conshdlr != NULL);
    3028 assert(consdata != NULL );
    3029 assert(*consdata != NULL );
    3030
    3032
    3033 /* get event handler */
    3034 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3035 assert(conshdlrdata != NULL);
    3036 assert(conshdlrdata->eventhdlrbinvars != NULL);
    3037 assert(conshdlrdata->eventhdlrintvars != NULL);
    3038
    3039 /* if constraint belongs to transformed problem space, drop bound change events on variables */
    3040 if( (*consdata)->nvars > 0 && SCIPvarIsTransformed((*consdata)->vars[0]) )
    3041 {
    3042 SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlrbinvars, conshdlrdata->eventhdlrintvars) );
    3043 }
    3044
    3045 /* free optcumulative constraint data */
    3046 SCIP_CALL( consdataFree(scip, consdata) );
    3047
    3048 return SCIP_OKAY;
    3049}
    3050
    3051/** transforms constraint data into data belonging to the transformed problem */
    3052static
    3053SCIP_DECL_CONSTRANS(consTransOptcumulative)
    3054{ /*lint --e{715}*/
    3055 SCIP_CONSHDLRDATA* conshdlrdata;
    3056 SCIP_CONSDATA* sourcedata;
    3057 SCIP_CONSDATA* targetdata;
    3058
    3059 assert(conshdlr != NULL);
    3061 assert(sourcecons != NULL);
    3062 assert(targetcons != NULL);
    3063
    3064 /* get event handler */
    3065 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3066 assert(conshdlrdata != NULL);
    3067 assert(conshdlrdata->eventhdlrbinvars != NULL);
    3068 assert(conshdlrdata->eventhdlrintvars != NULL);
    3069
    3070 sourcedata = SCIPconsGetData(sourcecons);
    3071 assert(sourcedata != NULL);
    3072 assert(sourcedata->row == NULL);
    3073
    3074 SCIPdebugMessage("transform optcumulative constraint <%s>\n", SCIPconsGetName(sourcecons));
    3075
    3076 /* create constraint data for target constraint */
    3077 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->binvars,
    3078 sourcedata->durations, sourcedata->demands, sourcedata->capacity, SCIPconsIsChecked(sourcecons)) );
    3079
    3080 /* create target constraint */
    3081 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
    3082 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
    3083 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
    3084 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
    3085 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
    3086
    3087 assert(targetdata->nglbfixedones == 0);
    3088 assert(targetdata->nglbfixedzeros == 0);
    3089 assert(targetdata->nfixedones == 0);
    3090 assert(targetdata->nfixedzeros == 0);
    3091
    3092 /* catch bound change events of variables */
    3093 SCIP_CALL( catchAllEvents(scip, *targetcons, conshdlrdata->eventhdlrbinvars, conshdlrdata->eventhdlrintvars) );
    3094
    3095 return SCIP_OKAY;
    3096}
    3097
    3098
    3099/** LP initialization method of constraint handler */
    3100static
    3101SCIP_DECL_CONSINITLP(consInitlpOptcumulative)
    3102{ /*lint --e{715}*/
    3103 SCIP_CONSHDLRDATA* conshdlrdata;
    3104 SCIP_Bool rowadded;
    3105 SCIP_Bool consadded;
    3106 SCIP_Bool cutoff;
    3107 int c;
    3108
    3109 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3110 assert(conshdlrdata != NULL);
    3111
    3112 rowadded = FALSE;
    3113 consadded = FALSE;
    3114
    3115 for( c = 0; c < nconss; ++c )
    3116 {
    3117 assert(SCIPconsIsInitial(conss[c]));
    3118 SCIP_CALL( addRelaxation(scip, conshdlr, conshdlrdata, conss[c], &rowadded, &consadded, &cutoff) );
    3119 /* ignore cutoff value */
    3120 }
    3121
    3122 return SCIP_OKAY;
    3123}
    3124
    3125
    3126/** separation method of constraint handler for LP solutions */
    3127static
    3128SCIP_DECL_CONSSEPALP(consSepalpOptcumulative)
    3129{
    3130 SCIP_CONSHDLRDATA* conshdlrdata;
    3131 SCIP_Bool rowadded;
    3132 SCIP_Bool consadded;
    3133 SCIP_Bool cutoff;
    3134 int c;
    3135
    3136 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3137 assert(conshdlrdata != NULL);
    3138
    3139 rowadded = FALSE;
    3140 consadded = FALSE;
    3141 cutoff = FALSE;
    3142
    3143 for( c = 0; c < nconss && ! cutoff; ++c )
    3144 {
    3145 SCIP_CALL( addRelaxation(scip, conshdlr, conshdlrdata, conss[c], &rowadded, &consadded, &cutoff) );
    3146 }
    3147
    3148 if ( cutoff )
    3149 *result = SCIP_CUTOFF;
    3150 else if( consadded )
    3151 *result = SCIP_CONSADDED;
    3152 else if( rowadded )
    3153 *result = SCIP_SEPARATED;
    3154 else
    3155 *result = SCIP_DIDNOTFIND;
    3156
    3157 return SCIP_OKAY;
    3158}/*lint !e715*/
    3159
    3160
    3161/** separation method of constraint handler for arbitrary primal solutions */
    3162#define consSepasolOptcumulative NULL
    3163
    3164
    3165/** constraint enforcing method of constraint handler for LP solutions */
    3166static
    3167SCIP_DECL_CONSENFOLP(consEnfolpOptcumulative)
    3168{ /*lint --e{715}*/
    3169 SCIP_CONSHDLRDATA* conshdlrdata;
    3170 SCIP_SOL* trysol;
    3171 SCIP_Bool violated;
    3172 SCIP_Bool consviolated;
    3173 SCIP_Bool consadded;
    3174 SCIP_Bool solfeasible;
    3175 int c;
    3176
    3177 SCIPdebugMessage("method: enforce LP solution (nconss %d)\n", nconss);
    3178
    3179 assert(conshdlr != NULL);
    3180 assert(nconss == 0 || conss != NULL);
    3181 assert(result != NULL);
    3182
    3184
    3185 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3186 assert(conshdlrdata != NULL);
    3187
    3188 violated = FALSE;
    3189 consviolated = FALSE;
    3190 consadded = FALSE;
    3191 solfeasible = TRUE;
    3192 trysol = NULL;
    3193
    3194 /* create pseudo solution */
    3195 if( conshdlrdata->heurtrysol != NULL )
    3196 {
    3198 }
    3199
    3200 /* check all constraints even if one is detected be violated */
    3201 for( c = 0; c < nconss && (!violated || solfeasible); ++c )
    3202 {
    3203 SCIP_CALL( enfopsCons(scip, conss[c], trysol, &consviolated, &consadded, &solfeasible) );
    3204 violated = violated || consviolated;
    3205 }
    3206
    3207 /* add a potentially feasible solution was constructed we pass it to the heuristic try sol */
    3208 if( solfeasible && violated && trysol != NULL )
    3209 {
    3210#ifdef SCIP_DEBUG
    3211 FILE* file;
    3212 file = fopen("build.sol", "w");
    3213
    3214 if( file != NULL )
    3215 {
    3216 SCIP_CALL( SCIPprintSol(scip, trysol, file, FALSE) );
    3217 fclose(file);
    3218 }
    3219#endif
    3220
    3221 SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->heurtrysol, trysol) );
    3222 }
    3223
    3224 SCIP_CALL( SCIPfreeSol(scip, &trysol) );
    3225
    3226 if( consadded )
    3227 *result = SCIP_CONSADDED;
    3228 else if( violated )
    3229 *result = SCIP_INFEASIBLE;
    3230 else
    3231 *result = SCIP_FEASIBLE;
    3232
    3233 return SCIP_OKAY;
    3234}
    3235
    3236
    3237/** constraint enforcing method of constraint handler for pseudo solutions */
    3238static
    3239SCIP_DECL_CONSENFOPS(consEnfopsOptcumulative)
    3240{ /*lint --e{715}*/
    3241 SCIP_CONSHDLRDATA* conshdlrdata;
    3242 SCIP_SOL* trysol;
    3243 SCIP_Bool violated;
    3244 SCIP_Bool consadded;
    3245 SCIP_Bool solfeasible;
    3246 int c;
    3247
    3248 SCIPdebugMessage("method: enforce pseudo solution\n");
    3249
    3250 assert(conshdlr != NULL);
    3251 assert(nconss == 0 || conss != NULL);
    3252 assert(result != NULL);
    3253
    3255
    3256 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3257 assert(conshdlrdata != NULL);
    3258
    3259 violated = FALSE;
    3260 consadded = FALSE;
    3261 solfeasible = TRUE;
    3262 trysol = NULL;
    3263
    3264 /* create pseudo solution */
    3265 if( conshdlrdata->heurtrysol != NULL )
    3266 {
    3268 }
    3269
    3270 for( c = 0; c < nconss && !violated; ++c )
    3271 {
    3272 SCIP_CALL( enfopsCons(scip, conss[c], trysol, &violated, &consadded, &solfeasible) );
    3273 }
    3274
    3275 /* add a potentially feasible solution was constructed we pass it to the heuristic try sol */
    3276 if( solfeasible && violated && trysol != NULL )
    3277 {
    3278 SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->heurtrysol, trysol) );
    3279 }
    3280
    3281 SCIP_CALL( SCIPfreeSol(scip, &trysol) );
    3282
    3283 if( consadded )
    3284 *result = SCIP_CONSADDED;
    3285 else if( violated )
    3286 *result = SCIP_INFEASIBLE;
    3287 else
    3288 *result = SCIP_FEASIBLE;
    3289
    3290 return SCIP_OKAY;
    3291}
    3292
    3293
    3294/** feasibility check method of constraint handler for integral solutions */
    3295static
    3296SCIP_DECL_CONSCHECK(consCheckOptcumulative)
    3297{ /*lint --e{715}*/
    3298 SCIP_Bool violated;
    3299 int c;
    3300
    3301 assert(conshdlr != NULL);
    3302 assert(nconss == 0 || conss != NULL);
    3303 assert(result != NULL);
    3304
    3306
    3307 violated = FALSE;
    3308
    3309 for( c = 0; c < nconss && !violated; ++c )
    3310 {
    3311 SCIP_CALL( checkCons(scip, conss[c], sol, &violated, printreason) );
    3312 }
    3313
    3314 if( violated )
    3315 *result = SCIP_INFEASIBLE;
    3316 else
    3317 *result = SCIP_FEASIBLE;
    3318
    3319 return SCIP_OKAY;
    3320}
    3321
    3322
    3323/** domain propagation method of constraint handler */
    3324static
    3325SCIP_DECL_CONSPROP(consPropOptcumulative)
    3326{ /*lint --e{715}*/
    3327 SCIP_CONSHDLRDATA* conshdlrdata;
    3328 SCIP_CONS* cons;
    3329 SCIP_Bool cutoff;
    3330 int nfixedvars;
    3331 int nupgdconss;
    3332 int ndelconss;
    3333 int nchgcoefs;
    3334 int nchgbds;
    3335 int c;
    3336
    3337 assert(scip != NULL);
    3338 assert(nconss > 0);
    3339
    3340 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3341 assert(conshdlrdata != NULL);
    3342
    3343 nfixedvars = 0;
    3344 nupgdconss = 0;
    3345 ndelconss = 0;
    3346 nchgcoefs = 0;
    3347 nchgbds = 0;
    3348 cutoff = FALSE;
    3349
    3350 SCIPdebugMessage("propagate %d optcumulative constraints (probing: %u)\n", nusefulconss, SCIPinProbing(scip));
    3351
    3352 /* first propagate only the useful constraints */
    3353 for( c = 0; c < nusefulconss && !cutoff; ++c )
    3354 {
    3355 SCIP_Bool mustpropagate;
    3356 int oldnchgcoefs;
    3357 int oldnchgbds;
    3358
    3359 cons = conss[c];
    3360 mustpropagate = TRUE;
    3361 oldnchgcoefs = nchgcoefs;
    3362 oldnchgbds = nchgbds;
    3363
    3364 /* it might be that the constraint is already deleted which can be case if SCIP is in probing mode */
    3365 if( SCIPconsIsDeleted(cons) )
    3366 {
    3367 assert(SCIPinProbing(scip));
    3368 continue;
    3369 }
    3370
    3371 /* try to upgrade optcumulative to cumulative constraint which is possible if all remaining binary variables are
    3372 * fixed to one; in case the constraint has no variable left it is removed
    3373 */
    3374 if( !SCIPinProbing(scip) )
    3375 {
    3376 SCIP_Bool redundant;
    3377
    3378 /* remove all jobs for which the binary variable is globally fixed to zero */
    3379 SCIP_CALL( applyZeroFixings(scip, cons, &nchgcoefs, &nchgbds) );
    3380
    3381 SCIP_CALL( checkRedundancy(scip, cons, &ndelconss, &redundant) );
    3382
    3383 if( redundant )
    3384 continue;
    3385
    3386 SCIP_CALL( upgradeCons(scip, cons, &ndelconss, &nupgdconss, &mustpropagate) );
    3387 }
    3388
    3389 if( mustpropagate )
    3390 {
    3391 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->conflictanalysis, &nfixedvars, &nchgbds, &ndelconss, &cutoff) );
    3392 }
    3393
    3394 /* update the age of the constraint w.r.t. success of the propagation rule */
    3395 if( oldnchgbds < nchgbds || oldnchgcoefs < nchgcoefs )
    3396 {
    3398 }
    3399 else
    3400 {
    3401 SCIP_CALL( SCIPincConsAge(scip, cons) );
    3402 }
    3403 }
    3404
    3405 if( cutoff )
    3406 {
    3407 SCIPdebugMessage("propagation detected a cutoff\n");
    3408 *result = SCIP_CUTOFF;
    3409 }
    3410 else if( nfixedvars > 0 || nchgbds > 0 || nupgdconss > 0 )
    3411 {
    3412 SCIPdebugMessage("propagation detected %d bound changes\n", nchgbds);
    3413 *result = SCIP_REDUCEDDOM;
    3414 }
    3415 else
    3416 *result = SCIP_DIDNOTFIND;
    3417
    3418 return SCIP_OKAY;
    3419}
    3420
    3421
    3422/** presolving method of constraint handler */
    3423static
    3424SCIP_DECL_CONSPRESOL(consPresolOptcumulative)
    3425{ /*lint --e{715}*/
    3426 SCIP_CONS* cons;
    3427 SCIP_Bool cutoff;
    3428 SCIP_Bool mustpropagate;
    3429 int oldnchgbds;
    3430 int oldndelconss;
    3431 int oldnupgdconss;
    3432 int oldnfixedvars;
    3433 int c;
    3434
    3435 assert(scip != NULL);
    3436 assert(nconss > 0);
    3437 assert(!SCIPinProbing(scip));
    3438
    3439 oldnchgbds = *nchgbds;
    3440 oldndelconss = *ndelconss;
    3441 oldnupgdconss = *nupgdconss;
    3442 oldnfixedvars = *nfixedvars;
    3443 cutoff = FALSE;
    3444
    3445 SCIPdebugMessage("presolve %d optcumulative constraints\n", nconss);
    3446
    3447 for( c = 0; c < nconss && !cutoff; ++c )
    3448 {
    3449 SCIP_CONSDATA* consdata;
    3450
    3451 cons = conss[c];
    3452 mustpropagate = TRUE;
    3453
    3454 /* remove all jobs for which the binary variable is globally fixed to zero */
    3455 SCIP_CALL( applyZeroFixings(scip, cons, nchgcoefs, nchgbds) );
    3456
    3457 /* try to upgrade optcumulative to cumulative constraint which is possible if all remaining binary variables are
    3458 * fixed to one; in case the constraint has no or one variable left it is removed
    3459 */
    3460 SCIP_CALL( upgradeCons(scip, cons, ndelconss, nupgdconss, &mustpropagate) );
    3461
    3462 if( mustpropagate )
    3463 {
    3464 int nvars;
    3465 int hmin;
    3466 int hmax;
    3467 int split;
    3468
    3469 consdata = SCIPconsGetData(cons);
    3470 assert(consdata != NULL);
    3471
    3472 nvars = consdata->nvars;
    3473 assert(nvars > 1);
    3474
    3475 if( !consdata->normalized )
    3476 {
    3477 /* divide demands and capacity by their greatest common divisor */
    3478 SCIP_CALL( SCIPnormalizeCumulativeCondition(scip, nvars, consdata->vars, consdata->durations,
    3479 consdata->demands, &consdata->capacity, nchgcoefs, nchgsides) );
    3480 consdata->normalized = TRUE;
    3481 }
    3482
    3483 /* propagate the constaint */
    3484 SCIP_CALL( propagateCons(scip, cons, FALSE, nfixedvars, nchgbds, ndelconss, &cutoff) );
    3485
    3486 /* if a cutoff was detected we are done */
    3487 if( cutoff )
    3488 break;
    3489
    3490 /* check if the optimal cumulative constraint can be decomposed */
    3491 SCIP_CALL( SCIPsplitCumulativeCondition(scip, nvars, consdata->vars, consdata->durations,
    3492 consdata->demands, consdata->capacity, &hmin, &hmax, &split) );
    3493
    3494 /* check if this time point improves the effective horizon */
    3495 if( consdata->hmin < hmin )
    3496 {
    3497 SCIPdebugMessage("cumulative constraint <%s> adjust hmin <%d> -> <%d>\n", SCIPconsGetName(cons), consdata->hmin, hmin);
    3498
    3499 consdata->hmin = hmin;
    3500 (*nchgsides)++;
    3501 }
    3502
    3503 /* check if this time point improves the effective horizon */
    3504 if( consdata->hmax > hmax )
    3505 {
    3506 SCIPdebugMessage("cumulative constraint <%s> adjust hmax <%d> -> <%d>\n", SCIPconsGetName(cons), consdata->hmax, hmax);
    3507 consdata->hmax = hmax;
    3508 (*nchgsides)++;
    3509 }
    3510
    3511 /* check if the constraint is redundant */
    3512 if( consdata->hmax <= consdata->hmin )
    3513 {
    3514 SCIPdebugMessage("constraint <%s> is redundant since hmax(%d) <= hmin(%d)\n",
    3515 SCIPconsGetName(cons), consdata->hmax, consdata->hmin);
    3516
    3517 SCIP_CALL( SCIPdelCons(scip, cons) );
    3518 (*ndelconss)++;
    3519
    3520 continue;
    3521 }
    3522
    3523 /* check if the cumulative constraint can be decomposed */
    3524 if( consdata->hmin < split && split < consdata->hmax )
    3525 {
    3526 SCIP_CONS* splitcons;
    3527 SCIP_CONSDATA* splitconsdata;
    3528 char name[SCIP_MAXSTRLEN];
    3529
    3530 (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "(%s)'", SCIPconsGetName(cons));
    3531
    3532 SCIPdebugMessage("split optcumulative constraint <%s>[%d,%d) with %d jobs at time point %d\n",
    3533 SCIPconsGetName(cons), consdata->hmin, consdata->hmax, nvars, split);
    3534
    3535 SCIP_CALL( SCIPcreateConsOptcumulative(scip, &splitcons, name, nvars, consdata->vars, consdata->binvars,
    3536 consdata->durations, consdata->demands, consdata->capacity,
    3539
    3540 splitconsdata = SCIPconsGetData(splitcons);
    3541 assert(splitconsdata != NULL);
    3542
    3543 /* adjust the effective time horizon of the new constraint */
    3544 splitconsdata->hmin = split;
    3545 splitconsdata->hmax = consdata->hmax;
    3546
    3547 assert(split < consdata->hmax);
    3548
    3549 /* add and release new cumulative constraint */
    3550 SCIP_CALL( SCIPaddCons(scip, splitcons) );
    3551 SCIP_CALL( SCIPreleaseCons(scip, &splitcons) );
    3552
    3553 /* adjust the effective time horizon of the constraint */
    3554 consdata->hmax = split;
    3555
    3556 assert(consdata->hmin < consdata->hmax);
    3557
    3558 (*naddconss)++;
    3559 }
    3560
    3561 /* presolve cumulative condition w.r.t. effective horizon by detecting irrelevant variables */
    3562 SCIP_CALL( presolveCumulativeCondition(scip, cons, nfixedvars, nchgcoefs, nchgsides, &cutoff) );
    3563
    3564 /* detect implications */
    3565 SCIP_CALL( detectImplications(scip, cons, nchgcoefs, naddconss) );
    3566
    3567 /* try to upgrade optcumulative to cumulative constraint which is possible if all remaining binary variables
    3568 * are fixed to one; in case the constraint has no variable left it is removed
    3569 */
    3570 assert(!SCIPinProbing(scip));
    3571 SCIP_CALL( upgradeCons(scip, cons, ndelconss, nupgdconss, &mustpropagate) );
    3572 }
    3573 }
    3574
    3575 if( cutoff )
    3576 {
    3577 SCIPdebugMessage("presolving detected a cutoff\n");
    3578 *result = SCIP_CUTOFF;
    3579 }
    3580 else if( oldnfixedvars < *nfixedvars || oldnchgbds < *nchgbds || oldnupgdconss < *nupgdconss || oldndelconss < *ndelconss )
    3581 {
    3582 SCIPdebugMessage("presolving detected %d bound changes\n", *nchgbds - oldnchgbds);
    3583 *result = SCIP_SUCCESS;
    3584 }
    3585 else
    3586 *result = SCIP_DIDNOTFIND;
    3587
    3588 return SCIP_OKAY;
    3589}
    3590
    3591
    3592/** propagation conflict resolving method of constraint handler */
    3593static
    3594SCIP_DECL_CONSRESPROP(consRespropOptcumulative)
    3595{ /*lint --e{715}*/
    3596 SCIP_CONSHDLRDATA* conshdlrdata;
    3597 SCIP_CONSDATA* consdata;
    3598 SCIP_VAR** vars;
    3599 SCIP_VAR** binvars;
    3600 int* durations;
    3601 int* demands;
    3602 SCIP_Bool choicevar;
    3603 int nvars;
    3604 int v;
    3605
    3606 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    3607 assert(conshdlrdata != NULL);
    3608
    3609 /* check if the constraint handler wants to participate in the conflict analysis */
    3610 if( !conshdlrdata->conflictanalysis )
    3611 {
    3612 *result = SCIP_DIDNOTFIND;
    3613 return SCIP_OKAY;
    3614 }
    3615
    3616 SCIPdebugMessage("resolve propagate of optcumulative constraints <%s>\n", SCIPconsGetName(cons));
    3617
    3618 consdata = SCIPconsGetData(cons);
    3619 assert(consdata != NULL);
    3620
    3621 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, consdata->nvars) );
    3622 SCIP_CALL( SCIPallocBufferArray(scip, &vars, consdata->nvars) );
    3623 SCIP_CALL( SCIPallocBufferArray(scip, &durations, consdata->nvars) );
    3624 SCIP_CALL( SCIPallocBufferArray(scip, &demands, consdata->nvars) );
    3625
    3626 nvars = 0;
    3627 choicevar = FALSE;
    3628
    3629 /* collect all activities which are were locally assigned to that machine before the bound change was made */
    3630 for( v = 0; v < consdata->nvars; ++v )
    3631 {
    3632 if( SCIPgetVarLbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) > 0.5 )
    3633 {
    3634 vars[nvars] = consdata->vars[v];
    3635 binvars[nvars] = consdata->binvars[v];
    3636 durations[nvars] = consdata->durations[v];
    3637 demands[nvars] = consdata->demands[v];
    3638 nvars++;
    3639 }
    3640 else if( consdata->binvars[v] == infervar )
    3641 choicevar = TRUE;
    3642 }
    3643
    3644 assert(nvars > 0);
    3645
    3646 if( choicevar )
    3647 {
    3648 for( v = 0; v < consdata->nvars; ++v )
    3649 {
    3650 if( SCIPgetVarLbAtIndex(scip, consdata->binvars[v], bdchgidx, FALSE) > 0.5 )
    3651 {
    3652 SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvars[v]) );
    3653
    3654 SCIP_CALL( SCIPaddConflictLb(scip, consdata->vars[v], bdchgidx) );
    3655 SCIP_CALL( SCIPaddConflictUb(scip, consdata->vars[v], bdchgidx) );
    3656 }
    3657 else if( consdata->binvars[v] == infervar )
    3658 {
    3659 SCIP_CALL( SCIPaddConflictLb(scip, consdata->vars[v], bdchgidx) );
    3660 SCIP_CALL( SCIPaddConflictUb(scip, consdata->vars[v], bdchgidx) );
    3661 }
    3662 }
    3663
    3664 *result = SCIP_SUCCESS;
    3665 }
    3666 else
    3667 {
    3668 SCIP_Bool* explanation;
    3669
    3670 SCIP_CALL( SCIPallocBufferArray(scip, &explanation, nvars) );
    3671 BMSclearMemoryArray(explanation, nvars);
    3672
    3673 /* resolve propagate of cumulative condition */
    3674 SCIP_CALL( SCIPrespropCumulativeCondition(scip, nvars, vars, durations, demands, consdata->capacity, consdata->hmin, consdata->hmax,
    3675 infervar, inferinfo, boundtype, bdchgidx, relaxedbd, explanation, result) );
    3676
    3677 /* if the cumulative constraint handler successfully create an explanation for the propagate we extend this
    3678 * explanation with the required choice variables
    3679 */
    3680 if( *result == SCIP_SUCCESS )
    3681 {
    3682 for( v = 0; v < nvars; ++v )
    3683 {
    3684 if( explanation[v] )
    3685 {
    3686 /* add the lower bounds of the choice variables as part of the initial reason */
    3687 SCIP_CALL( SCIPaddConflictBinvar(scip, binvars[v]) );
    3688 }
    3689 }
    3690 }
    3691
    3692 SCIPfreeBufferArray(scip, &explanation);
    3693 }
    3694
    3695 /* free all buffers */
    3696 SCIPfreeBufferArray(scip, &demands);
    3697 SCIPfreeBufferArray(scip, &durations);
    3698 SCIPfreeBufferArray(scip, &vars);
    3699 SCIPfreeBufferArray(scip, &binvars);
    3700
    3701 return SCIP_OKAY;
    3702}
    3703
    3704/** variable rounding lock method of constraint handler */
    3705static
    3706SCIP_DECL_CONSLOCK(consLockOptcumulative)
    3707{ /*lint --e{715}*/
    3708 SCIP_CONSDATA* consdata;
    3709 SCIP_VAR** vars;
    3710 int v;
    3711
    3712 assert(scip != NULL);
    3713 assert(cons != NULL);
    3714
    3715 consdata = SCIPconsGetData(cons);
    3716 assert(consdata != NULL);
    3717
    3718 vars = consdata->vars;
    3719 assert(vars != NULL);
    3720
    3721 for( v = 0; v < consdata->nvars; ++v )
    3722 {
    3723 assert(consdata->vars[v] != NULL);
    3724 if( consdata->downlocks[v] && consdata->uplocks[v] )
    3725 {
    3726 /* the integer start variable should not get rounded in both direction */
    3727 SCIP_CALL( SCIPaddVarLocksType(scip, vars[v], SCIP_LOCKTYPE_MODEL, nlockspos + nlocksneg, nlockspos + nlocksneg) );
    3728 }
    3729 else if( consdata->downlocks[v] )
    3730 {
    3731 SCIP_CALL( SCIPaddVarLocksType(scip, vars[v], SCIP_LOCKTYPE_MODEL, nlockspos, nlocksneg) );
    3732 }
    3733 else if( consdata->uplocks[v] )
    3734 {
    3735 SCIP_CALL( SCIPaddVarLocksType(scip, vars[v], SCIP_LOCKTYPE_MODEL, nlocksneg, nlockspos) );
    3736 }
    3737
    3738 /* the binary decision variable should not get rounded up; rounding down does not influence the feasibility */
    3739 assert(consdata->binvars[v] != NULL);
    3740 SCIP_CALL( SCIPaddVarLocksType(scip, consdata->binvars[v], SCIP_LOCKTYPE_MODEL, nlocksneg, nlockspos) );
    3741 }
    3742
    3743 return SCIP_OKAY;
    3744}
    3745
    3746
    3747/** constraint activation notification method of constraint handler */
    3748#define consActiveOptcumulative NULL
    3749
    3750
    3751/** constraint deactivation notification method of constraint handler */
    3752#define consDeactiveOptcumulative NULL
    3753
    3754
    3755/** constraint enabling notification method of constraint handler */
    3756#define consEnableOptcumulative NULL
    3757
    3758
    3759/** constraint disabling notification method of constraint handler */
    3760#define consDisableOptcumulative NULL
    3761
    3762/** variable deletion method of constraint handler */
    3763#define consDelvarsOptcumulative NULL
    3764
    3765/** constraint display method of constraint handler */
    3766static
    3767SCIP_DECL_CONSPRINT(consPrintOptcumulative)
    3768{ /*lint --e{715}*/
    3769 assert(scip != NULL);
    3770 assert(conshdlr != NULL);
    3771 assert(cons != NULL);
    3772
    3774
    3775 return SCIP_OKAY;
    3776}
    3777
    3778/** constraint copying method of constraint handler */
    3779static
    3780SCIP_DECL_CONSCOPY(consCopyOptcumulative)
    3781{ /*lint --e{715}*/
    3782 SCIP_CONSDATA* sourceconsdata;
    3783 SCIP_VAR** sourcebinvars;
    3784 SCIP_VAR** sourcevars;
    3785 SCIP_VAR** binvars;
    3786 SCIP_VAR** vars;
    3787 SCIP_Bool success;
    3788 const char* consname;
    3789
    3790 int nvars;
    3791 int v;
    3792
    3793 sourceconsdata = SCIPconsGetData(sourcecons);
    3794 assert(sourceconsdata != NULL);
    3795
    3796 /* get variables of the source constraint */
    3797 sourcebinvars = sourceconsdata->binvars;
    3798 sourcevars = sourceconsdata->vars;
    3799 nvars = sourceconsdata->nvars;
    3800
    3801 (*valid) = TRUE;
    3802
    3803 if( nvars == 0 )
    3804 return SCIP_OKAY;
    3805
    3806 /* allocate buffer array */
    3807 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
    3808 SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
    3809
    3810 success = TRUE;
    3811
    3812 for( v = 0; v < nvars && success; ++v )
    3813 {
    3814 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcebinvars[v], &binvars[v], varmap, consmap, global, &success) );
    3815 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, &success) );
    3816 }
    3817
    3818 if( success )
    3819 {
    3820 if( name != NULL )
    3821 consname = name;
    3822 else
    3823 consname = SCIPconsGetName(sourcecons);
    3824
    3825 /* copy the logic using the linear constraint copy method */
    3826 SCIP_CALL( SCIPcreateConsOptcumulative(scip, cons, consname, nvars, vars, binvars,
    3827 sourceconsdata->durations, sourceconsdata->demands, sourceconsdata->capacity,
    3828 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3829
    3830 }
    3831 else
    3832 (*valid) = FALSE;
    3833
    3834 /* free buffer array */
    3835 SCIPfreeBufferArray(scip, &vars);
    3836 SCIPfreeBufferArray(scip, &binvars);
    3837
    3838 return SCIP_OKAY;
    3839}
    3840
    3841/** constraint parsing method of constraint handler */
    3842static
    3843SCIP_DECL_CONSPARSE(consParseOptcumulative)
    3844{ /*lint --e{715}*/
    3845 SCIP_VAR** vars;
    3846 SCIP_VAR** binvars;
    3847 SCIP_VAR* var;
    3848 SCIP_VAR* binvar;
    3849 SCIP_Real value;
    3850 char strvalue[SCIP_MAXSTRLEN];
    3851 char* endptr;
    3852 int* demands;
    3853 int* durations;
    3854 int capacity;
    3855 int duration;
    3856 int demand;
    3857 int hmin;
    3858 int hmax;
    3859 int varssize;
    3860 int nvars;
    3861
    3862 SCIPdebugMsg(scip, "parse <%s> as optcumulative constraint\n", str);
    3863
    3864 /* cutoff "cumulative" form the constraint string */
    3865 SCIPstrCopySection(str, 'o', '(', strvalue, SCIP_MAXSTRLEN, &endptr);
    3866 str = endptr;
    3867
    3868 varssize = 100;
    3869 nvars = 0;
    3870
    3871 /* allocate buffer array for variables */
    3872 SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
    3873 SCIP_CALL( SCIPallocBufferArray(scip, &binvars, varssize) );
    3874 SCIP_CALL( SCIPallocBufferArray(scip, &demands, varssize) );
    3875 SCIP_CALL( SCIPallocBufferArray(scip, &durations, varssize) );
    3876
    3877 do
    3878 {
    3879 SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
    3880
    3881 if( var != NULL )
    3882 {
    3883 str = endptr;
    3884
    3885 SCIPstrCopySection(str, '(', ')', strvalue, SCIP_MAXSTRLEN, &endptr);
    3886 duration = atoi(strvalue);
    3887 str = endptr;
    3888
    3889 SCIPstrCopySection(str, '[', ']', strvalue, SCIP_MAXSTRLEN, &endptr);
    3890 demand = atoi(strvalue);
    3891 str = endptr;
    3892
    3893 SCIP_CALL( SCIPparseVarName(scip, str, &binvar, &endptr) );
    3894 str = endptr;
    3895
    3896 SCIPdebugMsg(scip, "parse job <%s><%s>, duration %d, demand %d\n", SCIPvarGetName(var), SCIPvarGetName(binvar), duration, demand);
    3897
    3898 assert(nvars < varssize);
    3899 vars[nvars] = var;
    3900 binvars[nvars] = binvar;
    3901 demands[nvars] = demand;
    3902 durations[nvars] = duration;
    3903 nvars++;
    3904 }
    3905 }
    3906 while( var != NULL );
    3907
    3908 /* parse effective time window */
    3909 SCIPstrCopySection(str, '[', ',', strvalue, SCIP_MAXSTRLEN, &endptr);
    3910 hmin = atoi(strvalue);
    3911 str = endptr;
    3912
    3913 if( SCIPstrToRealValue(str, &value, &endptr) )
    3914 {
    3915 hmax = (int)(value);
    3916 str = endptr;
    3917
    3918 /* parse capacity */
    3919 SCIPstrCopySection(str, ')', '=', strvalue, SCIP_MAXSTRLEN, &endptr);
    3920 str = endptr;
    3921 if( SCIPstrToRealValue(str, &value, &endptr) )
    3922 {
    3923 capacity = (int)value;
    3924
    3925 /* create cumulative constraint */
    3926 SCIP_CALL( SCIPcreateConsOptcumulative(scip, cons, name, nvars, vars, binvars, durations, demands, capacity,
    3927 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
    3928
    3929 (*success) = TRUE;
    3930
    3931 SCIP_CALL( SCIPsetHminOptcumulative(scip, *cons, hmin) );
    3932 SCIP_CALL( SCIPsetHmaxOptcumulative(scip, *cons, hmax) );
    3933 }
    3934 }
    3935
    3936 /* free buffer arrays */
    3937 SCIPfreeBufferArray(scip, &durations);
    3938 SCIPfreeBufferArray(scip, &demands);
    3939 SCIPfreeBufferArray(scip, &binvars);
    3940 SCIPfreeBufferArray(scip, &vars);
    3941
    3942 return SCIP_OKAY;
    3943}
    3944
    3945
    3946
    3947/*
    3948 * Callback methods of event handler
    3949 */
    3950
    3951static
    3952SCIP_DECL_EVENTEXEC(eventExecOptcumulativeBinvars)
    3953{ /*lint --e{715}*/
    3954 SCIP_CONSDATA* consdata;
    3955 SCIP_EVENTTYPE eventtype;
    3956
    3957 assert(eventhdlr != NULL);
    3958 assert(eventdata != NULL);
    3959 assert(event != NULL);
    3960
    3962
    3963 /* collect event information */
    3964 consdata = (SCIP_CONSDATA*)eventdata;
    3965 eventtype = SCIPeventGetType(event);
    3966
    3967 switch( eventtype )
    3968 {
    3970 consdata->nglbfixedones++;
    3971 break;
    3973 consdata->nglbfixedzeros++;
    3974 break;
    3976 consdata->nfixedones++;
    3977 consdata->propagated = FALSE;
    3978 break;
    3980 consdata->nfixedzeros++;
    3981 break;
    3983 consdata->nfixedones--;
    3984 consdata->triedsolving = FALSE;
    3985 break;
    3987 consdata->nfixedzeros--;
    3988 consdata->triedsolving = FALSE;
    3989
    3990 if( !SCIPinProbing(scip) )
    3991 consdata->propagated = FALSE;
    3992 break;
    3993 default:
    3994 SCIPerrorMessage("invalid event type %llx\n", (unsigned long long)eventtype);
    3995 return SCIP_INVALIDDATA;
    3996 }
    3997
    3998 return SCIP_OKAY;
    3999}
    4000
    4001static
    4002SCIP_DECL_EVENTEXEC(eventExecOptcumulativeIntvars)
    4003{ /*lint --e{715}*/
    4004 SCIP_CONSDATA* consdata;
    4005
    4006 assert(eventhdlr != NULL);
    4007 assert(eventdata != NULL);
    4008 assert(event != NULL);
    4009
    4011
    4012 /* collect event information */
    4013 consdata = (SCIP_CONSDATA*)eventdata;
    4014 assert(consdata != NULL);
    4015
    4016 /* a bound of a start time variable was tightened; therefore we mark to constraint to create a new local linear
    4017 * relaxation
    4018 */
    4019 if( consdata->nfixedzeros + consdata->nfixedones < consdata->nvars )
    4020 consdata->relaxadded = FALSE;
    4021
    4022 if( !SCIPinProbing(scip) )
    4023 consdata->propagated = FALSE;
    4024
    4025 return SCIP_OKAY;
    4026}
    4027
    4028/*
    4029 * constraint specific interface methods
    4030 */
    4031
    4032/** creates the handler for optcumulative constraints and includes it in SCIP */
    4034 SCIP* scip /**< SCIP data structure */
    4035 )
    4036{
    4037 SCIP_CONSHDLRDATA* conshdlrdata;
    4038 SCIP_EVENTHDLR* eventhdlrbinvars;
    4039 SCIP_EVENTHDLR* eventhdlrintvars;
    4040 SCIP_CONSHDLR* conshdlr;
    4041
    4042 /* create event handler for bound change events */
    4044 eventExecOptcumulativeBinvars, NULL) );
    4045
    4046 /* create event handler for bound change events */
    4048 eventExecOptcumulativeIntvars, NULL) );
    4049
    4050 /* create constraint handler data */
    4051 SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlrbinvars, eventhdlrintvars) );
    4052
    4053 /* include constraint handler */
    4056 consEnfolpOptcumulative, consEnfopsOptcumulative, consCheckOptcumulative,
    4057 consLockOptcumulative, conshdlrdata) );
    4058
    4059 /* set non-fundamental callbacks via specific setter functions */
    4060 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOptcumulative, consCopyOptcumulative) );
    4063 SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreOptcumulative) );
    4065 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOptcumulative) );
    4067 SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolOptcumulative) );
    4073 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOptcumulative) );
    4074 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOptcumulative) );
    4075 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOptcumulative) );
    4076 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOptcumulative,
    4078 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOptcumulative) );
    4079 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOptcumulative, CONSHDLR_PROPFREQ,
    4081 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOptcumulative) );
    4082 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOptcumulative, consSepasolOptcumulative,
    4084 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOptcumulative) );
    4086
    4087 /* add optcumulative constraint handler parameters */
    4089 "constraints/"CONSHDLR_NAME"/rowrelax",
    4090 "add linear relaxation as LP row (otherwise a knapsack constraint is created)?",
    4091 &conshdlrdata->rowrelax, FALSE, DEFAULT_ROWRELAX, NULL, NULL) );
    4092
    4094 "constraints/"CONSHDLR_NAME"/conflictanalysis",
    4095 "participate in conflict analysis?",
    4096 &conshdlrdata->conflictanalysis, FALSE, DEFAULT_CONFLICTANALYSIS, NULL, NULL) );
    4097
    4099 "constraints/"CONSHDLR_NAME"/intervalrelax",
    4100 "create a relaxation for each start and end time point interval",
    4101 &conshdlrdata->intervalrelax, FALSE, DEFAULT_INTERVALRELAX, NULL, NULL) );
    4102
    4103 return SCIP_OKAY;
    4104}
    4105
    4106/** creates and captures a optcumulative constraint */
    4108 SCIP* scip, /**< SCIP data structure */
    4109 SCIP_CONS** cons, /**< pointer to hold the created constraint */
    4110 const char* name, /**< name of constraint */
    4111 int nvars, /**< number of variables (jobs) */
    4112 SCIP_VAR** vars, /**< array of integer variable which corresponds to starting times for a job */
    4113 SCIP_VAR** binvars, /**< array of variable representing if the job has to be processed on this machine */
    4114 int* durations, /**< array containing corresponding durations */
    4115 int* demands, /**< array containing corresponding demands */
    4116 int capacity, /**< available cumulative capacity */
    4117 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
    4118 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
    4119 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
    4120 * Usually set to TRUE. */
    4121 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
    4122 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    4123 SCIP_Bool check, /**< should the constraint be checked for feasibility?
    4124 * TRUE for model constraints, FALSE for additional, redundant constraints. */
    4125 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
    4126 * Usually set to TRUE. */
    4127 SCIP_Bool local, /**< is constraint only valid locally?
    4128 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
    4129 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
    4130 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
    4131 * adds coefficients to this constraint. */
    4132 SCIP_Bool dynamic, /**< is constraint subject to aging?
    4133 * Usually set to FALSE. Set to TRUE for own cuts which
    4134 * are seperated as constraints. */
    4135 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
    4136 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
    4137 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
    4138 * if it may be moved to a more global node?
    4139 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
    4140 )
    4141{
    4142 /* TODO: (optional) modify the definition of the SCIPcreateConsOptcumulative() call, if you don't need all the information */
    4143
    4144 SCIP_CONSHDLR* conshdlr;
    4145 SCIP_CONSDATA* consdata;
    4146
    4147 /* find the optcumulative constraint handler */
    4148 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
    4149 if( conshdlr == NULL )
    4150 {
    4151 SCIPerrorMessage("optcumulative constraint handler not found\n");
    4152 return SCIP_PLUGINNOTFOUND;
    4153 }
    4154
    4155 /* the optcumulative constraint handler currently does not support modifiable constraints */
    4156 assert(modifiable == FALSE);
    4157
    4158 /* create constraint data */
    4159 SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, binvars, durations, demands, capacity, check) );
    4160
    4161 /* create constraint */
    4162 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
    4163 local, modifiable, dynamic, removable, stickingatnode) );
    4164
    4166 {
    4167 SCIP_CONSHDLRDATA* conshdlrdata;
    4168
    4169 /* get event handler */
    4170 conshdlrdata = SCIPconshdlrGetData(conshdlr);
    4171 assert(conshdlrdata != NULL);
    4172 assert(conshdlrdata->eventhdlrbinvars != NULL);
    4173 assert(conshdlrdata->eventhdlrintvars != NULL);
    4174 assert(consdata->nglbfixedzeros == 0);
    4175 assert(consdata->nglbfixedones == 0);
    4176 assert(consdata->nfixedzeros == 0);
    4177 assert(consdata->nfixedones == 0);
    4178
    4179 /* catch bound change events of variables */
    4180 SCIP_CALL( catchAllEvents(scip, *cons, conshdlrdata->eventhdlrbinvars, conshdlrdata->eventhdlrintvars) );
    4181 }
    4182
    4183 return SCIP_OKAY;
    4184}
    4185
    4186/** set the left bound of the time axis to be considered (including hmin) */
    4188 SCIP* scip, /**< SCIP data structure */
    4189 SCIP_CONS* cons, /**< constraint data */
    4190 int hmin /**< left bound of time axis to be considered */
    4191 )
    4192{
    4193 SCIP_CONSDATA* consdata;
    4194
    4196
    4197 consdata = SCIPconsGetData(cons);
    4198 assert(consdata != NULL);
    4199 assert(hmin >= 0);
    4200 assert(hmin <= consdata->hmax);
    4201
    4202 consdata->hmin = hmin;
    4203
    4204 return SCIP_OKAY;
    4205}
    4206
    4207/** returns the left bound of the time axis to be considered */
    4209 SCIP* scip, /**< SCIP data structure */
    4210 SCIP_CONS* cons /**< constraint */
    4211 )
    4212{
    4213 SCIP_CONSDATA* consdata;
    4214
    4216
    4217 consdata = SCIPconsGetData(cons);
    4218 assert(consdata != NULL);
    4219
    4220 return consdata->hmin;
    4221}
    4222
    4223/** set the right bound of the time axis to be considered (not including hmax) */
    4225 SCIP* scip, /**< SCIP data structure */
    4226 SCIP_CONS* cons, /**< constraint data */
    4227 int hmax /**< right bound of time axis to be considered */
    4228 )
    4229{
    4230 SCIP_CONSDATA* consdata;
    4231
    4233
    4234 consdata = SCIPconsGetData(cons);
    4235 assert(consdata != NULL);
    4236 assert(hmax >= consdata->hmin);
    4237
    4238 consdata->hmax = hmax;
    4239
    4240 return SCIP_OKAY;
    4241}
    4242
    4243/** returns the right bound of the time axis to be considered */
    4245 SCIP* scip, /**< SCIP data structure */
    4246 SCIP_CONS* cons /**< constraint */
    4247 )
    4248{
    4249 SCIP_CONSDATA* consdata;
    4250
    4252
    4253 consdata = SCIPconsGetData(cons);
    4254 assert(consdata != NULL);
    4255
    4256 return consdata->hmax;
    4257}
    static long bound
    constraint handler for cumulative constraints
    Constraint handler for knapsack constraints of the form , x binary and .
    #define consInitsolOptcumulative
    static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
    static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
    #define consExitpreOptcumulative
    static SCIP_DECL_CONSCOPY(consCopyOptcumulative)
    static SCIP_RETCODE createVarboundCons(SCIP *scip, SCIP_VAR *binvar, SCIP_VAR *intvar, int bound, SCIP_Bool lower)
    #define CONSHDLR_NEEDSCONS
    #define CONSHDLR_SEPAFREQ
    static SCIP_RETCODE detectImplications(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *naddconss)
    #define consActiveOptcumulative
    static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *rowadded, SCIP_Bool *consadded, SCIP_Bool *cutoff)
    #define EVENTHDLR_BINVARS_NAME
    static int removeRedundantRows(SCIP_Longint *rowtightness, int *startidxs, int nrows, SCIP_Longint tightness)
    #define CONSHDLR_CHECKPRIORITY
    #define CONSHDLR_DESC
    static SCIP_RETCODE checkRedundancy(SCIP *scip, SCIP_CONS *cons, int *ndelconss, SCIP_Bool *redundant)
    #define EVENTHDLR_INTVARS_DESC
    static void collectActivities(SCIP_CONSDATA *consdata, SCIP_VAR **binvars, SCIP_VAR **vars, int *durations, int *demands, int *nfixedones, int *nfixedzeros, SCIP_Bool *auxiliary)
    int SCIPgetHmaxOptcumulative(SCIP *scip, SCIP_CONS *cons)
    static void createSortedEventpoints(SCIP *scip, SCIP_CONSDATA *consdata, int *starttimes, int *endtimes, int *startindices, int *endindices, SCIP_Bool local)
    static SCIP_DECL_CONSENFOPS(consEnfopsOptcumulative)
    static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_VAR **binvars, int *durations, int *demands, int capacity, SCIP_Bool check)
    static SCIP_RETCODE dropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlrbinvars, SCIP_EVENTHDLR *eventhdlrintvars)
    #define CONSHDLR_PROP_TIMING
    static SCIP_DECL_CONSINITLP(consInitlpOptcumulative)
    #define EVENTHDLR_INTVARS_NAME
    static SCIP_RETCODE applyZeroFixings(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgbds)
    static SCIP_RETCODE solveSubproblem(SCIP *scip, SCIP_CONS *cons, SCIP_Bool conflictanalysis, SCIP_CONSDATA *consdata, SCIP_VAR **binvars, SCIP_VAR **vars, int *durations, int *demands, int nvars, int *nfixedvars, int *nchgbds, int *ndelconss, SCIP_Bool *cutoff)
    static SCIP_RETCODE catchEventIntvar(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    SCIP_RETCODE SCIPincludeConshdlrOptcumulative(SCIP *scip)
    static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool conflictanalysis, int *nfixedvars, int *nchgbds, int *ndelconss, SCIP_Bool *cutoff)
    #define CONSHDLR_MAXPREROUNDS
    static SCIP_RETCODE createSetPackingCons(SCIP *scip, SCIP_VAR *var1, SCIP_VAR *var2)
    #define CONSHDLR_SEPAPRIORITY
    #define consDeactiveOptcumulative
    static SCIP_RETCODE createBounddisjunctionCons(SCIP *scip, SCIP_VAR *binvar, SCIP_VAR *intvar, int lb, int ub)
    static SCIP_RETCODE dropEventIntvar(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    static SCIP_RETCODE dropEventBinvar(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    static SCIP_RETCODE enfopsCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *trysol, SCIP_Bool *violated, SCIP_Bool *consadded, SCIP_Bool *solfeasible)
    static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_VAR **vars, SCIP_Longint *weights, int nvars, SCIP_Longint capacity, SCIP_Bool local, SCIP_Bool *rowadded, SCIP_Bool *consadded, SCIP_Bool *cutoff)
    static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOptcumulative)
    #define consEnforelaxOptcomulative
    #define consExitOptcumulative
    static SCIP_RETCODE catchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlrbinvars, SCIP_EVENTHDLR *eventhdlrintvars)
    #define DEFAULT_CONFLICTANALYSIS
    static SCIP_DECL_CONSENFOLP(consEnfolpOptcumulative)
    static SCIP_RETCODE removeIrrelevantJobs(SCIP *scip, SCIP_CONS *cons)
    static SCIP_RETCODE createConflictCons(SCIP *scip, const char *name, SCIP_VAR **binvars, int nvars)
    static SCIP_RETCODE solveCumulative(SCIP *scip, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, int hmin, int hmax, SCIP_Bool local, SCIP_Real *ests, SCIP_Real *lsts, SCIP_Longint maxnodes, SCIP_Bool *solved, SCIP_Bool *infeasible, SCIP_Bool *unbounded, SCIP_Bool *error)
    #define DEFAULT_INTERVALRELAX
    static SCIP_Longint computeMaxEnergy(SCIP *scip, SCIP_CONSDATA *consdata, int starttime, int endtime)
    static void collectSolActivities(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol, SCIP_VAR **binvars, SCIP_VAR **vars, int *durations, int *demands, int *nvars, int *nfixedones, int *nfixedzeros, SCIP_Bool *auxiliary)
    static SCIP_DECL_CONSPRINT(consPrintOptcumulative)
    static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlrbinvars, SCIP_EVENTHDLR *eventhdlrintvars)
    static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *ndelconss, int *nupgdconss, SCIP_Bool *mustpropagate)
    static SCIP_DECL_CONSRESPROP(consRespropOptcumulative)
    static SCIP_DECL_CONSPARSE(consParseOptcumulative)
    static SCIP_RETCODE consdataDeletePos(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_CONS *cons, int pos)
    static SCIP_DECL_CONSPRESOL(consPresolOptcumulative)
    static SCIP_DECL_CONSSEPALP(consSepalpOptcumulative)
    static SCIP_DECL_CONSEXITSOL(consExitsolOptcumulative)
    static SCIP_DECL_CONSPROP(consPropOptcumulative)
    static SCIP_RETCODE fixIntegerVariable(SCIP *scip, SCIP_VAR *var, SCIP_Bool downlock, SCIP_Bool uplock, int *nchgbds)
    static SCIP_DECL_CONSLOCK(consLockOptcumulative)
    #define CONSHDLR_PROPFREQ
    static SCIP_DECL_CONSINITPRE(consInitpreOptcumulative)
    #define consInitOptcumulative
    #define consSepasolOptcumulative
    static SCIP_RETCODE collectVars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR **vars, SCIP_Longint *weights, int *nvars, int starttime, int endtime)
    static SCIP_DECL_CONSFREE(consFreeOptcumulative)
    int SCIPgetHminOptcumulative(SCIP *scip, SCIP_CONS *cons)
    static int convertBoundToInt(SCIP *scip, SCIP_Real bound)
    #define CONSHDLR_PRESOLTIMING
    static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
    static SCIP_DECL_CONSDELETE(consDeleteOptcumulative)
    SCIP_RETCODE SCIPsetHminOptcumulative(SCIP *scip, SCIP_CONS *cons, int hmin)
    SCIP_RETCODE SCIPsetHmaxOptcumulative(SCIP *scip, SCIP_CONS *cons, int hmax)
    #define CONSHDLR_EAGERFREQ
    static SCIP_RETCODE presolveCumulativeCondition(SCIP *scip, SCIP_CONS *cons, int *nfixedvars, int *nchgcoefs, int *nchgsides, SCIP_Bool *cutoff)
    static SCIP_DECL_CONSTRANS(consTransOptcumulative)
    #define consDisableOptcumulative
    static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *violated, SCIP_Bool printreason)
    static SCIP_RETCODE catchEventBinvar(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
    #define CONSHDLR_ENFOPRIORITY
    #define consEnableOptcumulative
    static SCIP_DECL_CONSCHECK(consCheckOptcumulative)
    #define CONSHDLR_DELAYSEPA
    #define EVENTHDLR_BINVARS_DESC
    #define CONSHDLR_NAME
    #define consDelvarsOptcumulative
    static void checkCounters(SCIP_CONSDATA *consdata)
    static SCIP_DECL_EVENTEXEC(eventExecOptcumulativeBinvars)
    static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *binvar, SCIP_VAR *var, SCIP_Bool downlock, SCIP_Bool uplock)
    #define CONSHDLR_DELAYPROP
    #define DEFAULT_ROWRELAX
    SCIP_RETCODE SCIPcreateConsOptcumulative(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_VAR **binvars, int *durations, int *demands, int capacity, 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)
    constraint handler for cumulative constraints with optional activities
    #define NULL
    Definition: def.h:257
    #define SCIP_MAXSTRLEN
    Definition: def.h:278
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPpropCumulativeCondition(SCIP *scip, SCIP_PRESOLTIMING presoltiming, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, int hmin, int hmax, SCIP_CONS *cons, int *nchgbds, SCIP_Bool *initialized, SCIP_Bool *explanation, SCIP_Bool *cutoff)
    SCIP_RETCODE SCIPsplitCumulativeCondition(SCIP *scip, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, int *hmin, int *hmax, int *split)
    SCIP_RETCODE SCIPcreateConsBasicVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_RETCODE SCIPcreateConsBasicBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
    SCIP_RETCODE SCIPcheckCumulativeCondition(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, int hmin, int hmax, SCIP_Bool *violated, SCIP_CONS *cons, SCIP_Bool printreason)
    SCIP_RETCODE SCIPsolveCumulative(SCIP *scip, int njobs, SCIP_Real *ests, SCIP_Real *lsts, SCIP_Real *objvals, int *durations, int *demands, int capacity, int hmin, int hmax, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Longint maxnodes, SCIP_Bool *solved, SCIP_Bool *infeasible, SCIP_Bool *unbounded, SCIP_Bool *error)
    SCIP_RETCODE SCIPaddCoefSetppc(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    Definition: cons_setppc.c:9664
    SCIP_RETCODE SCIPcreateConsKnapsack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Longint *weights, SCIP_Longint capacity, 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 SCIPrespropCumulativeCondition(SCIP *scip, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, int hmin, int hmax, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedbd, SCIP_Bool *explanation, SCIP_RESULT *result)
    SCIP_RETCODE SCIPnormalizeCumulativeCondition(SCIP *scip, int nvars, SCIP_VAR **vars, int *durations, int *demands, int *capacity, int *nchgcoefs, int *nchgsides)
    SCIP_RETCODE SCIPcreateWorstCaseProfile(SCIP *scip, SCIP_PROFILE *profile, int nvars, SCIP_VAR **vars, int *durations, int *demands)
    SCIP_RETCODE SCIPpresolveCumulativeCondition(SCIP *scip, int nvars, SCIP_VAR **vars, int *durations, int hmin, int hmax, SCIP_Bool *downlocks, SCIP_Bool *uplocks, SCIP_CONS *cons, SCIP_Bool *irrelevants, int *nfixedvars, int *nchgsides, SCIP_Bool *cutoff)
    SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPsetHminCumulative(SCIP *scip, SCIP_CONS *cons, int hmin)
    SCIP_RETCODE SCIPcreateConsBasicSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars)
    Definition: cons_setppc.c:9591
    SCIP_RETCODE SCIPsetHmaxCumulative(SCIP *scip, SCIP_CONS *cons, int hmax)
    SCIP_RETCODE SCIPaddCoefLogicor(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
    SCIP_RETCODE SCIPcreateConsCumulative(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, int *durations, int *demands, int capacity, 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)
    int SCIPcomputeHmin(SCIP *scip, SCIP_PROFILE *profile, int capacity)
    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:655
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:767
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3420
    SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:4067
    SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
    Definition: scip_prob.c:3986
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPheurPassSolTrySol(SCIP *scip, SCIP_HEUR *heur, SCIP_SOL *sol)
    Definition: heur_trysol.c:259
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    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
    SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
    SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
    SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
    SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
    SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
    Definition: scip_cons.c:808
    void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
    Definition: cons.c:4350
    SCIP_RETCODE SCIPsetConshdlrEnable(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENABLE((*consenable)))
    Definition: scip_cons.c:716
    SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
    Definition: scip_cons.c:540
    SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
    Definition: scip_cons.c:396
    SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
    Definition: scip_cons.c:492
    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 SCIPsetConshdlrDisable(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDISABLE((*consdisable)))
    Definition: scip_cons.c:739
    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:4320
    SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
    Definition: scip_cons.c:420
    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_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
    Definition: scip_cons.c:468
    SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
    Definition: scip_cons.c:762
    SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
    Definition: scip_cons.c:624
    SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
    Definition: scip_cons.c:444
    SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
    Definition: cons.c:4340
    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 SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
    Definition: scip_cons.c:670
    SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
    Definition: scip_cons.c:785
    SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
    Definition: cons.c:8423
    SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
    Definition: cons.c:8652
    SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
    Definition: cons.c:8413
    SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
    Definition: cons.c:8562
    SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
    Definition: scip_cons.c:2536
    SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
    Definition: cons.c:8592
    SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
    Definition: cons.c:8522
    SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
    Definition: cons.c:8702
    SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
    Definition: cons.c:8582
    SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    Definition: scip_cons.c:997
    SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
    Definition: cons.c:8612
    SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
    Definition: cons.c:8632
    const char * SCIPconsGetName(SCIP_CONS *cons)
    Definition: cons.c:8393
    SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1812
    SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
    Definition: cons.c:8642
    SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
    Definition: cons.c:8672
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
    Definition: cons.c:8572
    SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_cons.c:1784
    SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
    Definition: cons.c:8662
    SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
    Definition: scip_cut.c:117
    SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
    Definition: scip_cut.c:225
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:396
    SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
    Definition: event.c:1194
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
    Definition: scip_mem.c:126
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    SCIP_Longint SCIPgetMemUsed(SCIP *scip)
    Definition: scip_mem.c:100
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_RETCODE SCIPstartProbing(SCIP *scip)
    Definition: scip_probing.c:120
    SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
    Definition: scip_probing.c:166
    SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
    Definition: scip_probing.c:419
    SCIP_RETCODE SCIPendProbing(SCIP *scip)
    Definition: scip_probing.c:261
    SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1581
    SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1604
    SCIP_RETCODE SCIPcreateEmptyRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
    Definition: scip_lp.c:1367
    SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_lp.c:1646
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
    Definition: scip_lp.c:1508
    SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
    Definition: lp.c:17917
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    SCIP_RETCODE SCIPprintSol(SCIP *scip, SCIP_SOL *sol, FILE *file, SCIP_Bool printzeros)
    Definition: scip_sol.c:2351
    SCIP_RETCODE SCIPcreateCurrentSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:747
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1569
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPinRepropagation(SCIP *scip)
    Definition: scip_tree.c:146
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6401
    SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
    Definition: scip_var.c:2119
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    int SCIPvarGetNLocksDown(SCIP_VAR *var)
    Definition: var.c:4443
    SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
    Definition: var.c:23462
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23932
    SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
    Definition: scip_var.c:6651
    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:24174
    SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
    Definition: scip_var.c:5118
    SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
    Definition: scip_var.c:5296
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6141
    SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
    Definition: scip_var.c:2166
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6230
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    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
    int SCIPvarGetNLocksUp(SCIP_VAR *var)
    Definition: var.c:4456
    SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
    Definition: scip_var.c:361
    SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
    Definition: misc.c:7097
    void SCIPprofileFree(SCIP_PROFILE **profile)
    Definition: misc.c:6846
    SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
    Definition: misc.c:6832
    SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
    Definition: misc.c:7127
    void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
    void SCIPsortRealPtrPtrIntInt(SCIP_Real *realarray, void **ptrarray1, void **ptrarray2, int *intarray1, int *intarray2, int len)
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
    Definition: misc.c:10955
    void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
    Definition: misc.c:10985
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    #define SCIPdebugPrintCons(x, y, z)
    Definition: pub_message.h:102
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    default SCIP plugins
    static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
    Main separation function.
    Definition: sepa_flower.c:1219
    @ SCIP_CONFTYPE_PROPAGATION
    Definition: type_conflict.h:62
    struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
    Definition: type_cons.h:64
    struct SCIP_ConsData SCIP_CONSDATA
    Definition: type_cons.h:65
    #define SCIP_EVENTTYPE_GUBCHANGED
    Definition: type_event.h:76
    #define SCIP_EVENTTYPE_GBDCHANGED
    Definition: type_event.h:122
    struct SCIP_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #define SCIP_EVENTTYPE_UBTIGHTENED
    Definition: type_event.h:79
    #define SCIP_EVENTTYPE_LBRELAXED
    Definition: type_event.h:78
    #define SCIP_EVENTTYPE_GLBCHANGED
    Definition: type_event.h:75
    #define SCIP_EVENTTYPE_BOUNDRELAXED
    Definition: type_event.h:126
    uint64_t SCIP_EVENTTYPE
    Definition: type_event.h:156
    #define SCIP_EVENTTYPE_BOUNDTIGHTENED
    Definition: type_event.h:125
    #define SCIP_EVENTTYPE_LBTIGHTENED
    Definition: type_event.h:77
    #define SCIP_EVENTTYPE_UBRELAXED
    Definition: type_event.h:80
    @ SCIP_BOUNDTYPE_UPPER
    Definition: type_lp.h:58
    @ SCIP_BOUNDTYPE_LOWER
    Definition: type_lp.h:57
    enum SCIP_BoundType SCIP_BOUNDTYPE
    Definition: type_lp.h:60
    @ 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_CONSADDED
    Definition: type_result.h:52
    @ SCIP_SEPARATED
    Definition: type_result.h:49
    @ SCIP_SUCCESS
    Definition: type_result.h:58
    @ SCIP_INFEASIBLE
    Definition: type_result.h:46
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_STAGE_PROBLEM
    Definition: type_set.h:45
    @ SCIP_STAGE_TRANSFORMING
    Definition: type_set.h:46
    #define SCIP_PRESOLTIMING_ALWAYS
    Definition: type_timing.h:58
    @ SCIP_LOCKTYPE_MODEL
    Definition: type_var.h:141