Scippy

SCIP

Solving Constraint Integer Programs

presol_redvub.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_redvub.c
26 * @ingroup DEFPLUGINS_PRESOL
27 * @brief remove redundant variable upper bound constraints
28 * @author Dieter Weninger
29 *
30 * This presolver looks for dominating variable bound constraints
31 * on the same continuous variable and discards them. For example let x be a
32 * continuous variable and y, y' are binary variables. In addition, let two variable
33 * upper bound constraints ax - by <= e and cx - dy' <= f are given. If
34 * ax - by <= e implies cx - dy' <= f, then we can remove the second constraint
35 * and substitute/aggregate y' := y. The same can be done with variable lower
36 * bound constraints.
37 *
38 */
39
40/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
41
43#include "scip/presol_redvub.h"
44#include "scip/pub_matrix.h"
45#include "scip/pub_message.h"
46#include "scip/pub_presol.h"
47#include "scip/pub_var.h"
48#include "scip/scip_cons.h"
49#include "scip/scip_general.h"
50#include "scip/scip_mem.h"
51#include "scip/scip_message.h"
52#include "scip/scip_nlp.h"
53#include "scip/scip_numerics.h"
54#include "scip/scip_presol.h"
55#include "scip/scip_pricer.h"
56#include "scip/scip_prob.h"
57#include "scip/scip_probing.h"
58#include "scip/scip_var.h"
59
60#define PRESOL_NAME "redvub"
61#define PRESOL_DESC "detect redundant variable bound constraints"
62#define PRESOL_PRIORITY -9000000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
63#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
64#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
65
66#define MAXPAIRCOMP 1000 /**< maximal number of pairwise comparisons */
67
68/*
69 * Local methods
70 */
71
72/** verify if the constraint is a variable upper bound constraint */
73static
75 SCIP* scip, /**< SCIP main data structure */
76 SCIP_MATRIX* matrix, /**< matrix instance */
77 int row, /**< row index */
78 SCIP_Real* lowthreshold, /**< low switching threshold */
79 SCIP_Real* highthreshold, /**< high switching threshold */
80 int* conidx, /**< variable index of continuous variable */
81 int* binidx /**< variable index of binary variable */
82 )
83{
84 SCIP_Real* valpnt;
85 int* rowpnt;
86 SCIP_Bool isvub;
87
88 assert(scip != NULL);
89 assert(matrix != NULL);
90 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
91 assert(lowthreshold != NULL);
92 assert(highthreshold != NULL);
93 assert(conidx != NULL);
94 assert(binidx != NULL);
95
96 isvub = FALSE;
97
98 if( SCIPmatrixGetRowNNonzs(matrix, row) == 2 && SCIPmatrixIsRowRhsInfinity(matrix, row) )
99 {
100 SCIP_VARTYPE type1;
101 SCIP_VARTYPE type2;
102 int idx1;
103 int idx2;
104 SCIP_VAR* var1;
105 SCIP_VAR* var2;
106 SCIP_Real val1;
107 SCIP_Real val2;
108
109 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
110 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
111
112 idx1 = *rowpnt;
113 val1 = *valpnt;
114 var1 = SCIPmatrixGetVar(matrix, idx1);
115 type1 = SCIPvarGetType(var1);
116
117 rowpnt++;
118 valpnt++;
119
120 idx2 = *rowpnt;
121 val2 = *valpnt;
122 var2 = SCIPmatrixGetVar(matrix, idx2);
123 type2 = SCIPvarGetType(var2);
124
126 return isvub;
127
128 /* we claim that the vub has the structure ax + cy >= b
129 * with a<0, c>0, x continuous, x>=0, y binary and obj(y)>=0
130 */
131 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
132 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
133 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
134 {
135 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
136 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
137 *conidx = idx1;
138 *binidx = idx2;
139 isvub = TRUE;
140 }
141 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
142 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
143 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
144 {
145 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
146 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
147 *conidx = idx2;
148 *binidx = idx1;
149 isvub = TRUE;
150 }
151 }
152
153 return isvub;
154}
155
156/** verify if the constraint is a variable lower bound constraint */
157static
159 SCIP* scip, /**< SCIP main data structure */
160 SCIP_MATRIX* matrix, /**< matrix instance */
161 int row, /**< row index */
162 SCIP_Real* lowthreshold, /**< low switching threshold */
163 SCIP_Real* highthreshold, /**< high switching threshold */
164 int* conidx, /**< variable index of continuous variable */
165 int* binidx /**< variable index of binary variable */
166 )
167{
168 SCIP_Real* valpnt;
169 int* rowpnt;
170 SCIP_Bool isvlb;
171
172 assert(scip != NULL);
173 assert(matrix != NULL);
174 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
175 assert(lowthreshold != NULL);
176 assert(highthreshold != NULL);
177 assert(conidx != NULL);
178 assert(binidx != NULL);
179
180 isvlb = FALSE;
181
182 if( SCIPmatrixGetRowNNonzs(matrix, row) == 2 && SCIPmatrixIsRowRhsInfinity(matrix, row) )
183 {
184 SCIP_VARTYPE type1;
185 SCIP_VARTYPE type2;
186 int idx1;
187 int idx2;
188 SCIP_VAR* var1;
189 SCIP_VAR* var2;
190 SCIP_Real val1;
191 SCIP_Real val2;
192
193 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
194 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
195
196 idx1 = *rowpnt;
197 val1 = *valpnt;
198 var1 = SCIPmatrixGetVar(matrix, idx1);
199 type1 = SCIPvarGetType(var1);
200
201 rowpnt++;
202 valpnt++;
203
204 idx2 = *rowpnt;
205 val2 = *valpnt;
206 var2 = SCIPmatrixGetVar(matrix, idx2);
207 type2 = SCIPvarGetType(var2);
208
210 return isvlb;
211
212 /* we claim that the vlb has the structure ax + cy >= b
213 * with a>0, c<0, x continuous, x>=0, y binary and obj(y)>=0
214 */
215 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
216 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
217 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
218 {
219 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
220 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
221 *conidx = idx1;
222 *binidx = idx2;
223 isvlb = TRUE;
224 }
225 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
226 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
227 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
228 {
229 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
230 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
231 *conidx = idx2;
232 *binidx = idx1;
233 isvlb = TRUE;
234 }
235 }
236
237 return isvlb;
238}
239
240
241/** searches for variable upper bound constraints on the same continuous variable with a dominance relation */
242static
244 SCIP* scip, /**< SCIP main data structure */
245 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
246 int nvubs, /**< number of vubs */
247 int* vubs, /**< row indices of the vubs */
248 SCIP_Real* lowthresholds, /**< low switching thresholds */
249 SCIP_Real* highthresholds, /**< high switching thresholds */
250 int* conidxs, /**< variable indexes of continuous variable */
251 int* binidxs, /**< variable indexes of binary variable */
252 int* nvaragg, /**< number of variables for aggregation */
253 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
254 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
255 int* ndeletecons, /**< number of deleteable constraints */
256 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
257 )
258{
259 int i;
260 int j;
261 SCIP_Bool uselinearscan;
262
263 assert(scip != NULL);
264 assert(matrix != NULL);
265 assert(vubs != NULL);
266 assert(nvubs >= 2);
267 assert(lowthresholds != NULL);
268 assert(highthresholds != NULL);
269 assert(conidxs != NULL);
270 assert(binidxs != NULL);
271 assert(nvaragg != NULL);
272 assert(isvartoagg != NULL);
273 assert(aggvars != NULL);
274 assert(ndeletecons != NULL);
275 assert(deletecons != NULL);
276
277 /* use pairwise comparison only for a small number of vub constraints */
278 if( nvubs >= MAXPAIRCOMP )
279 uselinearscan = TRUE;
280 else
281 uselinearscan = FALSE;
282
283 for( i = 0; i < nvubs; i++ )
284 {
285 for( j = i+1; j < nvubs; j++ )
286 {
287 SCIP_VAR* var1;
288 SCIP_VAR* var2;
289
290 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
291 continue;
292
293 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
294 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
295
296 /* make sure that the binary variables switch synchronously */
297 if((SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 1 &&
298 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 1 &&
299 SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 0 &&
300 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 0) ||
301 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
302 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
303 {
304 if( SCIPisLE(scip, highthresholds[i], highthresholds[j]) )
305 {
306#ifdef SCIP_DEBUG
307 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
308 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
309 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[j]), NULL) );
310 SCIPinfoMessage(scip, NULL, "\n");
311#endif
312
313 isvartoagg[binidxs[j]] = TRUE;
314 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
315 (*nvaragg)++;
316
317 deletecons[vubs[j]] = TRUE;
318 (*ndeletecons)++;
319 }
320 else
321 {
322 assert(SCIPisGT(scip, highthresholds[i], highthresholds[j]));
323#ifdef SCIP_DEBUG
324 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
325 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
326 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[i]), NULL) );
327 SCIPinfoMessage(scip, NULL, "\n");
328#endif
329
330 isvartoagg[binidxs[i]] = TRUE;
331 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
332 (*nvaragg)++;
333
334 deletecons[vubs[i]] = TRUE;
335 (*ndeletecons)++;
336 }
337 }
338
339 if( uselinearscan )
340 break;
341 }
342 }
343
344 return SCIP_OKAY;
345}
346
347/** searches for variable lower bound constraints on the same continuous variable with a dominance relation */
348static
350 SCIP* scip, /**< SCIP main data structure */
351 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
352 int nvlbs, /**< number of vlbs */
353 int* vlbs, /**< row indices of the vlbs */
354 SCIP_Real* lowthresholds, /**< low switching thresholds */
355 SCIP_Real* highthresholds, /**< high switching thresholds */
356 int* conidxs, /**< variable indexes of continuous variable */
357 int* binidxs, /**< variable indexes of binary variable */
358 int* nvaragg, /**< number of variables for aggregation */
359 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
360 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
361 int* ndeletecons, /**< number of deleteable constraints */
362 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
363
364 )
365{
366 int i;
367 int j;
368 SCIP_Bool uselinearscan;
369
370 assert(scip != NULL);
371 assert(matrix != NULL);
372 assert(vlbs != NULL);
373 assert(nvlbs >= 2);
374 assert(lowthresholds != NULL);
375 assert(highthresholds != NULL);
376 assert(conidxs != NULL);
377 assert(binidxs != NULL);
378 assert(nvaragg != NULL);
379 assert(isvartoagg != NULL);
380 assert(aggvars != NULL);
381 assert(ndeletecons != NULL);
382 assert(deletecons != NULL);
383
384 /* use pairwise comparison only for a small number of vlb constraints */
385 if( nvlbs >= MAXPAIRCOMP )
386 uselinearscan = TRUE;
387 else
388 uselinearscan = FALSE;
389
390 for( i = 0; i < nvlbs; i++ )
391 {
392 for( j = i+1; j < nvlbs; j++ )
393 {
394 SCIP_VAR* var1;
395 SCIP_VAR* var2;
396
397 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
398 continue;
399
400 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
401 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
402
403 /* make sure that the binary variables switch synchronously */
404 if((SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 1 &&
405 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 1 &&
406 SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 0 &&
407 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 0) ||
408 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
409 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
410 {
411 if( SCIPisGE(scip, highthresholds[i], highthresholds[j]) )
412 {
413#ifdef SCIP_DEBUG
414 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
415 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
416 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[j]), NULL) );
417 SCIPinfoMessage(scip, NULL, "\n");
418#endif
419
420 isvartoagg[binidxs[j]] = TRUE;
421 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
422 (*nvaragg)++;
423
424 deletecons[vlbs[j]] = TRUE;
425 (*ndeletecons)++;
426 }
427 else
428 {
429 assert(SCIPisLT(scip, highthresholds[i], highthresholds[j]));
430#ifdef SCIP_DEBUG
431 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
432 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
433 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[i]), NULL) );
434 SCIPinfoMessage(scip, NULL, "\n");
435#endif
436
437 isvartoagg[binidxs[i]] = TRUE;
438 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
439 (*nvaragg)++;
440
441 deletecons[vlbs[i]] = TRUE;
442 (*ndeletecons)++;
443 }
444 }
445
446 if( uselinearscan )
447 break;
448 }
449 }
450
451 return SCIP_OKAY;
452}
453
454/** find variable aggregations and redundant variable bound constraints */
455static
457 SCIP* scip, /**< SCIP main data structure */
458 SCIP_MATRIX* matrix, /**< constraint matrix */
459 int* nvaragg, /**< number of redundant variables */
460 SCIP_Bool* isvartoagg, /**< flags indicating which variables could be substituted/aggregated */
461 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
462 int* ndeletecons, /**< number of redundant constraints */
463 SCIP_Bool* deletecons /**< flags indicating which constraints could be deleted */
464 )
465{
466 int c;
467 int* colpnt;
468 int* colend;
469 int* vbcons;
470 int nvbcons;
471 int ncols;
472 int nrows;
473 SCIP_Real* lowthresholds;
474 SCIP_Real* highthresholds;
475 int* conidxs;
476 int* binidxs;
477
478 ncols = SCIPmatrixGetNColumns(matrix);
479 nrows = SCIPmatrixGetNRows(matrix);
480
481 SCIP_CALL( SCIPallocBufferArray(scip, &binidxs, nrows) );
482 SCIP_CALL( SCIPallocBufferArray(scip, &conidxs, nrows) );
483 SCIP_CALL( SCIPallocBufferArray(scip, &lowthresholds, nrows) );
484 SCIP_CALL( SCIPallocBufferArray(scip, &highthresholds, nrows) );
485 SCIP_CALL( SCIPallocBufferArray(scip, &vbcons, nrows) );
486
487 for( c = 0; c < ncols; c++ )
488 {
489 SCIP_VAR* var;
490
491 var = SCIPmatrixGetVar(matrix, c);
492
493 if( SCIPvarIsIntegral(var) )
494 continue;
495
496 /* search vubs per variable */
497 nvbcons = 0;
498 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
499 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
500 for( ; (colpnt < colend); colpnt++ )
501 {
502 SCIP_Real lowthreshold;
503 SCIP_Real highthreshold;
504 int conidx;
505 int binidx;
506
507 if( isVub(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
508 {
509 vbcons[nvbcons] = *colpnt;
510 lowthresholds[nvbcons] = lowthreshold;
511 highthresholds[nvbcons] = highthreshold;
512 conidxs[nvbcons] = conidx;
513 binidxs[nvbcons] = binidx;
514 nvbcons++;
515 }
516 }
517 if( nvbcons >= 2 )
518 {
519 SCIP_CALL( detectDominatingVubs(scip, matrix, nvbcons, vbcons,
520 lowthresholds, highthresholds, conidxs, binidxs,
521 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
522 }
523
524 /* search vlbs per variable */
525 nvbcons = 0;
526 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
527 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
528 for( ; (colpnt < colend); colpnt++ )
529 {
530 SCIP_Real lowthreshold;
531 SCIP_Real highthreshold;
532 int conidx;
533 int binidx;
534
535 if( isVlb(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
536 {
537 vbcons[nvbcons] = *colpnt;
538 lowthresholds[nvbcons] = lowthreshold;
539 highthresholds[nvbcons] = highthreshold;
540 conidxs[nvbcons] = conidx;
541 binidxs[nvbcons] = binidx;
542 nvbcons++;
543 }
544 }
545 if( nvbcons >= 2 )
546 {
547 SCIP_CALL( detectDominatingVlbs(scip, matrix, nvbcons, vbcons,
548 lowthresholds, highthresholds, conidxs, binidxs,
549 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
550 }
551 }
552
553 SCIPfreeBufferArray(scip, &vbcons);
554 SCIPfreeBufferArray(scip, &highthresholds);
555 SCIPfreeBufferArray(scip, &lowthresholds);
556 SCIPfreeBufferArray(scip, &conidxs);
557 SCIPfreeBufferArray(scip, &binidxs);
558
559 return SCIP_OKAY;
560}
561
562/*
563 * Callback methods of presolver
564 */
565
566/** copy method for presolver plugins (called when SCIP copies plugins) */
567static
568SCIP_DECL_PRESOLCOPY(presolCopyRedvub)
569{ /*lint --e{715}*/
570 assert(scip != NULL);
571 assert(presol != NULL);
572 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
573
574 /* call inclusion method of presolver */
576
577 return SCIP_OKAY;
578}
579
580/** execution method of presolver */
581static
582SCIP_DECL_PRESOLEXEC(presolExecRedvub)
583{ /*lint --e{715}*/
584 SCIP_MATRIX* matrix;
585 SCIP_Bool initialized;
586 SCIP_Bool complete;
587 SCIP_Bool infeasible;
588
589 assert(result != NULL);
590 *result = SCIP_DIDNOTRUN;
591
593 return SCIP_OKAY;
594
596 return SCIP_OKAY;
597
598 *result = SCIP_DIDNOTFIND;
599
600 matrix = NULL;
601 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
602 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
603
604 /* if infeasibility was detected during matrix creation, return here */
605 if( infeasible )
606 {
607 if( initialized )
608 SCIPmatrixFree(scip, &matrix);
609
610 *result = SCIP_CUTOFF;
611 return SCIP_OKAY;
612 }
613
614 if( initialized && complete )
615 {
616 int nvaragg;
617 SCIP_Bool* isvartoagg;
618 int ndeletecons;
619 SCIP_Bool* deletecons;
620 SCIP_VAR** aggvars;
621 int ncols;
622 int nrows;
623
624 ncols = SCIPmatrixGetNColumns(matrix);
625 nrows = SCIPmatrixGetNRows(matrix);
626
627 nvaragg = 0;
628 ndeletecons = 0;
629
630 SCIP_CALL( SCIPallocBufferArray(scip, &isvartoagg, ncols) );
631 BMSclearMemoryArray(isvartoagg, ncols);
632
633 SCIP_CALL( SCIPallocBufferArray(scip, &deletecons, nrows) );
634 BMSclearMemoryArray(deletecons, nrows);
635
636 SCIP_CALL( SCIPallocBufferArray(scip, &aggvars, ncols) );
637 BMSclearMemoryArray(aggvars, ncols);
638
639 SCIP_CALL( findVarAggrRedVbcons(scip, matrix, &nvaragg, isvartoagg, aggvars, &ndeletecons, deletecons) );
640
641 if( nvaragg > 0 )
642 {
643 int v;
644 for( v = 0; v < ncols; v++ )
645 {
646 if( isvartoagg[v] )
647 {
648 SCIP_Bool redundant;
649 SCIP_Bool aggregated;
650
651 /* substitute/aggregate binary variable */
652 assert(aggvars[v] != NULL);
653 SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix,v), aggvars[v], 1.0, -1.0,
654 0.0, &infeasible, &redundant, &aggregated) );
655
656 if( infeasible )
657 {
658 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
659 *result = SCIP_CUTOFF;
660 return SCIP_OKAY;
661 }
662
663 if( aggregated )
664 {
665 (*naggrvars)++;
666
667 /* set result pointer */
668 if( (*result) == SCIP_DIDNOTFIND )
669 *result = SCIP_SUCCESS;
670 }
671 }
672 }
673 }
674
675 if( ndeletecons > 0 )
676 {
677 int r;
678 for( r = 0; r < nrows; r++ )
679 {
680 if( deletecons[r] )
681 {
682 SCIP_CONS* cons;
683
684 /* remove redundant variable bound constraint */
685 cons = SCIPmatrixGetCons(matrix, r);
686 SCIP_CALL( SCIPdelCons(scip, cons) );
687
688 (*ndelconss)++;
689
690 /* set result pointer */
691 if( (*result) == SCIP_DIDNOTFIND )
692 *result = SCIP_SUCCESS;
693 }
694 }
695 }
696
697 SCIPfreeBufferArray(scip, &aggvars);
698 SCIPfreeBufferArray(scip, &deletecons);
699 SCIPfreeBufferArray(scip, &isvartoagg);
700 }
701
702 SCIPmatrixFree(scip, &matrix);
703
704 return SCIP_OKAY;
705}
706
707/*
708 * presolver specific interface methods
709 */
710
711/** creates the redvub presolver and includes it in SCIP */
713 SCIP* scip /**< SCIP data structure */
714 )
715{
716 SCIP_PRESOL* presol;
717
718 /* include presolver */
720 PRESOL_TIMING, presolExecRedvub, NULL) );
721
722 /* set non fundamental callbacks via setter functions */
723 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyRedvub) );
724
725 return SCIP_OKAY;
726}
SCIP_Real * r
Definition: circlepacking.c:59
#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
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:3420
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPincludePresolRedvub(SCIP *scip)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
Definition: scip_nlp.c:74
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 SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition: var.c:23498
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip_var.c:10550
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:23900
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
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_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:16807
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_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
SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:2189
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
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition: matrix.c:2037
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
static SCIP_RETCODE detectDominatingVlbs(SCIP *scip, SCIP_MATRIX *matrix, int nvlbs, int *vlbs, SCIP_Real *lowthresholds, SCIP_Real *highthresholds, int *conidxs, int *binidxs, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
static SCIP_Bool isVlb(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lowthreshold, SCIP_Real *highthreshold, int *conidx, int *binidx)
#define PRESOL_NAME
Definition: presol_redvub.c:60
static SCIP_RETCODE detectDominatingVubs(SCIP *scip, SCIP_MATRIX *matrix, int nvubs, int *vubs, SCIP_Real *lowthresholds, SCIP_Real *highthresholds, int *conidxs, int *binidxs, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
#define MAXPAIRCOMP
Definition: presol_redvub.c:66
static SCIP_Bool isVub(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lowthreshold, SCIP_Real *highthreshold, int *conidx, int *binidx)
Definition: presol_redvub.c:74
static SCIP_DECL_PRESOLCOPY(presolCopyRedvub)
#define PRESOL_PRIORITY
Definition: presol_redvub.c:62
static SCIP_RETCODE findVarAggrRedVbcons(SCIP *scip, SCIP_MATRIX *matrix, int *nvaragg, SCIP_Bool *isvartoagg, SCIP_VAR **aggvars, int *ndeletecons, SCIP_Bool *deletecons)
#define PRESOL_MAXROUNDS
Definition: presol_redvub.c:63
#define PRESOL_TIMING
Definition: presol_redvub.c:64
static SCIP_DECL_PRESOLEXEC(presolExecRedvub)
#define PRESOL_DESC
Definition: presol_redvub.c:61
remove redundant variable upper bound constraints
public methods for matrix
public methods for message output
public methods for presolvers
public methods for problem variables
public methods for constraint handler plugins and constraints
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 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
@ 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_VARTYPE_BINARY
Definition: type_var.h:64
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73