Scippy

SCIP

Solving Constraint Integer Programs

prop_redcost.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_redcost.c
26 * @ingroup DEFPLUGINS_PROP
27 * @brief propagator using the LP reduced cost and the cutoff bound
28 * @author Tobias Achterberg
29 * @author Stefan Heinz
30 * @author Matthias Miltenberger
31 * @author Michael Winkler
32 *
33 * This propagator uses the reduced cost of an optimal solved LP relaxation to propagate the variables against the
34 * cutoff bound.
35 */
36
37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38
39#include "lpi/type_lpi.h"
40#include "scip/prop_redcost.h"
41#include "scip/pub_lp.h"
42#include "scip/pub_message.h"
43#include "scip/pub_prop.h"
44#include "scip/pub_tree.h"
45#include "scip/pub_var.h"
46#include "scip/scip_branch.h"
47#include "scip/scip_general.h"
48#include "scip/scip_lp.h"
49#include "scip/scip_mem.h"
50#include "scip/scip_message.h"
51#include "scip/scip_numerics.h"
52#include "scip/scip_param.h"
53#include "scip/scip_pricer.h"
54#include "scip/scip_prob.h"
55#include "scip/scip_prop.h"
57#include "scip/scip_tree.h"
58#include "scip/scip_var.h"
59#include <string.h>
60
61/**@name Propagator properties
62 *
63 * @{
64 */
65
66#define PROP_NAME "redcost"
67#define PROP_DESC "reduced cost strengthening propagator"
68#define PROP_TIMING SCIP_PROPTIMING_DURINGLPLOOP | SCIP_PROPTIMING_AFTERLPLOOP
69#define PROP_PRIORITY +1000000 /**< propagator priority */
70#define PROP_FREQ 1 /**< propagator frequency */
71#define PROP_DELAY FALSE /**< should propagation method be delayed, if other propagators found reductions? */
72
73/**@} */
74
75
76/**@name Default parameter values
77 *
78 * @{
79 */
80
81#define DEFAULT_CONTINUOUS FALSE /**< should reduced cost fixing be also applied to continuous variables? */
82#define DEFAULT_USEIMPLICS FALSE /**< should implications be used to strength the reduced cost for binary variables? */
83#define DEFAULT_FORCE FALSE /**< should the propagator be forced even if active pricer are present? Note that
84 * the reductions are always valid, but installing an upper bound on priced
85 * variables may lead to problems in pricing (existing variables at their upper
86 * bound may be priced again since they may have negative reduced costs) */
87
88/**@} */
89
90
91/*
92 * Data structures
93 */
94
95
96/** propagator data */
97struct SCIP_PropData
98{
99 SCIP_Bool continuous; /**< should reduced cost fixing be also applied to continuous variables? */
100 SCIP_Real maxredcost; /**< maximum reduced cost of a single binary variable */
101 SCIP_Bool usefullimplics; /**< are the implied reduced cost useful */
102 SCIP_Bool useimplics; /**< should implications be used to strength the reduced cost for binary variables? */
103 SCIP_Bool force; /**< should the propagator be forced even if active pricer are present? */
104};
105
106
107/**@name Local methods
108 *
109 * @{
110 */
111
112/** propagate the given binary variable/column using the root reduced cost stored in the SCIP internal data structures
113 * and check if the implications can be useful. Depending on that implications are used or not used during the search to
114 * strength the reduced costs.
115 */
116static
118 SCIP* scip, /**< SCIP data structure */
119 SCIP_PROPDATA* propdata, /**< propagator data structure */
120 SCIP_VAR* var, /**< variable to use for propagation */
121 SCIP_COL* col, /**< LP column of the variable */
122 SCIP_Real cutoffbound, /**< the current cutoff bound */
123 int* nchgbds /**< pointer to count the number of bound changes */
124 )
125{
126 SCIP_Real rootredcost;
127 SCIP_Real rootsol;
128 SCIP_Real rootlpobjval;
129
130 assert(scip != NULL);
131 assert(SCIPgetDepth(scip) == 0);
132
133 /* skip binary variable if it is locally fixed */
134 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
135 return SCIP_OKAY;
136
137 rootredcost = SCIPvarGetBestRootRedcost(var);
138 rootsol = SCIPvarGetBestRootSol(var);
139 rootlpobjval = SCIPvarGetBestRootLPObjval(var);
140
141 if( SCIPisDualfeasZero(scip, rootredcost) )
142 return SCIP_OKAY;
143
144 assert(rootlpobjval != SCIP_INVALID); /*lint !e777*/
145
146 if( rootsol > 0.5 )
147 {
148 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
149 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
150 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
151 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
152 */
153 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasPositive(scip, rootredcost));
154
155 /* update maximum reduced cost of a single binary variable */
156 propdata->maxredcost = MAX(propdata->maxredcost, -rootredcost);
157
158 if( rootlpobjval - rootredcost > cutoffbound )
159 {
160 SCIPdebugMsg(scip, "globally fix binary variable <%s> to 1.0\n", SCIPvarGetName(var));
161
162 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
163 (*nchgbds)++;
164 return SCIP_OKAY;
165 }
166 }
167 else
168 {
169 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
170 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
171 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
172 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
173 */
174 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasNegative(scip, rootredcost));
175
176 /* update maximum reduced cost of a single binary variable */
177 propdata->maxredcost = MAX(propdata->maxredcost, rootredcost);
178
179 if( rootlpobjval + rootredcost > cutoffbound )
180 {
181 SCIPdebugMsg(scip, "globally fix binary variable <%s> to 0.0\n", SCIPvarGetName(var));
182
183 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
184 (*nchgbds)++;
185 return SCIP_OKAY;
186 }
187 }
188
189 /* evaluate if the implications are useful; the implications are seen to be useful if they provide an increase for
190 * the root reduced costs
191 */
192 if( !propdata->usefullimplics )
193 {
194 SCIP_Real lbredcost;
195 SCIP_Real ubredcost;
196
197 lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
198 assert(!SCIPisDualfeasPositive(scip, lbredcost));
199
200 ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
201 assert(!SCIPisDualfeasNegative(scip, ubredcost));
202
203 switch( SCIPcolGetBasisStatus(col) )
204 {
206 ubredcost -= SCIPgetVarRedcost(scip, var);
207
208 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
209 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
210 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
211 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
212 */
213 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasNegative(scip, ubredcost));
214 break;
215
217 lbredcost -= SCIPgetVarRedcost(scip, var);
218
219 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
220 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
221 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
222 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
223 */
224 assert(!SCIPisLPDualReliable(scip) || !SCIPisDualfeasPositive(scip, lbredcost));
225 break;
226
229 default:
230 break;
231 }
232
233 propdata->usefullimplics = (lbredcost < 0.0) || (ubredcost > 0.0);
234 }
235
236 return SCIP_OKAY;
237}
238
239/** propagate the given binary variable/column using the reduced cost */
240static
242 SCIP* scip, /**< SCIP data structure */
243 SCIP_PROPDATA* propdata, /**< propagator data structure */
244 SCIP_VAR* var, /**< variable to use for propagation */
245 SCIP_COL* col, /**< LP column of the variable */
246 SCIP_Real requiredredcost, /**< required reduset cost to be able to fix a binary variable */
247 int* nchgbds, /**< pointer to count the number of bound changes */
248 SCIP_Bool* cutoff /**< pointer to store if an cutoff was detected */
249 )
250{
251 SCIP_Real lbredcost;
252 SCIP_Real ubredcost;
253 SCIP_Real redcost;
254
255 /* skip binary variable if it is locally fixed */
256 if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
257 return SCIP_OKAY;
258
259 /* first use the redcost cost to fix the binary variable */
260 switch( SCIPcolGetBasisStatus(col) )
261 {
263 redcost = SCIPgetVarRedcost(scip, var);
264
265 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
266 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
267 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
268 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
269 */
271
272 if( redcost > requiredredcost )
273 {
274 SCIPdebugMsg(scip, "variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>)\n",
275 SCIPvarGetName(var), requiredredcost, redcost);
276
277 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
278 (*nchgbds)++;
279 return SCIP_OKAY;
280 }
281 break;
282
284 redcost = SCIPgetVarRedcost(scip, var);
285
286 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
287 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
288 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
289 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
290 */
292
293 if( -redcost > requiredredcost )
294 {
295 SCIPdebugMsg(scip, "variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>)\n",
296 SCIPvarGetName(var), requiredredcost, redcost);
297
298 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
299 (*nchgbds)++;
300 return SCIP_OKAY;
301 }
302 break;
303
305 return SCIP_OKAY;
306
308 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
309 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
310 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
311 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
312 */
314 return SCIP_OKAY;
315
316 default:
317 SCIPerrorMessage("invalid basis state\n");
318 return SCIP_INVALIDDATA;
319 }
320
321 /* second, if the implications should be used and if the implications are seen to be promising use the implied
322 * reduced costs to fix the binary variable
323 */
324 if( propdata->useimplics && propdata->usefullimplics )
325 {
326 /* collect implied reduced costs if the variable would be fixed to its lower bound */
327 lbredcost = SCIPgetVarImplRedcost(scip, var, FALSE);
328
329 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
330 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
331 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
332 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
333 */
336
337 /* collect implied reduced costs if the variable would be fixed to its upper bound */
338 ubredcost = SCIPgetVarImplRedcost(scip, var, TRUE);
341
342 if( -lbredcost > requiredredcost && ubredcost > requiredredcost )
343 {
344 SCIPdebugMsg(scip, "variable <%s>: cutoff (requiredredcost <%g>, lbredcost <%g>, ubredcost <%g>)\n",
345 SCIPvarGetName(var), requiredredcost, lbredcost, ubredcost);
346
347 (*cutoff) = TRUE;
348 }
349 else if( -lbredcost > requiredredcost )
350 {
351 SCIPdebugMsg(scip, "variable <%s>: fixed 1.0 (requiredredcost <%g>, redcost <%g>, lbredcost <%g>)\n",
352 SCIPvarGetName(var), requiredredcost, redcost, lbredcost);
353
354 SCIP_CALL( SCIPchgVarLb(scip, var, 1.0) );
355 (*nchgbds)++;
356 }
357 else if( ubredcost > requiredredcost )
358 {
359 SCIPdebugMsg(scip, "variable <%s>: fixed 0.0 (requiredredcost <%g>, redcost <%g>, ubredcost <%g>)\n",
360 SCIPvarGetName(var), requiredredcost, redcost, ubredcost);
361
362 SCIP_CALL( SCIPchgVarUb(scip, var, 0.0) );
363 (*nchgbds)++;
364 }
365
366 /* update maximum reduced cost of a single binary variable */
367 propdata->maxredcost = MAX3(propdata->maxredcost, -lbredcost, ubredcost);
368 }
369
370 return SCIP_OKAY;
371}
372
373/** propagate the given none binary variable/column using the reduced cost */
374static
376 SCIP* scip, /**< SCIP data structure */
377 SCIP_VAR* var, /**< variable to use for propagation */
378 SCIP_COL* col, /**< LP column of the variable */
379 SCIP_Real lpobjval, /**< objective value of the current LP */
380 SCIP_Real cutoffbound, /**< the current cutoff bound */
381 int* nchgbds /**< pointer to count the number of bound changes */
382 )
383{
384 SCIP_Real redcost;
385
386 switch( SCIPcolGetBasisStatus(col) )
387 {
389 redcost = SCIPgetColRedcost(scip, col);
390
391 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
392 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
393 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
394 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
395 */
398
399 if( SCIPisDualfeasPositive(scip, redcost) )
400 {
401 SCIP_Real oldlb;
402 SCIP_Real oldub;
403
404 oldlb = SCIPvarGetLbLocal(var);
405 oldub = SCIPvarGetUbLocal(var);
406 assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
407 assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));
408
409 if( SCIPisFeasLT(scip, oldlb, oldub) )
410 {
411 SCIP_Real newub;
412 SCIP_Bool strengthen;
413
414 /* calculate reduced cost based bound */
415 newub = (cutoffbound - lpobjval) / redcost + oldlb;
416
417 /* check, if new bound is good enough:
418 * - integer variables: take all possible strengthenings
419 * - continuous variables: strengthening must cut part of the variable's dynamic range, and
420 * at least 20% of the current domain
421 */
422 if( SCIPvarIsIntegral(var) )
423 {
424 newub = SCIPadjustedVarUb(scip, var, newub);
425 strengthen = (newub < oldub - 0.5);
426 }
427 else
428 strengthen = (newub < SCIPcolGetMaxPrimsol(col) && newub <= 0.2 * oldlb + 0.8 * oldub);
429
430 if( strengthen )
431 {
432 /* strengthen upper bound */
433 SCIPdebugMsg(scip, "redcost strengthening upper bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
434 SCIPvarGetName(var), oldlb, oldub, oldlb, newub, cutoffbound, lpobjval, redcost);
435 SCIP_CALL( SCIPchgVarUb(scip, var, newub) );
436 (*nchgbds)++;
437 }
438 }
439 }
440 break;
441
443 break;
444
446 redcost = SCIPgetColRedcost(scip, col);
447
448 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
449 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
450 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
451 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
452 */
455
456 if( SCIPisDualfeasNegative(scip, redcost) )
457 {
458 SCIP_Real oldlb;
459 SCIP_Real oldub;
460
461 oldlb = SCIPvarGetLbLocal(var);
462 oldub = SCIPvarGetUbLocal(var);
463 assert(SCIPisEQ(scip, oldlb, SCIPcolGetLb(col)));
464 assert(SCIPisEQ(scip, oldub, SCIPcolGetUb(col)));
465
466 if( SCIPisFeasLT(scip, oldlb, oldub) )
467 {
468 SCIP_Real newlb;
469 SCIP_Bool strengthen;
470
471 /* calculate reduced cost based bound */
472 newlb = (cutoffbound - lpobjval) / redcost + oldub;
473
474 /* check, if new bound is good enough:
475 * - integer variables: take all possible strengthenings
476 * - continuous variables: strengthening must cut part of the variable's dynamic range, and
477 * at least 20% of the current domain
478 */
479 if( SCIPvarIsIntegral(var) )
480 {
481 newlb = SCIPadjustedVarLb(scip, var, newlb);
482 strengthen = (newlb > oldlb + 0.5);
483 }
484 else
485 strengthen = (newlb > SCIPcolGetMinPrimsol(col) && newlb >= 0.8 * oldlb + 0.2 * oldub);
486
487 /* check, if new bound is good enough: at least 20% strengthening for continuous variables */
488 if( strengthen )
489 {
490 /* strengthen lower bound */
491 SCIPdebugMsg(scip, "redcost strengthening lower bound: <%s> [%g,%g] -> [%g,%g] (ub=%g, lb=%g, redcost=%g)\n",
492 SCIPvarGetName(var), oldlb, oldub, newlb, oldub, cutoffbound, lpobjval, redcost);
493 SCIP_CALL( SCIPchgVarLb(scip, var, newlb) );
494 (*nchgbds)++;
495 }
496 }
497 }
498 break;
499
501 /* SCIPisLPDualReliable should always return TRUE if the dual feasibility check is enabled and the LP claims to
502 * have a dual feasible solution. if the check is disabled the dual solution might be incorrect and the assert
503 * might fail. however, if the user decides to disable the dual feasibility check (which also can lead to wrong
504 * cutoffs) we don't want to skip propagating with reduced costs as an unexpected side-effect.
505 */
507 break;
508
509 default:
510 SCIPerrorMessage("invalid basis state\n");
511 return SCIP_INVALIDDATA;
512 }
513
514 return SCIP_OKAY;
515}
516
517/**@} */
518
519/**@name Callback methods of propagator
520 *
521 * @{
522 */
523
524/** copy method for propagator plugins (called when SCIP copies plugins) */
525static
526SCIP_DECL_PROPCOPY(propCopyRedcost)
527{ /*lint --e{715}*/
528 assert(scip != NULL);
529 assert(prop != NULL);
530 assert(strcmp(SCIPpropGetName(prop), PROP_NAME) == 0);
531
532 /* call inclusion method of constraint handler */
534
535 return SCIP_OKAY;
536}
537
538/** destructor of propagator to free user data (called when SCIP is exiting) */
539/**! [SnippetPropFreeRedcost] */
540static
541SCIP_DECL_PROPFREE(propFreeRedcost)
542{ /*lint --e{715}*/
543 SCIP_PROPDATA* propdata;
544
545 /* free propagator data */
546 propdata = SCIPpropGetData(prop);
547 assert(propdata != NULL);
548
549 SCIPfreeBlockMemory(scip, &propdata);
550
551 SCIPpropSetData(prop, NULL);
552
553 return SCIP_OKAY;
554}
555/**! [SnippetPropFreeRedcost] */
556
557/** solving process initialization method of propagator (called when branch and bound process is about to begin) */
558static
559SCIP_DECL_PROPINITSOL(propInitsolRedcost)
560{
561 SCIP_PROPDATA* propdata;
562
563 propdata = SCIPpropGetData(prop);
564 assert(propdata != NULL);
565
566 propdata->usefullimplics = FALSE;
567 propdata->maxredcost = 0.0;
568
569 return SCIP_OKAY;
570}
571
572/** reduced cost propagation method for an LP solution */
573static
574SCIP_DECL_PROPEXEC(propExecRedcost)
575{ /*lint --e{715}*/
576 SCIP_PROPDATA* propdata;
577 SCIP_COL** cols;
578 SCIP_Real requiredredcost;
579 SCIP_Real cutoffbound;
580 SCIP_Real lpobjval;
581 SCIP_Bool propbinvars;
582 SCIP_Bool cutoff;
583 int nchgbds;
584 int ncols;
585 int c;
586
587 *result = SCIP_DIDNOTRUN;
588
589 /* in case we have a zero objective function, we skip the reduced cost propagator */
590 if( SCIPgetNObjVars(scip) == 0 )
591 return SCIP_OKAY;
592
593 /* propagator can only be applied during solving stage */
595 return SCIP_OKAY;
596
597 /* we cannot apply reduced cost fixing, if we want to solve exactly */
598 /**@todo implement reduced cost fixing with interval arithmetics */
600 return SCIP_OKAY;
601
602 /* only call propagator, if the current node has an LP */
604 return SCIP_OKAY;
605
606 /* only call propagator, if an optimal LP solution is at hand */
608 return SCIP_OKAY;
609
610 /* only call propagator, if the current LP is a valid relaxation */
611 if( !SCIPisLPRelax(scip) )
612 return SCIP_OKAY;
613
614 /* we cannot apply reduced cost strengthening, if no simplex basis is available */
615 if( !SCIPisLPSolBasic(scip) )
616 return SCIP_OKAY;
617
618 /* do not run if propagation w.r.t. objective is not allowed */
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 cutoff */
626 if( SCIPisInfinity(scip, cutoffbound) )
627 return SCIP_OKAY;
628
629 /* get LP columns */
630 cols = SCIPgetLPCols(scip);
631 ncols = SCIPgetNLPCols(scip);
632
633 /* do nothing if the LP has no columns (is empty) */
634 if( ncols == 0 )
635 return SCIP_OKAY;
636
637 /* get propagator data */
638 propdata = SCIPpropGetData(prop);
639 assert(propdata != NULL);
640
641 /* do nothing if active pricer are present and force flag is not TRUE */
642 if( !propdata->force && SCIPgetNActivePricers(scip) > 0 )
643 return SCIP_OKAY;
644
645 /* check if all integral variables are fixed and the continuous variables should not be propagated */
646 if( !propdata->continuous && SCIPgetNPseudoBranchCands(scip) == 0 )
647 return SCIP_OKAY;
648
649 /* get LP objective value */
650 lpobjval = SCIPgetLPObjval(scip);
651
652 /* check if binary variables should be propagated */
653 propbinvars = (SCIPgetDepth(scip) == 0) || (cutoffbound - lpobjval < 5 * propdata->maxredcost);
654
655 /* skip the propagator if the problem has only binary variables and those should not be propagated */
656 if( !propbinvars && SCIPgetNVars(scip) == SCIPgetNBinVars(scip) )
657 return SCIP_OKAY;
658
659 *result = SCIP_DIDNOTFIND;
660 cutoff = FALSE;
661 nchgbds = 0;
662
663 /* compute the required reduced cost which are needed for a binary variable to be fixed */
664 requiredredcost = cutoffbound - lpobjval;
665
666 SCIPdebugMsg(scip, "lpobjval <%g>, cutoffbound <%g>, max reduced <%g>, propgate binary %u, use implics %u\n",
667 lpobjval, cutoffbound, propdata->maxredcost, propbinvars, propdata->usefullimplics);
668
669 /* check reduced costs for non-basic columns */
670 for( c = 0; c < ncols && !cutoff; ++c )
671 {
672 SCIP_VAR* var;
673
674 var = SCIPcolGetVar(cols[c]);
675
676 /* skip continuous variables in case the corresponding parameter is set */
677 if( !propdata->continuous && !SCIPvarIsIntegral(var) )
678 continue;
679
680 if( SCIPvarIsBinary(var) )
681 {
682 if( propbinvars )
683 {
684 if( SCIPgetDepth(scip) == 0 )
685 {
686 SCIP_CALL( propagateRootRedcostBinvar(scip, propdata, var, cols[c], cutoffbound, &nchgbds) );
687 }
688 else
689 {
690 SCIP_CALL( propagateRedcostBinvar(scip, propdata, var, cols[c], requiredredcost, &nchgbds, &cutoff) );
691 }
692 }
693 }
694 else
695 {
696 SCIP_CALL( propagateRedcostVar(scip, var, cols[c], lpobjval, cutoffbound, &nchgbds) );
697 }
698 }
699
700 if( cutoff )
701 {
702 *result = SCIP_CUTOFF;
703
704 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": detected cutoff\n",
706 }
707 else if( nchgbds > 0 )
708 {
709 *result = SCIP_REDUCEDDOM;
710
711 SCIPdebugMsg(scip, "node %" SCIP_LONGINT_FORMAT ": %d bound changes (max redcost <%g>)\n",
712 SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) , nchgbds, propdata->maxredcost);
713 }
714
715 return SCIP_OKAY;
716}
717
718/**@} */
719
720/** creates the redcost propagator and includes it in SCIP */
722 SCIP* scip /**< SCIP data structure */
723 )
724{
725 SCIP_PROPDATA* propdata;
726 SCIP_PROP* prop;
727
728 /* create redcost propagator data */
729 SCIP_CALL( SCIPallocBlockMemory(scip, &propdata) );
730
731 /* include propagator */
733 propExecRedcost, propdata) );
734
735 assert(prop != NULL);
736
737 /* set optional callbacks via setter functions */
738 SCIP_CALL( SCIPsetPropCopy(scip, prop, propCopyRedcost) );
739 SCIP_CALL( SCIPsetPropInitsol(scip, prop, propInitsolRedcost) );
740 SCIP_CALL( SCIPsetPropFree(scip, prop, propFreeRedcost) );
741
742 /* add redcost propagator parameters */
744 "propagating/" PROP_NAME "/continuous",
745 "should reduced cost fixing be also applied to continuous variables?",
746 &propdata->continuous, FALSE, DEFAULT_CONTINUOUS, NULL, NULL) );
748 "propagating/" PROP_NAME "/useimplics",
749 "should implications be used to strength the reduced cost for binary variables?",
750 &propdata->useimplics, FALSE, DEFAULT_USEIMPLICS, NULL, NULL) );
752 "propagating/" PROP_NAME "/force",
753 "should the propagator be forced even if active pricer are present?",
754 &propdata->force, TRUE, DEFAULT_FORCE, NULL, NULL) );
755
756 return SCIP_OKAY;
757}
#define NULL
Definition: def.h:267
#define SCIP_INVALID
Definition: def.h:193
#define SCIP_Bool
Definition: def.h:91
#define MAX3(x, y, z)
Definition: def.h:247
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define SCIP_CALL(x)
Definition: def.h:374
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:380
SCIP_Bool SCIPisExactSolve(SCIP *scip)
Definition: scip_general.c:611
int SCIPgetNObjVars(SCIP *scip)
Definition: scip_prob.c:2220
int SCIPgetNVars(SCIP *scip)
Definition: scip_prob.c:1992
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 SCIPincludePropRedcost(SCIP *scip)
Definition: prop_redcost.c:721
int SCIPgetNPseudoBranchCands(SCIP *scip)
Definition: scip_branch.c:758
SCIP_Real SCIPgetColRedcost(SCIP *scip, SCIP_COL *col)
Definition: scip_lp.c:1154
SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
Definition: lp.c:17009
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17042
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16963
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16973
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17031
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition: lp.c:17019
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
SCIP_Bool SCIPisLPRelax(SCIP *scip)
Definition: scip_lp.c:225
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:168
SCIP_COL ** SCIPgetLPCols(SCIP *scip)
Definition: scip_lp.c:506
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:247
int SCIPgetNLPCols(SCIP *scip)
Definition: scip_lp.c:527
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip_lp.c:667
SCIP_Bool SCIPisLPDualReliable(SCIP *scip)
Definition: scip_lp.c:207
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7493
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
void SCIPpropSetData(SCIP_PROP *prop, SCIP_PROPDATA *propdata)
Definition: prop.c:799
SCIP_RETCODE SCIPsetPropInitsol(SCIP *scip, SCIP_PROP *prop, SCIP_DECL_PROPINITSOL((*propinitsol)))
Definition: scip_prop.c:215
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 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 SCIPisDualfeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisDualfeasPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:670
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip_tree.c:91
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17599
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4676
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18144
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13715
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4766
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip_var.c:4645
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip_var.c:4613
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17610
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18134
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:1864
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13782
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13816
SCIP_Real SCIPgetVarImplRedcost(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing)
Definition: scip_var.c:1909
SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
Definition: scip_var.c:8656
#define PROP_DESC
Definition: prop_redcost.c:67
#define PROP_NAME
Definition: prop_redcost.c:66
static SCIP_DECL_PROPFREE(propFreeRedcost)
Definition: prop_redcost.c:541
static SCIP_DECL_PROPEXEC(propExecRedcost)
Definition: prop_redcost.c:574
#define PROP_DELAY
Definition: prop_redcost.c:71
#define DEFAULT_CONTINUOUS
Definition: prop_redcost.c:81
#define PROP_TIMING
Definition: prop_redcost.c:68
#define DEFAULT_USEIMPLICS
Definition: prop_redcost.c:82
static SCIP_DECL_PROPCOPY(propCopyRedcost)
Definition: prop_redcost.c:526
static SCIP_DECL_PROPINITSOL(propInitsolRedcost)
Definition: prop_redcost.c:559
static SCIP_RETCODE propagateRedcostBinvar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_COL *col, SCIP_Real requiredredcost, int *nchgbds, SCIP_Bool *cutoff)
Definition: prop_redcost.c:241
static SCIP_RETCODE propagateRedcostVar(SCIP *scip, SCIP_VAR *var, SCIP_COL *col, SCIP_Real lpobjval, SCIP_Real cutoffbound, int *nchgbds)
Definition: prop_redcost.c:375
#define PROP_FREQ
Definition: prop_redcost.c:70
#define DEFAULT_FORCE
Definition: prop_redcost.c:83
#define PROP_PRIORITY
Definition: prop_redcost.c:69
static SCIP_RETCODE propagateRootRedcostBinvar(SCIP *scip, SCIP_PROPDATA *propdata, SCIP_VAR *var, SCIP_COL *col, SCIP_Real cutoffbound, int *nchgbds)
Definition: prop_redcost.c:117
propagator using the LP reduced cost and the cutoff bound
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
public methods for propagators
public methods for branch and bound tree
public methods for problem variables
public methods for branching rule plugins and branching
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 propagator plugins
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
type definitions for specific LP solvers interface
@ SCIP_BASESTAT_BASIC
Definition: type_lpi.h:92
@ SCIP_BASESTAT_UPPER
Definition: type_lpi.h:93
@ SCIP_BASESTAT_LOWER
Definition: type_lpi.h:91
@ SCIP_BASESTAT_ZERO
Definition: type_lpi.h:94
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_INVALIDDATA
Definition: type_retcode.h:52
@ 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