Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_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-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_optcumulative.c
    26 * @ingroup PRIMALHEURISTICS
    27 * @brief heuristic for cumulative scheduling with optional activities
    28 * @author Stefan Heinz
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include <assert.h>
    34#include <string.h>
    35
    37#include "heur_optcumulative.h"
    38
    39
    40#define HEUR_NAME "optcumulative"
    41#define HEUR_DESC "problem specific heuristic of cumulative scheduling problems with optional jobs"
    42#define HEUR_DISPCHAR 'q'
    43#define HEUR_PRIORITY -1106000
    44#define HEUR_FREQ -1
    45#define HEUR_FREQOFS 0
    46#define HEUR_MAXDEPTH -1
    47#define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
    48#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    49
    50#define DEFAULT_MAXNODES 1000LL /**< maximum number of nodes to regard in the subproblem */
    51#define DEFAULT_MAXPROPROUNDS -1 /**< maximum number of propagation rounds during probing */
    52
    53/*
    54 * Data structures
    55 */
    56
    58{
    62 unsigned int* keys;
    63 int* nones;
    66};
    68
    69
    70/** primal heuristic data */
    71struct SCIP_HeurData
    72{
    73 SCIP_VAR*** binvars; /**< machnine job matrix (choice variables) */
    74 SCIP_VAR*** vars; /**< machnine job matrix (start time variables) */
    75 int** durations; /**< machnine job duration matrix */
    76 int** demands; /**< machnine job demands matrix */
    77 int* machines; /**< number of jobs for each machines */
    78 int* capacities; /**< machine capacities */
    79 int nmachines; /**< number of machines */
    80 int njobs; /**< number of njobs */
    81
    82 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
    83 int maxproprounds; /**< maximum number of propagation rounds during probing */
    84 SCIP_Bool initialized; /**< are the candidate list initialized? */
    85
    86 SCIP_ASSIGNMENT** machineassignments;
    87};
    88
    89/*
    90 * Local methods
    91 */
    92
    93/** reset heuristic data structure */
    94static
    96 SCIP* scip, /**< original SCIP data structure */
    97 SCIP_HEURDATA* heurdata /**< structure containing heurdata */
    98 )
    99{
    100 heurdata->vars = NULL;
    101 heurdata->binvars = NULL;
    102 heurdata->durations = NULL;
    103 heurdata->demands = NULL;
    104 heurdata->machines = NULL;
    105 heurdata->capacities = NULL;
    106 heurdata->machineassignments = NULL;
    107 heurdata->nmachines = 0;
    108 heurdata->njobs = 0;
    109
    110 heurdata->initialized = FALSE;
    111}
    112
    113/** apply variable bound fixing during probing */
    114static
    116 SCIP* scip, /**< original SCIP data structure */
    117 SCIP_HEURDATA* heurdata, /**< structure containing heurdata */
    118 SCIP_Bool* infeasible /**< pointer to store whether problem is infeasible */
    119 )
    120{
    121 SCIP_VAR*** binvars;
    122 int* machines;
    123 int* possitions;
    124 int nmachines;
    125 int j;
    126 int m;
    127
    128 binvars = heurdata->binvars;
    129 nmachines = heurdata->nmachines;
    130 machines = heurdata->machines;
    131
    132 SCIP_CALL( SCIPallocBufferArray(scip, &possitions, nmachines) );
    133 BMSclearMemoryArray(possitions, nmachines);
    134
    135 while( !(*infeasible) )
    136 {
    137 SCIP_VAR* var;
    138 SCIP_Real objval;
    139 int bestmachine;
    140
    141 bestmachine = -1;
    142 objval = SCIPinfinity(scip);
    143
    144 /* search over all machines and find the next cheapest job to assign */
    145 for( m = 0; m < nmachines; ++m )
    146 {
    147 int currentpos;
    148
    149 currentpos = possitions[m];
    150
    151 /* find next unfixed variable for the current machine */
    152 for( j = currentpos; j < machines[m]; ++j )
    153 {
    154 if( SCIPvarGetLbLocal(binvars[m][j]) + 0.5 < SCIPvarGetUbLocal(binvars[m][j]) )
    155 break;
    156
    157 possitions[m]++;
    158 }
    159
    160 currentpos = possitions[m];
    161
    162 /* check if we have a variable left on that machine */
    163 if( currentpos < machines[m] )
    164 {
    165 assert(binvars[m][currentpos] != NULL);
    166
    167 /* check if the objective coefficient is better than the best known one */
    168 if( SCIPvarGetObj(binvars[m][currentpos]) < objval )
    169 {
    170 objval = SCIPvarGetObj(binvars[m][currentpos]);
    171 bestmachine = m;
    172 }
    173 }
    174 }
    175
    176 /* check if unsigned variable was left */
    177 if( bestmachine == -1 )
    178 break;
    179
    180 assert(bestmachine < nmachines);
    181 assert(possitions[bestmachine] < machines[bestmachine]);
    182
    183 var = binvars[bestmachine][possitions[bestmachine]];
    184 assert(var != NULL);
    185 assert(SCIPvarGetLbLocal(var) + 0.5 < SCIPvarGetUbLocal(var));
    186
    187 possitions[bestmachine]++;
    188
    190
    191 SCIP_CALL( SCIPfixVarProbing(scip, var, 1.0) );
    192
    193 SCIPdebugMessage("variable <%s> objective coefficient <%g> fixed to 1.0 (%d pseudo cands)\n",
    195
    196 /* check if problem is already infeasible */
    197 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, infeasible, NULL) );
    198
    199 if( *infeasible )
    200 {
    201 /* backtrack */
    203
    204 /* after backtracking the variable might be already fixed to zero */
    205 if( SCIPvarGetUbLocal(var) > 0.5 )
    206 {
    207 SCIP_CALL( SCIPfixVarProbing(scip, var, 0.0) );
    208 }
    209
    210 SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, infeasible, NULL) );
    211 }
    212 }
    213
    214 SCIPfreeBufferArray(scip, &possitions);
    215
    216 SCIPdebugMessage("probing ended with %sfeasible problem\n", (*infeasible) ? "in" : "");
    217
    218 return SCIP_OKAY;
    219}
    220
    221/** initialize the solution by assign the lower bound of the variable as solution value */
    222static
    224 SCIP* scip, /**< SCIP data structure */
    225 SCIP_SOL* sol /**< solution to be initialize */
    226 )
    227{
    228 SCIP_VAR** vars;
    229 int nvars;
    230 int v;
    231
    232 nvars = SCIPgetNOrigVars(scip);
    233 vars = SCIPgetOrigVars(scip);
    234
    235 for( v = 0; v < nvars; ++v )
    236 {
    237 SCIP_CALL( SCIPsetSolVal(scip, sol, vars[v], SCIPvarGetLbLocal(vars[v])) );
    238 }
    239
    240 return SCIP_OKAY;
    241}
    242
    243/** main procedure of the optcumulative heuristic */
    244static
    246 SCIP* scip, /**< SCIP data structure */
    247 SCIP_HEUR* heur, /**< heuristic */
    248 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
    249 SCIP_RESULT* result /**< pointer to store the result */
    250 )
    251{
    252 SCIP_Real lowerbound;
    253 SCIP_Real upperbound;
    254 SCIP_Real pseudoobj;
    255 SCIP_Bool infeasible;
    256
    257 assert(heur != NULL);
    258 assert(heurdata != NULL);
    259
    260 /* initialize default values */
    261 infeasible = FALSE;
    262
    263 *result = SCIP_DIDNOTFIND;
    264
    265 /* start probing */
    267
    268 /* apply the variable fixings */
    269 SCIP_CALL( applyOptcumulativeFixings(scip, heurdata, &infeasible) );
    270
    271 lowerbound = SCIPgetLowerbound(scip);
    272 upperbound = SCIPgetUpperbound(scip);
    273 pseudoobj = SCIPgetPseudoObjval(scip);
    274
    275 /* if a solution has been found --> fix all other variables by subscip if necessary */
    276 if( !infeasible && pseudoobj >= lowerbound && pseudoobj < upperbound )
    277 {
    278 SCIP_ASSIGNMENT* machineassignment;
    279 int pos;
    280
    281 SCIP_SOL* sol;
    282 SCIP_VAR** vars;
    283 SCIP_Real* lbs;
    284 SCIP_Real* ubs;
    285 int* durations;
    286 int* demands;
    287 SCIP_Bool unbounded;
    288 int njobs;
    289 int nvars;
    290 int j;
    291 int m;
    292
    293 /* create temporary solution */
    294 SCIP_CALL( SCIPcreateOrigSol(scip, &sol, heur) );
    295
    296 /* initialize the solution with the lower bound of all variables */
    298
    299 njobs = heurdata->njobs;
    300
    301 /* allocate memory for collecting the information for the single machines */
    302 SCIP_CALL( SCIPallocBufferArray(scip, &vars, njobs) );
    303 SCIP_CALL( SCIPallocBufferArray(scip, &durations, njobs) );
    304 SCIP_CALL( SCIPallocBufferArray(scip, &demands, njobs) );
    305 SCIP_CALL( SCIPallocBufferArray(scip, &lbs, njobs) );
    306 SCIP_CALL( SCIPallocBufferArray(scip, &ubs, njobs) );
    307
    308 nvars = -1;
    309
    310 for( m = 0; m < heurdata->nmachines && !infeasible; ++m )
    311 {
    312 unsigned int key;
    313 int a;
    314
    315 machineassignment = heurdata->machineassignments[m];
    316
    317 pos = machineassignment->nassignments;
    318
    319 /* realloc memory if not enough space left */
    320 if( machineassignment->nassignments == machineassignment->sassignments)
    321 {
    322 int oldsize;
    323 int newsize;
    324
    325 oldsize = machineassignment->sassignments;
    326 newsize = SCIPcalcMemGrowSize(scip, pos + 1);
    327
    328 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(machineassignment->vars), oldsize, newsize) );
    329 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(machineassignment->solvals), oldsize, newsize) );
    330 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(machineassignment->feasibles), oldsize, newsize) );
    331 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(machineassignment->keys), oldsize, newsize) );
    332 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(machineassignment->nones), oldsize, newsize) );
    333
    334 machineassignment->sassignments = newsize;
    335 }
    336 assert(machineassignment->sassignments > pos);
    337
    338 assert(njobs >= heurdata->machines[m]);
    339 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &machineassignment->vars[pos], heurdata->machines[m]) ); /*lint !e866*/
    340 BMSclearMemoryArray(machineassignment->vars[pos], heurdata->machines[m]); /*lint !e866*/
    341 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &machineassignment->solvals[pos], heurdata->machines[m]) ); /*lint !e866*/
    342 machineassignment->nassignments++;
    343 nvars = 0;
    344 key = 0;
    345
    346 /* collect the jobs which are assign to that machine */
    347 for( j = 0; j < heurdata->machines[m]; ++j )
    348 {
    349 SCIP_VAR* binvar;
    350
    351 binvar = heurdata->binvars[m][j];
    352 assert(binvar != NULL);
    353
    354 /* check if job is assign to that machine */
    355 if( SCIPvarGetLbLocal(binvar) > 0.5 )
    356 {
    357 vars[nvars] = heurdata->vars[m][j];
    358 durations[nvars] = heurdata->durations[m][j];
    359 demands[nvars] = heurdata->demands[m][j];
    360 nvars++;
    361
    362 machineassignment->vars[pos][j] = TRUE;
    363 key |= (1 << (j % 32)); /*lint !e701*/
    364
    365 SCIP_CALL( SCIPsetSolVal(scip, sol, binvar, 1.0) );
    366 }
    367 }
    368 machineassignment->nones[pos] = nvars;
    369 machineassignment->keys[pos] = key;
    370
    371 /* if none of the variables is assigned to that machine we skip it */
    372 if( nvars == 0 )
    373 {
    374 SCIPfreeBlockMemoryArray(scip, &machineassignment->vars[pos], heurdata->machines[m]); /*lint !e866*/
    375 SCIPfreeBlockMemoryArray(scip, &machineassignment->solvals[pos], heurdata->machines[m]); /*lint !e866*/
    376 machineassignment->nassignments--;
    377 continue;
    378 }
    379
    380 /* check whether we already have try a subset of this variable combination */
    381 for( a = pos - 1; a >= 0; --a )
    382 {
    383 /* infeasible check */
    384 if( !machineassignment->feasibles[a]
    385 && nvars > machineassignment->nones[a] && ((~key & machineassignment->keys[a]) == 0) )
    386 {
    387 /* if we compare to an infeasible assignment, that assignment can be smaller or equal since a smaller
    388 * infeasible assignment induces a infeasibility for all assignments which include that assignment
    389 */
    390
    391 /* do the expensive pairwise comparison */
    392 for( j = heurdata->machines[m] - 1; j >= 0; --j )
    393 {
    394 /* at least the same variables in the old combination have to be assigned to 1 */
    395 if( machineassignment->vars[pos][j] < machineassignment->vars[a][j] )
    396 break;
    397 }
    398 /* we already tried this combination */
    399 if( j == -1 )
    400 break;
    401 }
    402 /* feasible check */
    403 else if( machineassignment->feasibles[a] &&
    404 nvars < machineassignment->nones[a] && ((key & ~(machineassignment->keys[a])) == 0) )
    405 {
    406 /* if we compare to a feasible assignment, that assignment can be larger or equal since a larger feasible
    407 * assignment induces a feasibility for all assignments which is subset of that assignment
    408 */
    409
    410 /* do the expensive pairwise comparison */
    411 for( j = heurdata->machines[m] - 1; j >= 0; --j )
    412 {
    413 if( machineassignment->vars[pos][j] > machineassignment->vars[a][j] )
    414 break;
    415 }
    416 /* we already tried this combination */
    417 if( j == -1 )
    418 break;
    419 }
    420 else if( nvars == machineassignment->nones[a] && ((~key & machineassignment->keys[a]) == 0) )
    421 {
    422 /* do the expensive pairwise comparison */
    423 for( j = heurdata->machines[m] - 1; j >= 0; --j )
    424 {
    425 if( machineassignment->vars[pos][j] != machineassignment->vars[a][j] )
    426 break;
    427 }
    428 /* we already tried this combination */
    429 if( j == -1 )
    430 break;
    431 }
    432 }
    433
    434 if( a >= 0 )
    435 {
    436 SCIPdebugMessage("We already tried %s this combination, it was %s\n",
    437 machineassignment->nones[pos] > machineassignment->nones[a] ? "a subset of" : (machineassignment->nones[pos] > machineassignment->nones[a] ? "a superset of" : ""),
    438 machineassignment->feasibles[a] ? "feasible" : "infeasible");
    439
    440 /* delete unnecessary data */
    441 SCIPfreeBlockMemoryArray(scip, &machineassignment->vars[pos], heurdata->machines[m]); /*lint !e866*/
    442 SCIPfreeBlockMemoryArray(scip, &machineassignment->solvals[pos], heurdata->machines[m]); /*lint !e866*/
    443 machineassignment->nassignments--;
    444
    445 infeasible = !machineassignment->feasibles[a];
    446
    447 if( infeasible )
    448 break;
    449
    450 for( j = 0; j < heurdata->machines[m]; ++j )
    451 {
    452 if( machineassignment->vars[a][j] && SCIPvarGetLbLocal(heurdata->binvars[m][j]) > 0.5 )
    453 {
    454 SCIP_CALL( SCIPsetSolVal(scip, sol, heurdata->vars[m][j], machineassignment->solvals[a][j]) );
    455 }
    456 }
    457 }
    458 else
    459 {
    460 SCIP_Real* objvals;
    461 SCIP_Real timelimit;
    462 SCIP_Real memorylimit;
    463 SCIP_Bool solved;
    464 SCIP_Bool error;
    465 int v;
    466
    467 SCIPdebugMessage("check machine %d (variables %d)\n", m, nvars);
    468
    469 SCIP_CALL( SCIPallocBufferArray(scip, &objvals, nvars) );
    470
    471 for( v = 0; v < nvars; ++v )
    472 {
    473 SCIP_VAR* var;
    474
    475 var = vars[v];
    476 assert(var != NULL);
    477
    478 lbs[v] = SCIPvarGetLbLocal(var);
    479 ubs[v] = SCIPvarGetUbLocal(var);
    480 objvals[v] = SCIPvarGetObj(var);
    481 }
    482
    483 /* check whether there is enough time and memory left */
    484 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
    485 if( !SCIPisInfinity(scip, timelimit) )
    486 timelimit -= SCIPgetSolvingTime(scip);
    487 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
    488
    489 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    490 if( !SCIPisInfinity(scip, memorylimit) )
    491 {
    492 memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    493 memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    494 }
    495
    496 /* solve the cumulative condition separately */
    497 SCIP_CALL( SCIPsolveCumulative(scip, nvars, lbs, ubs, objvals, durations, demands, heurdata->capacities[m], 0, INT_MAX,
    498 timelimit, memorylimit, heurdata->maxnodes, &solved, &infeasible, &unbounded, &error) );
    499 assert(!unbounded);
    500 assert(!error);
    501
    502 SCIPfreeBufferArray(scip, &objvals);
    503
    504 machineassignment->feasibles[pos] = !infeasible;
    505
    506 if( infeasible )
    507 {
    508 SCIPdebugMessage("infeasible :-(\n");
    509 break;
    510 }
    511
    512 for( j = 0, v = 0; j < heurdata->machines[m]; ++j )
    513 {
    514 if( machineassignment->vars[pos][j] && SCIPvarGetLbLocal(heurdata->binvars[m][j]) > 0.5 )
    515 {
    516 SCIP_CALL( SCIPsetSolVal(scip, sol, heurdata->vars[m][j], lbs[v]) );
    517 machineassignment->solvals[pos][j] = lbs[v];
    518 v++;
    519 }
    520 }
    521 }
    522 }
    523
    526 SCIPfreeBufferArray(scip, &demands);
    527 SCIPfreeBufferArray(scip, &durations);
    529
    530 /* try and free solution */
    531 if( !infeasible )
    532 {
    533 SCIP_Bool stored;
    534
    535 SCIPdebugMessage("************ try solution <%g>\n", SCIPgetSolOrigObj(scip, sol));
    536
    537 SCIP_CALL( SCIPtrySolFree(scip, &sol, FALSE, FALSE, FALSE, FALSE, TRUE, &stored) );
    538
    539 if( stored )
    540 *result = SCIP_FOUNDSOL;
    541 }
    542 }
    543
    544 /* exit probing mode */
    546
    547 return SCIP_OKAY;
    548}
    549
    550/*
    551 * Callback methods of primal heuristic
    552 */
    553
    554/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    555static
    556SCIP_DECL_HEURCOPY(heurCopyOptcumulative)
    557{ /*lint --e{715}*/
    558 assert(scip != NULL);
    559 assert(heur != NULL);
    560 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    561
    562 /* call inclusion method of heuristic */
    564
    565 return SCIP_OKAY;
    566}
    567
    568/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    569static
    570SCIP_DECL_HEURFREE(heurFreeOptcumulative)
    571{ /*lint --e{715}*/
    572 SCIP_HEURDATA* heurdata;
    573 int m;
    574
    575 /* free heuristic data */
    576 heurdata = SCIPheurGetData(heur);
    577 assert(heurdata != NULL);
    578
    579 /* release all variables */
    580 for( m = heurdata->nmachines - 1; m >= 0; --m )
    581 {
    582 int a;
    583
    584 for( a = 0; a < heurdata->machineassignments[m]->nassignments; ++a )
    585 {
    586 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->vars[a]), heurdata->machines[m]); /*lint !e866*/
    587 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->solvals[a]), heurdata->machines[m]); /*lint !e866*/
    588 }
    589
    590 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->nones), heurdata->machineassignments[m]->sassignments);
    591 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->keys), heurdata->machineassignments[m]->sassignments);
    592 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->feasibles), heurdata->machineassignments[m]->sassignments);
    593 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->solvals), heurdata->machineassignments[m]->sassignments);
    594 SCIPfreeBlockMemoryArray(scip, &(heurdata->machineassignments[m]->vars), heurdata->machineassignments[m]->sassignments);
    595 SCIPfreeBlockMemory(scip, &heurdata->machineassignments[m]); /*lint !e866*/
    596
    597 SCIPfreeBlockMemoryArray(scip, &heurdata->vars[m], heurdata->machines[m]);
    598 SCIPfreeBlockMemoryArray(scip, &heurdata->binvars[m], heurdata->machines[m]);
    599 SCIPfreeBlockMemoryArray(scip, &heurdata->durations[m], heurdata->machines[m]);
    600 SCIPfreeBlockMemoryArray(scip, &heurdata->demands[m], heurdata->machines[m]);
    601 }
    602
    603 /* free arrays */
    604 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->machineassignments, heurdata->nmachines);
    605 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->demands, heurdata->nmachines);
    606 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->durations, heurdata->nmachines);
    607 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->binvars, heurdata->nmachines);
    608 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->vars, heurdata->nmachines);
    609
    610 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->capacities, heurdata->nmachines);
    611 SCIPfreeBlockMemoryArrayNull(scip, &heurdata->machines, heurdata->nmachines);
    612
    613 SCIPfreeBlockMemory(scip, &heurdata);
    614 SCIPheurSetData(heur, NULL);
    615
    616 return SCIP_OKAY;
    617}
    618
    619/** initialization method of primal heuristic (called after problem was transformed) */
    620#define heurInitOptcumulative NULL
    621
    622/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    623#define heurExitOptcumulative NULL
    624
    625/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    626#define heurInitsolOptcumulative NULL
    627
    628/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
    629#define heurExitsolOptcumulative NULL
    630
    631/** execution method of primal heuristic */
    632static
    633SCIP_DECL_HEUREXEC(heurExecOptcumulative)
    634{ /*lint --e{715}*/
    635 SCIP_HEURDATA* heurdata;
    636
    637 assert( heur != NULL );
    638 assert( scip != NULL );
    639 assert( result != NULL );
    640
    641 *result = SCIP_DIDNOTRUN;
    642
    644 return SCIP_OKAY;
    645
    646 heurdata = SCIPheurGetData(heur);
    647 assert(heurdata != NULL);
    648
    649 if( !heurdata->initialized )
    650 return SCIP_OKAY;
    651
    652 if( SCIPisStopped(scip) )
    653 return SCIP_OKAY;
    654
    655 SCIPdebugMessage("apply optcumulative heuristic at node %"SCIP_LONGINT_FORMAT"\n",
    657
    658 *result = SCIP_DIDNOTFIND;
    659
    660 /* try variable lower and upper bounds which respect to objective coefficients */
    661 SCIP_CALL( applyOptcumulative(scip, heur, heurdata, result) );
    662
    663 return SCIP_OKAY;
    664}
    665
    666/*
    667 * primal heuristic specific interface methods
    668 */
    669
    670/** creates the optcumulative primal heuristic and includes it in SCIP */
    672 SCIP* scip /**< SCIP data structure */
    673 )
    674{
    675 SCIP_HEURDATA* heurdata;
    676
    677 /* create optcumulative primal heuristic data */
    678 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    679 heurdataReset(scip, heurdata);
    680
    681 /* include primal heuristic */
    684 heurCopyOptcumulative,
    685 heurFreeOptcumulative, heurInitOptcumulative, heurExitOptcumulative,
    687 heurdata) );
    688
    689 /* add variable bounds primal heuristic parameters */
    690 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/"HEUR_NAME"/maxnodes",
    691 "maximum number of nodes to regard in the subproblem",
    692 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    693 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/"HEUR_NAME"/maxproprounds",
    694 "maximum number of propagation rounds during probing (-1 infinity)",
    695 &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
    696
    697 return SCIP_OKAY;
    698}
    699
    700/** initialize the heuristics data structure */
    702 SCIP* scip, /**< original SCIP data structure */
    703 int nmachines, /**< number of machines */
    704 int njobs, /**< number of njobs */
    705 int* machines, /**< number of jobs for each machines */
    706 SCIP_VAR*** binvars, /**< machnine job matrix (choice variables) */
    707 SCIP_VAR*** vars, /**< machnine job matrix (start time variables) */
    708 int** durations, /**< machnine job duration matrix */
    709 int** demands, /**< machnine job demands matrix */
    710 int* capacities /**< machine capacities */
    711 )
    712{
    713 SCIP_HEUR* heur;
    714 SCIP_HEURDATA* heurdata;
    715 int m;
    716
    717 heur = SCIPfindHeur(scip, HEUR_NAME);
    718
    719 if( heur == NULL )
    720 {
    721 SCIPerrorMessage("optcumulative heuristic not found\n");
    722 return SCIP_PLUGINNOTFOUND;
    723 }
    724
    725 heurdata = SCIPheurGetData(heur);
    726 assert(heurdata != NULL);
    727
    728 /* copy the problem data */
    729 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->vars, nmachines) );
    730 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->binvars, nmachines) );
    731 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->durations, nmachines) );
    732 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->demands, nmachines) );
    733 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->machineassignments, nmachines) );
    734
    735 for( m = 0; m < nmachines; ++m )
    736 {
    737 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->vars[m], vars[m], machines[m]) ); /*lint !e866*/
    738 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->binvars[m], binvars[m], machines[m]) ); /*lint !e866*/
    739 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->durations[m], durations[m], machines[m]) ); /*lint !e866*/
    740 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->demands[m], demands[m], machines[m]) ); /*lint !e866*/
    741
    742 /* sort variable w.r.t. their objective coefficient */
    743 SCIPsortPtrPtrIntInt((void**)heurdata->binvars[m], (void**)heurdata->vars[m],
    744 heurdata->durations[m], heurdata->demands[m], SCIPvarCompObj, machines[m]);
    745
    746 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata->machineassignments[m]) ); /*lint !e866*/
    747 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->machineassignments[m]->vars), njobs) );
    748 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->machineassignments[m]->solvals), njobs) );
    749 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->machineassignments[m]->feasibles), njobs) );
    750 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->machineassignments[m]->keys), njobs) );
    751 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(heurdata->machineassignments[m]->nones), njobs) );
    752 heurdata->machineassignments[m]->nassignments = 0;
    753 heurdata->machineassignments[m]->sassignments = njobs;
    754 }
    755
    756 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->machines, machines, nmachines) );
    757 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &heurdata->capacities, capacities, nmachines) );
    758
    759 heurdata->nmachines = nmachines;
    760 heurdata->njobs = njobs;
    761 heurdata->initialized = TRUE;
    762
    763 return SCIP_OKAY;
    764}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    constraint handler for cumulative constraints
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    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_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    SCIP_VAR ** SCIPgetOrigVars(SCIP *scip)
    Definition: scip_prob.c:2811
    int SCIPgetNOrigVars(SCIP *scip)
    Definition: scip_prob.c:2838
    SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:111
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    int SCIPgetNPseudoBranchCands(SCIP *scip)
    Definition: scip_branch.c:766
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeur(SCIP *scip, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEURCOPY((*heurcopy)), SCIP_DECL_HEURFREE((*heurfree)), SCIP_DECL_HEURINIT((*heurinit)), SCIP_DECL_HEUREXIT((*heurexit)), SCIP_DECL_HEURINITSOL((*heurinitsol)), SCIP_DECL_HEUREXITSOL((*heurexitsol)), SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:67
    SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
    Definition: scip_heur.c:263
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Real SCIPgetPseudoObjval(SCIP *scip)
    Definition: scip_lp.c:339
    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
    int SCIPcalcMemGrowSize(SCIP *scip, int num)
    Definition: scip_mem.c:139
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
    Definition: scip_mem.h:111
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8483
    int SCIPgetProbingDepth(SCIP *scip)
    Definition: scip_probing.c:199
    SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
    Definition: scip_probing.c:581
    SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
    Definition: scip_probing.c:226
    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 SCIPcreateOrigSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:831
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4109
    SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:1892
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    void SCIPsortPtrPtrIntInt(void **ptrarray1, void **ptrarray2, int *intarray1, int *intarray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    #define heurInitsolOptcumulative
    static SCIP_DECL_HEUREXEC(heurExecOptcumulative)
    static SCIP_RETCODE initializeSol(SCIP *scip, SCIP_SOL *sol)
    #define DEFAULT_MAXNODES
    SCIP_RETCODE SCIPinitHeurOptcumulative(SCIP *scip, int nmachines, int njobs, int *machines, SCIP_VAR ***binvars, SCIP_VAR ***vars, int **durations, int **demands, int *capacities)
    #define HEUR_TIMING
    #define HEUR_FREQOFS
    #define HEUR_DESC
    static SCIP_RETCODE applyOptcumulativeFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Bool *infeasible)
    static SCIP_RETCODE applyOptcumulative(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_RESULT *result)
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    static void heurdataReset(SCIP *scip, SCIP_HEURDATA *heurdata)
    #define HEUR_NAME
    #define heurExitOptcumulative
    #define heurExitsolOptcumulative
    SCIP_RETCODE SCIPincludeHeurOptcumulative(SCIP *scip)
    #define HEUR_FREQ
    #define HEUR_USESSUBSCIP
    #define DEFAULT_MAXPROPROUNDS
    #define heurInitOptcumulative
    static SCIP_DECL_HEURCOPY(heurCopyOptcumulative)
    static SCIP_DECL_HEURFREE(heurFreeOptcumulative)
    heuristic for cumulative scheduling with optional activities
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugMessage
    Definition: pub_message.h:96
    SCIP_Real ** solvals
    SCIP_Bool * feasibles
    unsigned int * keys
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_FOUNDSOL
    Definition: type_result.h:56
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_PLUGINNOTFOUND
    Definition: type_retcode.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63