Scippy

SCIP

Solving Constraint Integer Programs

prop_rootredcost.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file prop_rootredcost.c
26 * @ingroup DEFPLUGINS_PROP
27 * @brief reduced cost strengthening using root node reduced costs and the cutoff bound
28 * @author Tobias Achterberg
29 * @author Stefan Heinz
30 *
31 * This propagator uses the root reduced cost to (globally) propagate against the cutoff bound. The propagator checks if
32 * the variables with non-zero root reduced cost can exceed the cutoff bound. If this is the case the corresponding
33 * bound can be tightened.
34 *
35 * The propagate is performed during the search any time a new cutoff bound (primal solution) is found.
36 *
37 * @todo do not sort the variables; just store the cutoff bound which leads to a fixing. If that appears loop over all
38 * variables and fix and store the next cutoff bound which leads to an fixing
39 * @todo resolve the root LP in case of repropagation and update root reduced costs use root LP counter to check if new
40 * best root combinations might be available
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
46#include "scip/pub_message.h"
47#include "scip/pub_misc_sort.h"
48#include "scip/pub_prop.h"
49#include "scip/pub_var.h"
50#include "scip/scip_general.h"
51#include "scip/scip_lp.h"
52#include "scip/scip_mem.h"
53#include "scip/scip_message.h"
54#include "scip/scip_numerics.h"
55#include "scip/scip_param.h"
56#include "scip/scip_pricer.h"
57#include "scip/scip_prob.h"
58#include "scip/scip_probing.h"
59#include "scip/scip_prop.h"
61#include "scip/scip_tree.h"
62#include "scip/scip_var.h"
63#include <string.h>
64
65/**@name Propagator properties
66 *
67 * @{
68 */
69
70#define PROP_NAME "rootredcost"
71#define PROP_DESC "reduced cost strengthening using root node reduced costs and the cutoff bound"
72#define PROP_TIMING SCIP_PROPTIMING_BEFORELP | SCIP_PROPTIMING_AFTERLPLOOP
73#define PROP_PRIORITY +10000000 /**< propagator priority */
74#define PROP_FREQ 1 /**< propagator frequency */
75#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
76
77/**@} */
78
79/**@name Default parameter values
80 *
81 * @{
82 */
83#define DEFAULT_ONLYBINARY FALSE /**< should only binary variables be propagated? */
84#define DEFAULT_FORCE FALSE /**< should the propagator be forced even if active pricer are present? Note that
85 * the reductions are always valid, but installing an upper bound on priced
86 * variables may lead to problems in pricing (existing variables at their upper
87 * bound may be priced again since they may have negative reduced costs) */
88
89/**@} */
90
91
92/*
93 * Data structures
94 */
95
96/** propagator data */
97struct SCIP_PropData
98{
99 SCIP_VAR** redcostvars; /**< variables with non-zero root reduced cost */
100 SCIP_Real lastcutoffbound; /**< cutoff bound for which the root reduced costs were already processed */
101 int nredcostvars; /**< number of variables with non-zero root reduced cost */
102 int nredcostbinvars; /**< number of binary variables with non-zero root reduced cost */
103 int glbfirstnonfixed; /**< index of first globally non-fixed binary variable */
104 SCIP_Bool initialized; /**< is the propagator data initialized */
105 SCIP_Bool onlybinary; /**< should only binary variables be propagated? */
106 SCIP_Bool force; /**< should the propagator be forced even if active pricer are present? */
107};
108
109
110/**@name Local methods
111 *
112 * @{
113 */
114
115/** reset structure memember of propagator data structure */
116static
118 SCIP_PROPDATA* propdata /**< propagator data to reset */
119 )
120{
121 propdata->redcostvars = NULL;
122 propdata->lastcutoffbound = SCIP_INVALID;
123 propdata->nredcostvars = 0;
124 propdata->nredcostbinvars = 0;
125 propdata->glbfirstnonfixed = 0;
126 propdata->initialized = FALSE;
127}
128
129/** compare variables with non-zero reduced cost w.r.t.
130 * (i) the cutoff bound which would lead to a fixing
131 * (ii) variable problem index;
132 */
133static
135{
136 SCIP_VAR* var1 = (SCIP_VAR*)elem1;
137 SCIP_VAR* var2 = (SCIP_VAR*)elem2;
138 SCIP_Real key1;
139 SCIP_Real key2;
140
141 assert(SCIPvarIsBinary(var1));
142 assert(SCIPvarGetBestRootRedcost(var1) != 0.0);
143
144 assert(SCIPvarIsBinary(var2));
145 assert(SCIPvarGetBestRootRedcost(var2) != 0.0);
146
147 /* collect sorting key for both variables */
150
151 if( key1 < key2 )
152 return -1;
153 else if( key1 > key2 )
154 return +1;
155
156 /* second criterion: use the problem index
157 *
158 * @note The problem index is unique. That means the resulting sorting is unique.
159 */
160 return SCIPvarCompare(var1, var2);
161}
162
163/** create propagator data structure */
164static
166 SCIP* scip, /**< SCIP data structure */
167 SCIP_PROPDATA** propdata /**< pointer to store the created propagator data */
168 )
169{
170 SCIP_CALL( SCIPallocBlockMemory(scip, propdata) );
171
172 propdataReset(*propdata);
173
174 return SCIP_OKAY;
175}
176
177/** counts the number of variables with non-zero root reduced cost */
178static
180 SCIP* scip, /**< SCIP data structure */
181 SCIP_VAR** vars, /**< variable array */
182 int nvars /**< number of variables */
183 )
184{
185 int count;
186 int v;
187
188 count = 0;
189
190 /* count number of variables with non-zero root reduced cost */
191 for( v = 0; v < nvars; ++v )
192 {
193 SCIP_Real redcost;
194
195 assert(vars[v] != NULL);
196
197 redcost = SCIPvarGetBestRootRedcost(vars[v]);
198 if( !SCIPisDualfeasZero(scip, redcost) )
199 count++;
200 }
201
202 return count;
203}
204
205/** free propagator data */
206static
208 SCIP* scip, /**< SCIP data structure */
209 SCIP_PROPDATA* propdata /**< propagator data */
210 )
211{
212 int v;
213
214 /* release all variables */
215 for( v = 0; v < propdata->nredcostvars; ++v )
216 {
217 SCIP_CALL( SCIPreleaseVar(scip, &propdata->redcostvars[v]) );
218 }
219
220 /* free memory for non-zero reduced cost variables */
221 SCIPfreeBlockMemoryArrayNull(scip, &propdata->redcostvars, propdata->nredcostvars);
222
223 propdataReset(propdata);
224
225 return SCIP_OKAY;
226}
227
228/** initializate the propagator */
229static
231 SCIP* scip, /**< SCIP data structure */
232 SCIP_PROPDATA* propdata /**< propagator data */
233 )
234{
235 SCIP_VAR** vars;
236 int nvars;
237 int nbinvars;
238 int nredcostvars;
239 int nredcostbinvars;
240 int v;
241
242 assert(scip != NULL);
243 assert(propdata != NULL);
244
245 /* check if the propagator data structure is already initialized */
246 if( propdata->initialized )
247 return SCIP_OKAY;
248
249 /* get problem variables */
250 vars = SCIPgetVars(scip);
251 nvars = SCIPgetNVars(scip);
252 nbinvars = SCIPgetNBinVars(scip);
253
254 /* count binary variables with non-zero root reduced cost */
255 nredcostbinvars = countNonZeroRootRedcostVars(scip, vars, nbinvars);
256 SCIPdebugMsg(scip, "There are %d (poor) binary variables with non-zero root reduced cost <%s>.\n", nredcostbinvars, SCIPgetProbName(scip));
257
258 /* count non-binary variables with non-zero root reduced cost */
259 nredcostvars = countNonZeroRootRedcostVars(scip, &vars[nbinvars], nvars - nbinvars);
260
261 nredcostvars += nredcostbinvars;
262
263 /* collect the variables with non-zero reduced costs */
264 if( nredcostvars > 0 )
265 {
266 int k;
267
268 k = 0;
269 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &propdata->redcostvars, nredcostvars) );
270
271 SCIPdebugMsg(scip, "Store non-zero root reduced cost variables at address <%p>.\n", (void*)propdata->redcostvars);
272
273 for( v = 0; v < nvars; ++v )
274 {
275 SCIP_Real redcost;
276 SCIP_VAR* var;
277
278 var = vars[v];
279 redcost = SCIPvarGetBestRootRedcost(var);
280
281 if( SCIPisDualfeasZero(scip, redcost) )
282 continue;
283
284 assert(k < nredcostvars);
285
286 /* check if one of the non-binary variables is implicit binary */
287 if( k >= nredcostbinvars && SCIPvarIsBinary(var) )
288 {
289 /* move the first non-binary variable to end of the array */
290 propdata->redcostvars[k] = propdata->redcostvars[nredcostbinvars];
291
292 /* place the binary variable at the end of the binary section */
293 propdata->redcostvars[nredcostbinvars] = var;
294 nredcostbinvars++;
295 }
296 else
297 propdata->redcostvars[k] = var;
298
299 /* captures the variable */
300 SCIP_CALL( SCIPcaptureVar(scip, var) ) ;
301
302 k++;
303
304 /* check if already visited all variable with non-zero redcostective coefficient */
305 if( k == nredcostvars )
306 break;
307 }
308
309 /* sort binary variables with respect to their cutoff bound which would lead to an fixing; this order can be used
310 * to efficiently propagate the binary variables
311 */
312 SCIPsortDownPtr((void**)propdata->redcostvars, varCompRedcost, nredcostbinvars);
313
314 assert(k == nredcostvars);
315
316 SCIPdebugMsg(scip, "variables with non-zero redcostective coefficient: %d binaries, %d non-binaries\n", nredcostbinvars, nredcostvars - nredcostbinvars);
317 }
318
319 propdata->nredcostvars = nredcostvars;
320 propdata->nredcostbinvars = nredcostbinvars;
321 propdata->glbfirstnonfixed = 0;
322 propdata->lastcutoffbound = SCIPinfinity(scip);
323 propdata->initialized = TRUE;
324
325 return SCIP_OKAY;
326}
327
328/** propagates the root reduced cost against the cutoff bound for the given variable */
329static
331 SCIP* scip, /**< SCIP data structure */
332 SCIP_VAR* var, /**< variable to propagate */
333 SCIP_Real cutoffbound, /**< cutoff bound to use */
334 SCIP_Bool* infeasible, /**< pointer to store whether the new domain is empty */
335 SCIP_Bool* tightened /**< pointer to store if the bound was tightened */
336 )
337{
338 SCIP_Real rootsol;
339 SCIP_Real rootredcost;
340 SCIP_Real rootlpobjval;
341 SCIP_Real newbd;
342
343 rootredcost = SCIPvarGetBestRootRedcost(var);
344 assert(rootredcost != SCIP_INVALID); /*lint !e777*/
345
346 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
347 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
348 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
349 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
350 */
351 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasZero(scip, rootredcost));
352
353 rootsol = SCIPvarGetBestRootSol(var);
354 rootlpobjval = SCIPvarGetBestRootLPObjval(var);
355
356 /* calculate reduced cost based bound */
357 newbd = rootsol + (cutoffbound - rootlpobjval) / rootredcost;
358
359 if( SCIPisDualfeasPositive(scip, rootredcost) )
360 {
361 assert(SCIPisFeasLE(scip, rootsol, SCIPvarGetLbGlobal(var))); /* lb might have been increased in the meantime */
362
363 /* strengthen upper bound */
364 SCIP_CALL( SCIPtightenVarUbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
365 }
366 else
367 {
368 assert(!SCIPisLPDualReliable(scip) || SCIPisDualfeasNegative(scip, rootredcost));
369 assert(SCIPisFeasGE(scip, rootsol, SCIPvarGetUbGlobal(var))); /* ub might have been decreased in the meantime */
370
371 /* strengthen lower bound */
372 SCIP_CALL( SCIPtightenVarLbGlobal(scip, var, newbd, FALSE, infeasible, tightened) );
373 }
374
375 return SCIP_OKAY;
376}
377
378/** propagate binary variables with non-zero root reduced cost */
379static
381 SCIP* scip, /**< SCIP data structure */
382 SCIP_PROPDATA* propdata, /**< propagator data structure */
383 SCIP_Real cutoffbound, /**< cutoff bound to use */
384 int* nchgbds, /**< pointer to store the number of bound changes */
385 SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */
386 )
387{
388 SCIP_VAR** redcostvars;
389 int v;
390
391 assert(!(*cutoff));
392
393 /* the binary variables are stored in the beginning of the variable array; these variables are sorted w.r.t. cutoff
394 * bound which would lead to a fixing; that give us an abort criterion (see below)
395 */
396 redcostvars = propdata->redcostvars;
397 assert(redcostvars != NULL);
398
399#ifndef NDEBUG
400 /* check that the binary variables are correctly sorted
401 *
402 * @note In case the assertion fails it indicates that a new LP root solving arose after we initialized the
403 * propagator; The new LP solution destroyed the sorting of the binary variables since the reduced cost of the
404 * variables changed. This could lead to potentially missing a domain reductions. Currently, it is not possible to
405 * check if a new root LP was solved, changing the root reduced costs. This case, however, should not happen in the
406 * current SCIP version.
407 */
408 for( v = 1; v < propdata->nredcostbinvars; ++v )
409 assert(varCompRedcost(redcostvars[v-1], redcostvars[v]) == 1);
410
411 /* check that the variables before glbfirstnonfixed are globally fixed */
412 for( v = 0; v < propdata->glbfirstnonfixed; ++v )
413 {
414 SCIP_VAR* var;
415
416 var = redcostvars[v];
417 assert(var != NULL);
418
419 assert(SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5);
420 }
421#endif
422
423 /* propagate binary variables */
424 for( v = propdata->glbfirstnonfixed; v < propdata->nredcostbinvars; ++v )
425 {
426 SCIP_VAR* var;
427 SCIP_Bool tightened;
428
429 var = redcostvars[v];
430 assert(var != NULL);
431
432 /* check if the variables is already globally fixed; if so continue with the next potential candidate */
433 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
434 continue;
435
436 /* try to tighten the variable bound */
437 SCIP_CALL( propagateRootRedcostVar(scip, var, cutoffbound, cutoff, &tightened) );
438
439 if( tightened )
440 {
441 /* @note The variable might not be globally fixed right away since this would destroy the local internal data
442 * structure of a search node; the bound change is in that case pending; hence we cannot assert that the
443 * variable is globally fixed
444 */
445 assert(!(*cutoff));
446
447 SCIPdebugMsg(scip, "globally fixed binary variable <%s> [%g,%g] bestroot sol <%g>, redcost <%g>, lpobj <%g>\n",
450
451 (*nchgbds)++;
452 }
453 else
454 {
455 assert(!tightened);
456
457 /* The binary variables are sorted in non-increasing manner w.r.t. their cutoff bound which would lead to a
458 * global fixing; That is, abs(rootredcost) + rootlpobjval. Depending on the sign of the reduced cost the
459 * following two cases can arise for binary variables which are not fixed globally yet:
460 *
461 * - redcost > 0 --> newub = 0.0 + (cutoffbound - lpobjval) / redcost --> newub = 0 <=> cutoffbound < redcost + lpobjval = sorting key
462 * - redcost < 0 --> newlb = 1.0 + (cutoffbound - lpobjval) / redcost --> newlb = 1 <=> cutoffbound < -redcost + lpobjval = sorting key
463 *
464 * Due to the order of the binary variables it follows if one binary variable cannot be fixed anymore all the
465 * remaining once can also not be fixed since these have only an smaller or equal cutoff bound which would lead
466 * to global fixing. Hence, we can break that loop.
467 *
468 * Note that variables with non-zero reduced cost are sitting at one of their bound. That is the lower one if
469 * the reduced cost are positive and the upper bound if the reduced cost are negative. For binary variables
470 * that is 0 for the lower bound and 1 for the upper bound.
471 */
472 SCIPdebugMsg(scip, "interrupt propagation for binary variables after %d from %d binary variables\n",
473 v, propdata->nredcostbinvars);
474
475 if( *cutoff )
476 {
477 SCIPdebugMsg(scip, "detected cutoff: binary variable <%s> [%g,%g], redcost <%g>, rootsol <%g>, rootlpobjval <%g>\n",
480 }
481
482 break;
483 }
484 }
485 /* store the index of the variable which is not globally fixed */
486 propdata->glbfirstnonfixed = v;
487
488#ifdef SCIP_DISABLED_CODE
489 /* Due to numerics it might be that the abort criterion did not work correctly, because the sorting mechanism may
490 * have evaluated variables with a really small difference in their reduced cost values but with really huge
491 * lpobjval as the same. Thus, we disable the check below for now.
492 */
493#ifndef NDEBUG
494 /* check that the abort criterion works; that means none of the remaining binary variables can be fixed */
495 for( ; v < propdata->nredcostbinvars && !(*cutoff); ++v )
496 {
497 SCIP_VAR* var;
498 SCIP_Bool tightened;
499
500 var = redcostvars[v];
501 assert(var != NULL);
502
503 /* check if the variables is already globally fixed; if so continue with the potential candidate */
504 if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5)
505 continue;
506
507 /* try to tighten the variable bound */
508 SCIP_CALL( propagateRootRedcostVar(scip, var, cutoffbound, cutoff, &tightened) );
509 assert(!tightened);
510 assert(!(*cutoff));
511 }
512#endif
513#endif
514
515 return SCIP_OKAY;
516}
517
518/**@} */
519
520
521/**@name Callback methods of propagator
522 *
523 * @{
524 */
525
526/** copy method for propagator plugins (called when SCIP copies plugins) */
527static
528SCIP_DECL_PROPCOPY(propCopyRootredcost)
529{ /*lint --e{715}*/
530 assert(scip != NULL);
531 assert(prop != NULL);
532 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
533
534 /* call inclusion method of propagator */
536
537 return SCIP_OKAY;
538}
539
540/** destructor of propagator to free user data (called when SCIP is exiting) */
541static
542SCIP_DECL_PROPFREE(propFreeRootredcost)
543{ /*lint --e{715}*/
544 SCIP_PROPDATA* propdata;
545
546 /* free propagator data */
547 propdata = SCIPpropGetData(prop);
548 assert(propdata != NULL);
549 assert(propdata->redcostvars == NULL);
550
551 SCIPfreeBlockMemory(scip, &propdata);
552 SCIPpropSetData(prop, NULL);
553
554 return SCIP_OKAY;
555}
556
557/** solving process deinitialization method of propagator (called before branch and bound process data is freed) */
558static
559SCIP_DECL_PROPEXITSOL(propExitsolRootredcost)
560{ /*lint --e{715}*/
561 SCIP_PROPDATA* propdata;
562
563 propdata = SCIPpropGetData(prop);
564 assert(propdata != NULL);
565
566 /* reset propagator data structure */
567 SCIP_CALL( propdataExit(scip, propdata) );
568
569 return SCIP_OKAY;
570}
571
572/** execution method of propagator */
573static
574SCIP_DECL_PROPEXEC(propExecRootredcost)
575{ /*lint --e{715}*/
576 SCIP_PROPDATA* propdata;
577 SCIP_VAR** redcostvars;
578 SCIP_Real cutoffbound;
579 SCIP_Real lpobjval;
580 SCIP_Bool cutoff;
581 int nredcostvars;
582 int nchgbds;
583 int v;
584
585 *result = SCIP_DIDNOTRUN;
586
587 /* in case we have a zero objective fucntion, we skip the root reduced cost propagator */
588 if( SCIPgetNObjVars(scip) == 0 )
589 return SCIP_OKAY;
590
591 /* propagator can only be applied during solving stage */
593 return SCIP_OKAY;
594
595 /* the propagator should run in all nodes except the root node; for the root node the redcost propagator does
596 * the job already
597 */
598 if( SCIPgetDepth(scip) < 1 )
599 return SCIP_OKAY;
600
601 /* first check root LP objective value if it exists */
602 lpobjval = SCIPgetLPRootObjval(scip);
603 if( lpobjval == SCIP_INVALID ) /*lint !e777*/
604 return SCIP_OKAY;
605
606 /* do not run in probing mode since this propagator changes global variable bounds */
607 if( SCIPinProbing(scip) )
608 return SCIP_OKAY;
609
610 /* do not run if propagation w.r.t. objective is not allowed */
612 return SCIP_OKAY;
613
614 /* get propagator data */
615 propdata = SCIPpropGetData(prop);
616 assert(propdata != NULL);
617
618 /* do nothing if active pricer are present and force flag is not TRUE */
619 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
620 return SCIP_OKAY;
621
622 /* get current cutoff bound */
623 cutoffbound = SCIPgetCutoffbound(scip);
624
625 /* reduced cost strengthening can only be applied, if we have a finite upper bound on the LP value */
626 if( SCIPisInfinity(scip, cutoffbound) )
627 return SCIP_OKAY;
628
629 /* initialize propagator data structure */
630 SCIP_CALL( propdataInit(scip, propdata) );
631 assert(cutoffbound <= propdata->lastcutoffbound);
632
633 if( cutoffbound == propdata->lastcutoffbound ) /*lint !e777*/
634 return SCIP_OKAY;
635
636 /* get variables */
637 redcostvars = propdata->redcostvars;
638 nredcostvars = propdata->nredcostvars;
639
640 /* since no variables has non-zero reduced cost do nothing */
641 if( nredcostvars == 0 )
642 return SCIP_OKAY;
643
644 /* store cutoff bound to remember later that for that particular cutoff bound the propagation was already
645 * preformed
646 */
647 propdata->lastcutoffbound = cutoffbound;
648
649 SCIPdebugMsg(scip, "searching for root reduced cost fixings\n");
650 SCIPdebugMsg(scip, "-> cutoffbound <%g>\n", cutoffbound);
651 SCIPdebugMsg(scip, "-> LP objective value <%g>\n", lpobjval);
652
653 *result = SCIP_DIDNOTFIND;
654 nchgbds = 0;
655 cutoff = FALSE;
656
657 /* propagate the binary variables with non-zero root reduced cost */
658 SCIP_CALL( propagateBinaryBestRootRedcost(scip, propdata, cutoffbound, &nchgbds, &cutoff) );
659
660 if( !propdata->onlybinary )
661 {
662 /* check reduced costs for non-binary variables that were columns of the root LP */
663 for( v = propdata->nredcostbinvars; v < nredcostvars && !cutoff; ++v )
664 {
665 SCIP_VAR* var;
666 SCIP_Bool tightened;
667
668 var = redcostvars[v];
669 assert(var != NULL);
670
671 /* try to tighten the variable bound */
672 SCIP_CALL( propagateRootRedcostVar(scip, var, cutoffbound, &cutoff, &tightened) );
673
674 if( tightened )
675 nchgbds++;
676 }
677 }
678
679 /* evaluate propagation results */
680 if( cutoff )
681 {
682 /* we are done with solving since the cutoff is w.r.t. a global bound change; cutoff root node */
684 (*result) = SCIP_CUTOFF;
685 }
686 else if( nchgbds > 0 )
687 (*result) = SCIP_REDUCEDDOM;
688
689 SCIPdebugMsg(scip, "tightened %d variable domains (%u cutoff)\n", nchgbds, cutoff);
690
691 return SCIP_OKAY;
692}
693
694/**@} */
695
696
697/** creates the root node reduced cost strengthening propagator and includes it in SCIP */
699 SCIP* scip /**< SCIP data structure */
700 )
701{
702 SCIP_PROPDATA* propdata;
703 SCIP_PROP* prop;
704
705 /* create rootredcost propagator data */
706 SCIP_CALL( propdataCreate(scip, &propdata) );
707
708 /* include propagator */
710 propExecRootredcost, propdata) );
711
712 assert(prop != NULL);
713
714 /* set optional callbacks via setter functions */
715 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyRootredcost) );
716 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeRootredcost) );
717 SCIP_CALL( SCIPsetPropExitsol(scip, prop, propExitsolRootredcost) );
718
720 "propagating/" PROP_NAME "/onlybinary",
721 "should only binary variables be propagated?",
722 &propdata->onlybinary, TRUE, DEFAULT_ONLYBINARY, NULL, NULL) );
724 "propagating/" PROP_NAME "/force",
725 "should the propagator be forced even if active pricer are present?",
726 &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
727
728 return SCIP_OKAY;
729}
#define NULL
Definition: def.h:266
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:172
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define REALABS(x)
Definition: def.h:196
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1067
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip_prob.c:1947
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2037
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
SCIP_RETCODE SCIPincludePropRootredcost(SCIP *scip)
SCIP_Real SCIPgetLPRootObjval(SCIP *scip)
Definition: scip_lp.c:372
SCIP_Bool SCIPisLPDualReliable(SCIP *scip)
Definition: scip_lp.c:207
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:799
SCIP_PROPDATA * SCIPpropGetData(SCIP_PROP *prop)
Definition: prop.c:789
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:941
SCIP_RETCODE SCIPsetPropFree(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPFREE((*propfree)))
Definition: scip_prop.c:167
SCIP_RETCODE SCIPsetPropCopy(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPCOPY((*propcopy)))
Definition: scip_prop.c:151
SCIP_RETCODE SCIPsetPropExitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPEXITSOL((*propexitsol)))
Definition: scip_prop.c:231
SCIP_RETCODE SCIPincludePropBasic(SCIP *scip, SCIP_PROP **propptr, const char *name, const char *desc, int priority, int freq, SCIP_Bool delay, SCIP_PROPTIMING timingmask, SCIP_DECL_PROPEXEC((*propexec)), SCIP_PROPDATA *propdata)
Definition: scip_prop.c:114
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisDualfeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisDualfeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition: scip_tree.c:436
SCIP_NODE * SCIPgetRootNode(SCIP *scip)
Definition: scip_tree.c:110
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17598
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6471
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13714
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18087
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17418
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip_var.c:1248
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18077
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13781
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11941
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13815
SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
Definition: scip_var.c:8779
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1214
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:6351
void SCIPsortDownPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define PROP_DESC
#define DEFAULT_ONLYBINARY
#define PROP_NAME
static SCIP_DECL_PROPFREE(propFreeRootredcost)
static SCIP_RETCODE propagateBinaryBestRootRedcost(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_Real cutoffbound, int *nchgbds, SCIP_Bool *cutoff)
static SCIP_RETCODE propagateRootRedcostVar(SCIP *scip, SCIP_VAR *var, SCIP_Real cutoffbound, SCIP_Bool *infeasible, SCIP_Bool *tightened)
static SCIP_RETCODE propdataInit(SCIP *scip, SCIP_PROPDATA *propdata)
static SCIP_DECL_PROPEXITSOL(propExitsolRootredcost)
#define PROP_DELAY
static void propdataReset(SCIP_PROPDATA *propdata)
static SCIP_RETCODE propdataExit(SCIP *scip, SCIP_PROPDATA *propdata)
#define PROP_TIMING
static SCIP_RETCODE propdataCreate(SCIP *scip, SCIP_PROPDATA **propdata)
static int countNonZeroRootRedcostVars(SCIP *scip, SCIP_VAR **vars, int nvars)
static SCIP_DECL_PROPEXEC(propExecRootredcost)
static SCIP_DECL_PROPCOPY(propCopyRootredcost)
#define PROP_FREQ
#define DEFAULT_FORCE
#define PROP_PRIORITY
static SCIP_DECL_SORTPTRCOMP(varCompRedcost)
reduced cost strengthening using root node reduced costs and the cutoff bound
public methods for message output
methods for sorting joint arrays of various types
public methods for propagators
public methods for problem variables
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for variable pricer plugins
public methods for global and local (sub)problems
public methods for the probing mode
public methods for propagator plugins
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
struct SCIP_PropData SCIP_PROPDATA
Definition: type_prop.h:52
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_REDUCEDDOM
Definition: type_result.h:51
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_SOLVING
Definition: type_set.h:53