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