Scippy

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