Scippy

SCIP

Solving Constraint Integer Programs

presol_dualcomp.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file presol_dualcomp.c
26 * @ingroup DEFPLUGINS_PRESOL
27 * @brief dual compensation presolver
28 * @author Dieter Weninger
29 *
30 * This presolver looks for variables with
31 * i) objcoef >= 0 and exactly one downlock
32 * ii) objcoef <= 0 and exactly one uplock
33 * and fixes the variable in case i) at the lower bound and in case ii) at the
34 * upper bound if a combination of singleton continuous variables can compensate
35 * the downlock in case i) and the uplock in case ii).
36 */
37
38/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
39
42#include "scip/pub_matrix.h"
43#include "scip/pub_message.h"
44#include "scip/pub_presol.h"
45#include "scip/pub_var.h"
46#include "scip/scip_general.h"
47#include "scip/scip_mem.h"
48#include "scip/scip_message.h"
49#include "scip/scip_nlp.h"
50#include "scip/scip_numerics.h"
51#include "scip/scip_param.h"
52#include "scip/scip_presol.h"
53#include "scip/scip_pricer.h"
54#include "scip/scip_prob.h"
55#include "scip/scip_probing.h"
56#include "scip/scip_var.h"
57#include <string.h>
58
59#define PRESOL_NAME "dualcomp"
60#define PRESOL_DESC "compensate single up-/downlocks by singleton continuous variables"
61
62/* we need singleton continuous variables for the lock compensation,
63 * thus it is presumably a good idea to call this presolver before stuffing, which
64 * fixes singleton continuous variables
65 */
66#define PRESOL_PRIORITY -50 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
67#define PRESOL_MAXROUNDS -1 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
68#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
69
70#define DEFAULT_COMP_ONLY_DIS_VARS FALSE /**< should only discrete variables be compensated? */
71
72/*
73 * Data structures
74 */
75
76/** control parameters */
77struct SCIP_PresolData
78{
79 SCIP_Bool componlydisvars; /**< flag indicating if only discrete variables should be compensated */
80};
81
82/** type of fixing direction */
84{
85 FIXATLB = -1, /**< fix variable at lower bound */
86 NOFIX = 0, /**< do not fix variable */
87 FIXATUB = 1 /**< fix variable at upper bound */
88};
90
91/** type of variable lock compensation */
93{
96};
98
99/*
100 * Local methods
101 */
102
103/** try to compensate a variable with a single opposite lock
104 by using singleton continuous variables */
105static
107 SCIP* scip, /**< SCIP main data structure */
108 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
109 int col, /**< variable fixing candidate */
110 int row, /**< row index with opposite lock */
111 SCIP_Real val, /**< value of fixing candidate in the opposite lock constraint */
112 SCIP_Bool twosides, /**< flag indicating that two sides are present */
113 LOCKCOMPENSATION compensation, /**< type of lock compensation */
114 FIXINGDIRECTION* varstofix, /**< array holding fixing information */
115 int* nfixings /**< number of possible fixings */
116 )
117{
118 SCIP_Real* valpnt;
119 int* rowpnt;
120 int* rowend;
121 SCIP_VAR* var;
122 int colidx;
123 SCIP_Real coef;
124 SCIP_Real lhs;
125 SCIP_Real delta;
126 SCIP_Bool trytofix;
127 SCIP_Real lb;
128 SCIP_Real ub;
129 SCIP_Bool deltaisinf;
130 SCIP_Real ratio;
131 SCIP_Bool multrowbyminusone;
132 SCIP_Bool singleton;
133 SCIP_Real offset;
134
135 assert(scip != NULL);
136 assert(matrix != NULL);
137 assert(0 <= col && col < SCIPmatrixGetNColumns(matrix));
138 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
139 assert(compensation == COMPENSATE_DOWNLOCK || compensation == COMPENSATE_UPLOCK);
140 assert(varstofix != NULL);
141 assert(nfixings != NULL);
142
143 /* the variable for compensation should not be a compensation variable itself */
144 assert(SCIPmatrixGetColNNonzs(matrix, col) != 1 || SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, col)));
145
146 /* try lock compensation only if minimum one singleton continuous variable is present */
147 singleton = FALSE;
148 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
149 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
150 for( ; rowpnt < rowend; rowpnt++ )
151 {
152 var = SCIPmatrixGetVar(matrix, *rowpnt);
153
154 if( SCIPmatrixGetColNNonzs(matrix, *rowpnt) == 1 && !SCIPvarIsIntegral(var)
157 {
158 /* minimal one valid compensation variable is present in this row */
159 singleton = TRUE;
160 break;
161 }
162 }
163
164 /* return if no compensation variable is available */
165 if( !singleton )
166 return SCIP_OKAY;
167
168 /* we perform the following transformations afterwards:
169 *
170 * lhs <= a1 x1 + a2 x2 + ... an xn <= rhs
171 * with a1, a2, ..., an >= 0.
172 *
173 * for the downlock case we multiply the constraint in thought by (-1)
174 * if the corresponding coefficient is negative.
175 *
176 * we attribute the uplock case to the downlock case by multiplying
177 * in thought the corresponding column by (-1).
178 */
179 multrowbyminusone = FALSE;
180 if( compensation == COMPENSATE_DOWNLOCK )
181 {
182 if( SCIPisLT(scip,val,0.0) )
183 multrowbyminusone = TRUE;
184 }
185 else
186 {
187 assert(compensation == COMPENSATE_UPLOCK);
188
189 /* in the uplock case we multiply the column in thought by (-1) and
190 * thus we need to multiply the constraint by (-1) to get a positive coefficient
191 */
192 if( SCIPisGT(scip,val,0.0) )
193 multrowbyminusone = TRUE;
194 }
195
196 /* we need the objective coefficient and constraint coefficient ratio
197 * to later preserve optimality.
198 * further we need to consider multiplications of the constraint by (-1).
199 * for ranged rows and equalities we switch to the rhs.
200 */
201 lhs = SCIPmatrixGetRowLhs(matrix, row);
202 ratio = SCIPvarGetObj( SCIPmatrixGetVar(matrix,col) ) / val;
203 if( multrowbyminusone )
204 {
205 if( twosides )
206 lhs = -SCIPmatrixGetRowRhs(matrix, row);
207 else
208 lhs = -lhs;
209
210 ratio = -ratio;
211 }
212
213 offset = 0.0;
214 trytofix = TRUE;
215 delta = 0;
216 deltaisinf = FALSE;
217
218 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
219 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
220 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
221
222 for( ; rowpnt < rowend; rowpnt++, valpnt++ )
223 {
224 colidx = *rowpnt;
225 coef = *valpnt;
226 var = SCIPmatrixGetVar(matrix, colidx);
227 lb = SCIPvarGetLbGlobal(var);
228 ub = SCIPvarGetUbGlobal(var);
229
230 if( colidx == col )
231 {
232 /* this is the variable which we want to compensate */
233
234 if( compensation == COMPENSATE_DOWNLOCK )
235 {
236 if( SCIPisInfinity(scip, -lb) )
237 {
238 trytofix = FALSE;
239 break;
240 }
241 else
242 {
243 if( multrowbyminusone )
244 offset += (-coef) * lb;
245 else
246 offset += coef * lb;
247 }
248 }
249 else
250 {
251 if( SCIPisInfinity(scip, ub) )
252 {
253 trytofix = FALSE;
254 break;
255 }
256 else
257 {
258 /* for the uplock case we have opposed sign for the coefficient as
259 * in the downlock case.
260 * the multiplication of the column results in swapping the negative bounds.
261 */
262 if( multrowbyminusone )
263 offset += coef * (-ub);
264 else
265 offset += (-coef) * (-ub);
266 }
267 }
268 }
269 else if( SCIPmatrixGetColNNonzs(matrix, colidx) == 1 && !SCIPvarIsIntegral(var)
272 {
273 /* this is singleton continuous variable and
274 * thus a valid compensation candidate
275 */
276
277 if( SCIPisLT(scip,coef,0.0) )
278 {
279 /* coef < 0 */
280
281 if( multrowbyminusone )
282 {
283 if( SCIPisInfinity(scip, -lb) )
284 {
285 trytofix = FALSE;
286 break;
287 }
288
289 /* we have a negative coefficient and the row is multiplied by (-1)
290 * thus actually we have a positive coefficient
291 */
292 offset += (-coef) * lb;
293
294 /* only consider singleton continuous variables with a better or the same
295 * obj/coef ratio for preserving optimality
296 */
297 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/(-coef), ratio) )
298 {
299 if( SCIPisInfinity(scip, ub) )
300 {
301 deltaisinf = TRUE;
302 break;
303 }
304
305 /* calculate the contribution to the compensation value */
306 delta += (-coef) * (ub - lb);
307 }
308 }
309 else
310 {
311 if( SCIPisInfinity(scip, ub) )
312 {
313 trytofix = FALSE;
314 break;
315 }
316
317 /* we have a negative coefficient and hence need to multiply the column by (-1).
318 * this means the bounds swap and change the sign
319 */
320 offset += (-coef) * (-ub);
321
322 /* only consider singleton continuous variables with a better or the same
323 * obj/coef ratio for preserving optimality
324 */
325 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/coef, ratio) )
326 {
327 if( SCIPisInfinity(scip, -lb) )
328 {
329 deltaisinf = TRUE;
330 break;
331 }
332
333 /* calculate the contribution to the compensation value */
334 delta += (-coef) * (ub - lb);
335 }
336 }
337 }
338 else
339 {
340 /* coef >= 0 */
341
342 if( multrowbyminusone )
343 {
344 /* we have a positive or zero coefficient and the row is multiplied by (-1) */
345 if( SCIPisInfinity(scip, ub) )
346 {
347 trytofix = FALSE;
348 break;
349 }
350
351 /* we have a positive or zero coefficient and multiply in thought the constraint
352 * by (-1) thus we have actually a negative coefficient and multiply the column by (-1).
353 * therefore the sign of the coefficient does not change but the bounds swap and change
354 * the sign.
355 */
356 offset += coef * (-ub);
357
358 /* we have a positive or zero coefficient and multiply in thought the constraint
359 * by (-1) which delivers the ratio.
360 * a further multiplication of the column does not change anything.
361 */
362 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/(-coef), ratio) )
363 {
364 if( SCIPisInfinity(scip, -lb) )
365 {
366 deltaisinf = TRUE;
367 break;
368 }
369
370 /* calculate the contribution to the compensation value */
371 delta += coef * (ub - lb);
372 }
373 }
374 else
375 {
376 if( SCIPisInfinity(scip, -lb) )
377 {
378 trytofix = FALSE;
379 break;
380 }
381
382 /* we have positive coefficient and do not need to multiply anything by (-1) */
383 offset += coef * lb;
384
385 if( SCIPisLE(scip,SCIPvarGetObj(SCIPmatrixGetVar(matrix, colidx))/coef, ratio) )
386 {
387 if( SCIPisInfinity(scip, ub) )
388 {
389 deltaisinf = TRUE;
390 break;
391 }
392
393 /* calculate the contribution to the compensation value */
394 delta += coef * (ub - lb);
395 }
396 }
397 }
398 }
399 else
400 {
401 /* remaining variables */
402
403 /* the reasons for the following signs are the same as for the singleton
404 * continuous variables
405 */
406 if( SCIPisLT(scip,coef,0.0) )
407 {
408 if( multrowbyminusone )
409 {
410 if( SCIPisInfinity(scip, -lb) )
411 {
412 trytofix = FALSE;
413 break;
414 }
415
416 offset += (-coef) * lb;
417 }
418 else
419 {
420 if( SCIPisInfinity(scip, ub) )
421 {
422 trytofix = FALSE;
423 break;
424 }
425
426 offset += (-coef) * (-ub);
427 }
428 }
429 else
430 {
431 if( multrowbyminusone )
432 {
433 if( SCIPisInfinity(scip, ub) )
434 {
435 trytofix = FALSE;
436 break;
437 }
438
439 offset += coef * (-ub);
440 }
441 else
442 {
443 if( SCIPisInfinity(scip, -lb) )
444 {
445 trytofix = FALSE;
446 break;
447 }
448
449 offset += coef * lb;
450 }
451 }
452 }
453 }
454
455 /* avoid fixings to infinite values or fixings of already fixed variables */
456 if( trytofix && varstofix[col] == NOFIX)
457 {
458 /* feasibility is secured if the compensation value delta
459 * is large enough to compensate the value lhs-offset
460 */
461 if( deltaisinf || SCIPisLE(scip, lhs-offset, delta) )
462 {
463 if( compensation == COMPENSATE_UPLOCK )
464 {
466 {
467 varstofix[col] = FIXATUB;
468 (*nfixings)++;
469
470#ifdef SCIP_MORE_DEBUG
471 SCIPmatrixPrintRow(scip, matrix, row);
472 SCIPdebugMsg(scip, "%s, bds=[%.2f,%.2f], obj=%.2f, nnonzs=%d, type=%s, fix=ub, %.1f <= %.1f\n",
475 SCIPmatrixGetColNNonzs(matrix, col),
476 SCIPvarGetType(SCIPmatrixGetVar(matrix, col))==SCIP_VARTYPE_CONTINUOUS ? "con" : "dis",
477 lhs-offset, delta);
478#endif
479 }
480 }
481 else
482 {
484 {
485 varstofix[col] = FIXATLB;
486 (*nfixings)++;
487
488#ifdef SCIP_MORE_DEBUG
489 SCIPmatrixPrintRow(scip, matrix, row);
490 SCIPdebugMsg(scip, "%s, bds=[%.2f,%.2f], obj=%.2f, nnonzs=%d, type=%s, fix=lb, %.1f <= %.1f\n",
493 SCIPmatrixGetColNNonzs(matrix, col),
494 SCIPvarGetType(SCIPmatrixGetVar(matrix, col))==SCIP_VARTYPE_CONTINUOUS ? "con" : "dis",
495 lhs-offset, delta);
496#endif
497 }
498 }
499 }
500 }
501
502 return SCIP_OKAY;
503}
504
505/*
506 * Callback methods of presolver
507 */
508
509/** copy method for constraint handler plugins (called when SCIP copies plugins) */
510static
511SCIP_DECL_PRESOLCOPY(presolCopyDualcomp)
512{ /*lint --e{715}*/
513 assert(scip != NULL);
514 assert(presol != NULL);
515 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
516
517 /* call inclusion method of presolver */
519
520 return SCIP_OKAY;
521}
522
523/** execution method of presolver */
524static
525SCIP_DECL_PRESOLEXEC(presolExecDualcomp)
526{ /*lint --e{715}*/
527 SCIP_PRESOLDATA* presoldata;
528 SCIP_MATRIX* matrix;
529 SCIP_Bool initialized;
530 SCIP_Bool complete;
531 SCIP_Bool infeasible;
532
533 assert(result != NULL);
534 *result = SCIP_DIDNOTRUN;
535
537 return SCIP_OKAY;
538
540 return SCIP_OKAY;
541
542 /* don't run if no compensation variables are present */
543 if( SCIPgetNContVars(scip) == 0 )
544 return SCIP_OKAY;
545
547 return SCIP_OKAY;
548
549 *result = SCIP_DIDNOTFIND;
550
551 presoldata = SCIPpresolGetData(presol);
552 assert(presoldata != NULL);
553
554 matrix = NULL;
555
556 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
557 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
558
559 /* if infeasibility was detected during matrix creation, return here */
560 if( infeasible )
561 {
562 if( initialized )
563 SCIPmatrixFree(scip, &matrix);
564
565 *result = SCIP_CUTOFF;
566 return SCIP_OKAY;
567 }
568
569 /* we only work on pure MIPs currently */
570 if( initialized && complete )
571 {
572 int ncols;
573 int i;
574 SCIP_Real* valpnt;
575 int* colpnt;
576 int* colend;
577 int row;
578 SCIP_VAR* var;
579 SCIP_Bool inspect;
580 SCIP_Real val;
581 FIXINGDIRECTION* varstofix;
582 int nfixings;
583 SCIP_Real lhs;
584 SCIP_Real rhs;
585 SCIP_Bool twosides;
586
587 ncols = SCIPmatrixGetNColumns(matrix);
588 nfixings = 0;
589
590 SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
591 BMSclearMemoryArray(varstofix, ncols);
592
593 for(i = 0; i < ncols; i++)
594 {
595 var = SCIPmatrixGetVar(matrix, i);
596
597 /* exclude compensation variables itself for compensation */
598 if( !SCIPvarIsIntegral(var) && SCIPmatrixGetColNNonzs(matrix, i) == 1 )
599 continue;
600
601 /* if requested exclude continuous variables for compensation */
602 if( presoldata->componlydisvars && !SCIPvarIsIntegral(var) )
603 continue;
604
605 /* verifiy that this variable has one uplock and that the uplocks are consistent */
607 SCIPmatrixGetColNUplocks(matrix, i) == 1 &&
608 SCIPisLE(scip, SCIPvarGetObj(var), 0.0) )
609 {
610 row = -1;
611 val = 0.0;
612 inspect = FALSE;
613 twosides = FALSE;
614 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
615 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
616 valpnt = SCIPmatrixGetColValPtr(matrix, i);
617
618 /* search row which causes the uplock */
619 for( ; (colpnt < colend); colpnt++, valpnt++ )
620 {
621 row = *colpnt;
622 val = *valpnt;
623 lhs = SCIPmatrixGetRowLhs(matrix, row);
624 rhs = SCIPmatrixGetRowRhs(matrix, row);
625
626 if( SCIPisEQ(scip, lhs, rhs) )
627 {
628 /* equation */
629 inspect = TRUE;
630 twosides = TRUE;
631 break;
632 }
633 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
634 {
635 /* >= */
636 if( SCIPisLT(scip, val, 0.0) )
637 {
638 inspect = TRUE;
639 break;
640 }
641 }
642 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
643 {
644 /* ranged row */
645 inspect = TRUE;
646 twosides = TRUE;
647 break;
648 }
649 }
650
651 assert(inspect);
652
653 if( inspect ) /*lint !e774*/
654 {
655 assert(row >= 0);
656 assert(!SCIPisZero(scip, val));
657
658 /* try to fix variable i at the upper bound */
659 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
660 twosides, COMPENSATE_UPLOCK, varstofix, &nfixings) );
661 }
662 }
663 /* verifiy that this variable has one downlock and that the downlocks are consistent */
664 else if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1 &&
665 SCIPmatrixGetColNDownlocks(matrix, i) == 1 &&
666 SCIPisGE(scip, SCIPvarGetObj(var), 0.0) )
667 {
668 row = -1;
669 val = 0.0;
670 inspect = FALSE;
671 twosides = FALSE;
672 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
673 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
674 valpnt = SCIPmatrixGetColValPtr(matrix, i);
675
676 /* search row which causes the downlock */
677 for( ; (colpnt < colend); colpnt++, valpnt++ )
678 {
679 row = *colpnt;
680 val = *valpnt;
681 lhs = SCIPmatrixGetRowLhs(matrix, row);
682 rhs = SCIPmatrixGetRowRhs(matrix, row);
683
684 if( SCIPisEQ(scip, lhs, rhs) )
685 {
686 /* equation */
687 inspect = TRUE;
688 twosides = TRUE;
689 break;
690 }
691 else if( SCIPmatrixIsRowRhsInfinity(matrix, row) )
692 {
693 /* >= */
694 if( SCIPisGT(scip, val, 0.0) )
695 {
696 inspect = TRUE;
697 break;
698 }
699 }
700 else if( !SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs) )
701 {
702 /* ranged row */
703 inspect = TRUE;
704 twosides = TRUE;
705 break;
706 }
707 }
708
709 assert(inspect);
710
711 if( inspect ) /*lint !e774*/
712 {
713 assert(row >= 0);
714 assert(!SCIPisZero(scip, val));
715
716 /* try to fix variable i at the lower bound */
717 SCIP_CALL( compensateVarLock(scip, matrix, i, row, val,
718 twosides, COMPENSATE_DOWNLOCK, varstofix, &nfixings) );
719 }
720 }
721 }
722
723 if( nfixings > 0 )
724 {
725 int v;
726 int oldnfixedvars;
727 int numupperboundfixings;
728 int numlowerboundfixings;
729 int numcontinuousfixings;
730 int numdiscretefixings;
731
732 oldnfixedvars = *nfixedvars;
733 numupperboundfixings = 0;
734 numlowerboundfixings = 0;
735 numcontinuousfixings = 0;
736 numdiscretefixings = 0;
737
738 /* look for fixable variables */
739 for( v = ncols - 1; v >= 0; --v )
740 {
741 SCIP_Bool fixed;
742
743 var = SCIPmatrixGetVar(matrix, v);
744
745 if( varstofix[v] == FIXATLB )
746 {
747 SCIP_Real lb;
748
749 lb = SCIPvarGetLbGlobal(var);
750
751 /* avoid fixings to infinite values */
752 assert(!SCIPisInfinity(scip, -lb));
753
754 SCIPdebugMsg(scip, "Fix variable %s at lower bound %.15g\n", SCIPvarGetName(var), lb);
755
756 /* fix at lower bound */
757 SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
758 if( infeasible )
759 {
760 SCIPdebugMsg(scip, " -> infeasible fixing\n");
761 *result = SCIP_CUTOFF;
762
763 break;
764 }
765 assert(fixed);
766 (*nfixedvars)++;
767 numlowerboundfixings++;
768
769 if( !SCIPvarIsIntegral(var) )
770 numcontinuousfixings++;
771 else
772 numdiscretefixings++;
773 }
774 else if( varstofix[v] == FIXATUB )
775 {
776 SCIP_Real ub;
777
778 ub = SCIPvarGetUbGlobal(var);
779
780 /* avoid fixings to infinite values */
781 assert(!SCIPisInfinity(scip, ub));
782
783 SCIPdebugMsg(scip, "Fix variable %s at upper bound %.15g\n", SCIPvarGetName(var), ub);
784
785 /* fix at upper bound */
786 SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
787 if( infeasible )
788 {
789 SCIPdebugMsg(scip, " -> infeasible fixing\n");
790 *result = SCIP_CUTOFF;
791
792 break;
793 }
794 assert(fixed);
795 (*nfixedvars)++;
796 numupperboundfixings++;
797
798 if( !SCIPvarIsIntegral(var) )
799 numcontinuousfixings++;
800 else
801 numdiscretefixings++;
802 }
803 }
804
805 if( *result != SCIP_CUTOFF && *nfixedvars > oldnfixedvars )
806 *result = SCIP_SUCCESS;
807
808 SCIPdebugMsg(scip, "### lbfixes: %d, ubfixes: %d, con: %d, dis: %d\n",
809 numlowerboundfixings, numupperboundfixings,
810 numcontinuousfixings, numdiscretefixings);
811 }
812
813 SCIPfreeBufferArray(scip, &varstofix);
814 }
815
816 SCIPmatrixFree(scip, &matrix);
817
818 return SCIP_OKAY;
819}
820
821/*
822 * presolver specific interface methods
823 */
824
825/** destructor of presolver to free user data (called when SCIP is exiting) */
826static
827SCIP_DECL_PRESOLFREE(presolFreeDualcomp)
828{ /*lint --e{715}*/
829 SCIP_PRESOLDATA* presoldata;
830
831 /* free presolver data */
832 presoldata = SCIPpresolGetData(presol);
833 assert(presoldata != NULL);
834
835 SCIPfreeBlockMemory(scip, &presoldata);
836 SCIPpresolSetData(presol, NULL);
837
838 return SCIP_OKAY;
839}
840
841/** creates the dualcomp presolver and includes it in SCIP */
843 SCIP* scip /**< SCIP data structure */
844 )
845{
846 SCIP_PRESOLDATA* presoldata;
847 SCIP_PRESOL* presol;
848
849 /* create dualcomp presolver data */
850 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
851
852 /* include presolver */
854 PRESOL_TIMING, presolExecDualcomp, presoldata) );
855 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualcomp) );
856 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualcomp) );
857
859 "presolving/dualcomp/componlydisvars",
860 "should only discrete variables be compensated?",
861 &presoldata->componlydisvars, FALSE, DEFAULT_COMP_ONLY_DIS_VARS, NULL, NULL) );
862
863 return SCIP_OKAY;
864}
#define NULL
Definition: def.h:248
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:444
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2569
#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 SCIPincludePresolDualcomp(SCIP *scip)
#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
SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
Definition: scip_nlp.c:74
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition: presol.c:538
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition: presol.c:528
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLFREE((*presolfree)))
Definition: scip_presol.c:164
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
Definition: scip_presol.c:148
SCIP_RETCODE SCIPincludePresolBasic(SCIP *scip, SCIP_PRESOL **presolptr, const char *name, const char *desc, int priority, int maxrounds, SCIP_PRESOLTIMING timing, SCIP_DECL_PRESOLEXEC((*presolexec)), SCIP_PRESOLDATA *presoldata)
Definition: scip_presol.c:113
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition: presol.c:625
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:98
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4386
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:23490
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip_var.c:10318
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:4328
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition: scip_var.c:10984
int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1873
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2013
int SCIPmatrixGetColNDownlocks(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1941
int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1885
SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2095
int SCIPmatrixGetColNUplocks(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1929
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2047
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1977
SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2059
SCIP_Real * SCIPmatrixGetColValPtr(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1861
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
Definition: matrix.c:703
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition: matrix.c:1897
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition: matrix.c:1348
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1953
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2001
void SCIPmatrixPrintRow(SCIP *scip, SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1425
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition: matrix.c:2037
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
Fixingdirection
enum Fixingdirection FIXINGDIRECTION
#define DEFAULT_COMP_ONLY_DIS_VARS
enum Lockcompensation LOCKCOMPENSATION
Lockcompensation
@ COMPENSATE_UPLOCK
@ COMPENSATE_DOWNLOCK
#define PRESOL_NAME
@ FIXATUB
@ FIXATLB
@ NOFIX
enum Fixingdirection FIXINGDIRECTION
static SCIP_DECL_PRESOLEXEC(presolExecDualcomp)
#define PRESOL_PRIORITY
static SCIP_DECL_PRESOLCOPY(presolCopyDualcomp)
static SCIP_DECL_PRESOLFREE(presolFreeDualcomp)
#define PRESOL_MAXROUNDS
#define PRESOL_TIMING
static SCIP_RETCODE compensateVarLock(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Bool twosides, LOCKCOMPENSATION compensation, FIXINGDIRECTION *varstofix, int *nfixings)
#define PRESOL_DESC
dual compensation presolver
public methods for matrix
public methods for message output
public methods for presolvers
public methods for problem variables
general public methods
public methods for memory management
public methods for message handling
public methods for nonlinear relaxation
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for presolving plugins
public methods for variable pricer plugins
public methods for global and local (sub)problems
public methods for the probing mode
public methods for SCIP variables
struct SCIP_PresolData SCIP_PRESOLDATA
Definition: type_presol.h:51
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_CUTOFF
Definition: type_result.h:48
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_SUCCESS
Definition: type_result.h:58
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STAGE_PRESOLVING
Definition: type_set.h:49
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141