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
125 /* we claim that the vub has the structure ax + cy >= b
126 * with a<0, c>0, x continuous, x>=0, y binary and obj(y)>=0
127 */
128 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
129 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
130 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
131 {
132 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
133 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
134 *conidx = idx1;
135 *binidx = idx2;
136 isvub = TRUE;
137 }
138 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
139 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
140 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
141 {
142 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
143 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
144 *conidx = idx2;
145 *binidx = idx1;
146 isvub = TRUE;
147 }
148 }
149
150 return isvub;
151}
152
153/** verify if the constraint is a variable lower bound constraint */
154static
156 SCIP* scip, /**< SCIP main data structure */
157 SCIP_MATRIX* matrix, /**< matrix instance */
158 int row, /**< row index */
159 SCIP_Real* lowthreshold, /**< low switching threshold */
160 SCIP_Real* highthreshold, /**< high switching threshold */
161 int* conidx, /**< variable index of continuous variable */
162 int* binidx /**< variable index of binary variable */
163 )
164{
165 SCIP_Real* valpnt;
166 int* rowpnt;
167 SCIP_Bool isvlb;
168
169 assert(scip != NULL);
170 assert(matrix != NULL);
171 assert(0 <= row && row < SCIPmatrixGetNRows(matrix));
172 assert(lowthreshold != NULL);
173 assert(highthreshold != NULL);
174 assert(conidx != NULL);
175 assert(binidx != NULL);
176
177 isvlb = FALSE;
178
179 if( SCIPmatrixGetRowNNonzs(matrix, row) == 2 && SCIPmatrixIsRowRhsInfinity(matrix, row) )
180 {
181 SCIP_VARTYPE type1;
182 SCIP_VARTYPE type2;
183 int idx1;
184 int idx2;
185 SCIP_VAR* var1;
186 SCIP_VAR* var2;
187 SCIP_Real val1;
188 SCIP_Real val2;
189
190 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
191 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
192
193 idx1 = *rowpnt;
194 val1 = *valpnt;
195 var1 = SCIPmatrixGetVar(matrix, idx1);
196 type1 = SCIPvarGetType(var1);
197
198 rowpnt++;
199 valpnt++;
200
201 idx2 = *rowpnt;
202 val2 = *valpnt;
203 var2 = SCIPmatrixGetVar(matrix, idx2);
204 type2 = SCIPvarGetType(var2);
205
206 /* we claim that the vlb has the structure ax + cy >= b
207 * with a>0, c<0, x continuous, x>=0, y binary and obj(y)>=0
208 */
209 if( (type1 == SCIP_VARTYPE_CONTINUOUS && type2 == SCIP_VARTYPE_BINARY)
210 && val1 > 0.0 && val2 < 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var1), 0.0)
211 && SCIPisGE(scip, SCIPvarGetObj(var2), 0.0) )
212 {
213 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val1;
214 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val2) / val1;
215 *conidx = idx1;
216 *binidx = idx2;
217 isvlb = TRUE;
218 }
219 else if( (type1 == SCIP_VARTYPE_BINARY && type2 == SCIP_VARTYPE_CONTINUOUS)
220 && val1 < 0.0 && val2 > 0.0 && SCIPisGE(scip, SCIPvarGetLbGlobal(var2), 0.0)
221 && SCIPisGE(scip, SCIPvarGetObj(var1), 0.0) )
222 {
223 *lowthreshold = SCIPmatrixGetRowLhs(matrix, row) / val2;
224 *highthreshold = (SCIPmatrixGetRowLhs(matrix, row) - val1) / val2;
225 *conidx = idx2;
226 *binidx = idx1;
227 isvlb = TRUE;
228 }
229 }
230
231 return isvlb;
232}
233
234
235/** searches for variable upper bound constraints on the same continuous variable with a dominance relation */
236static
238 SCIP* scip, /**< SCIP main data structure */
239 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
240 int nvubs, /**< number of vubs */
241 int* vubs, /**< row indices of the vubs */
242 SCIP_Real* lowthresholds, /**< low switching thresholds */
243 SCIP_Real* highthresholds, /**< high switching thresholds */
244 int* conidxs, /**< variable indexes of continuous variable */
245 int* binidxs, /**< variable indexes of binary variable */
246 int* nvaragg, /**< number of variables for aggregation */
247 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
248 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
249 int* ndeletecons, /**< number of deleteable constraints */
250 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
251 )
252{
253 int i;
254 int j;
255 SCIP_Bool uselinearscan;
256
257 assert(scip != NULL);
258 assert(matrix != NULL);
259 assert(vubs != NULL);
260 assert(nvubs >= 2);
261 assert(lowthresholds != NULL);
262 assert(highthresholds != NULL);
263 assert(conidxs != NULL);
264 assert(binidxs != NULL);
265 assert(nvaragg != NULL);
266 assert(isvartoagg != NULL);
267 assert(aggvars != NULL);
268 assert(ndeletecons != NULL);
269 assert(deletecons != NULL);
270
271 /* use pairwise comparison only for a small number of vub constraints */
272 if( nvubs >= MAXPAIRCOMP )
273 uselinearscan = TRUE;
274 else
275 uselinearscan = FALSE;
276
277 for( i = 0; i < nvubs; i++ )
278 {
279 for( j = i+1; j < nvubs; j++ )
280 {
281 SCIP_VAR* var1;
282 SCIP_VAR* var2;
283
284 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
285 continue;
286
287 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
288 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
289
290 /* make sure that the binary variables switch synchronously */
291 if((SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 1 &&
292 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 1 &&
293 SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 0 &&
294 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 0) ||
295 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
296 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
297 {
298 if( SCIPisLE(scip, highthresholds[i], highthresholds[j]) )
299 {
300#ifdef SCIP_DEBUG
301 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
302 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
303 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[j]), NULL));
304 SCIPinfoMessage(scip, NULL, "\n");
305#endif
306
307 isvartoagg[binidxs[j]] = TRUE;
308 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
309 (*nvaragg)++;
310
311 deletecons[vubs[j]] = TRUE;
312 (*ndeletecons)++;
313 }
314 else
315 {
316 assert(SCIPisGT(scip, highthresholds[i], highthresholds[j]));
317#ifdef SCIP_DEBUG
318 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
319 SCIPdebugMsg(scip, "Delete variable upper bound constraint:\n");
320 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vubs[i]), NULL));
321 SCIPinfoMessage(scip, NULL, "\n");
322#endif
323
324 isvartoagg[binidxs[i]] = TRUE;
325 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
326 (*nvaragg)++;
327
328 deletecons[vubs[i]] = TRUE;
329 (*ndeletecons)++;
330 }
331 }
332
333 if( uselinearscan )
334 break;
335 }
336 }
337
338 return SCIP_OKAY;
339}
340
341/** searches for variable lower bound constraints on the same continuous variable with a dominance relation */
342static
344 SCIP* scip, /**< SCIP main data structure */
345 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
346 int nvlbs, /**< number of vlbs */
347 int* vlbs, /**< row indices of the vlbs */
348 SCIP_Real* lowthresholds, /**< low switching thresholds */
349 SCIP_Real* highthresholds, /**< high switching thresholds */
350 int* conidxs, /**< variable indexes of continuous variable */
351 int* binidxs, /**< variable indexes of binary variable */
352 int* nvaragg, /**< number of variables for aggregation */
353 SCIP_Bool* isvartoagg, /**< flags indicating if variable could be aggregated */
354 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
355 int* ndeletecons, /**< number of deleteable constraints */
356 SCIP_Bool* deletecons /**< flags which constraints could be deleted */
357
358 )
359{
360 int i;
361 int j;
362 SCIP_Bool uselinearscan;
363
364 assert(scip != NULL);
365 assert(matrix != NULL);
366 assert(vlbs != NULL);
367 assert(nvlbs >= 2);
368 assert(lowthresholds != NULL);
369 assert(highthresholds != NULL);
370 assert(conidxs != NULL);
371 assert(binidxs != NULL);
372 assert(nvaragg != NULL);
373 assert(isvartoagg != NULL);
374 assert(aggvars != NULL);
375 assert(ndeletecons != NULL);
376 assert(deletecons != NULL);
377
378 /* use pairwise comparison only for a small number of vlb constraints */
379 if( nvlbs >= MAXPAIRCOMP )
380 uselinearscan = TRUE;
381 else
382 uselinearscan = FALSE;
383
384 for( i = 0; i < nvlbs; i++ )
385 {
386 for( j = i+1; j < nvlbs; j++ )
387 {
388 SCIP_VAR* var1;
389 SCIP_VAR* var2;
390
391 if( !SCIPisEQ(scip, lowthresholds[i], lowthresholds[j]) )
392 continue;
393
394 var1 = SCIPmatrixGetVar(matrix, binidxs[i]);
395 var2 = SCIPmatrixGetVar(matrix, binidxs[j]);
396
397 /* make sure that the binary variables switch synchronously */
398 if((SCIPmatrixGetColNUplocks(matrix, binidxs[j]) == 1 &&
399 SCIPmatrixGetColNUplocks(matrix, binidxs[i]) == 1 &&
400 SCIPmatrixGetColNDownlocks(matrix, binidxs[j]) == 0 &&
401 SCIPmatrixGetColNDownlocks(matrix, binidxs[i]) == 0) ||
402 (SCIPvarsHaveCommonClique(var1, FALSE, var2, TRUE, TRUE) &&
403 SCIPvarsHaveCommonClique(var1, TRUE, var2, FALSE, TRUE)) )
404 {
405 if( SCIPisGE(scip, highthresholds[i], highthresholds[j]) )
406 {
407#ifdef SCIP_DEBUG
408 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var2), SCIPvarGetName(var1));
409 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
410 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[j]), NULL));
411 SCIPinfoMessage(scip, NULL, "\n");
412#endif
413
414 isvartoagg[binidxs[j]] = TRUE;
415 aggvars[binidxs[j]] = SCIPmatrixGetVar(matrix, binidxs[i]);
416 (*nvaragg)++;
417
418 deletecons[vlbs[j]] = TRUE;
419 (*ndeletecons)++;
420 }
421 else
422 {
423 assert(SCIPisLT(scip, highthresholds[i], highthresholds[j]));
424#ifdef SCIP_DEBUG
425 SCIPdebugMsg(scip, "Aggregate variable %s by %s\n", SCIPvarGetName(var1), SCIPvarGetName(var2));
426 SCIPdebugMsg(scip, "Delete variable lower bound constraint:\n");
427 SCIP_CALL( SCIPprintCons(scip, SCIPmatrixGetCons(matrix, vlbs[i]), NULL));
428 SCIPinfoMessage(scip, NULL, "\n");
429#endif
430
431 isvartoagg[binidxs[i]] = TRUE;
432 aggvars[binidxs[i]] = SCIPmatrixGetVar(matrix, binidxs[j]);
433 (*nvaragg)++;
434
435 deletecons[vlbs[i]] = TRUE;
436 (*ndeletecons)++;
437 }
438 }
439
440 if( uselinearscan )
441 break;
442 }
443 }
444
445 return SCIP_OKAY;
446}
447
448/** find variable aggregations and redundant variable bound constraints */
449static
451 SCIP* scip, /**< SCIP main data structure */
452 SCIP_MATRIX* matrix, /**< constraint matrix */
453 int* nvaragg, /**< number of redundant variables */
454 SCIP_Bool* isvartoagg, /**< flags indicating which variables could be substituted/aggregated */
455 SCIP_VAR** aggvars, /**< pointers to the variables by which the aggregation should be done */
456 int* ndeletecons, /**< number of redundant constraints */
457 SCIP_Bool* deletecons /**< flags indicating which constraints could be deleted */
458 )
459{
460 int c;
461 int* colpnt;
462 int* colend;
463 int* vbcons;
464 int nvbcons;
465 int ncols;
466 int nrows;
467 SCIP_Real* lowthresholds;
468 SCIP_Real* highthresholds;
469 int* conidxs;
470 int* binidxs;
471
472 ncols = SCIPmatrixGetNColumns(matrix);
473 nrows = SCIPmatrixGetNRows(matrix);
474
475 SCIP_CALL( SCIPallocBufferArray(scip, &binidxs, nrows) );
476 SCIP_CALL( SCIPallocBufferArray(scip, &conidxs, nrows) );
477 SCIP_CALL( SCIPallocBufferArray(scip, &lowthresholds, nrows) );
478 SCIP_CALL( SCIPallocBufferArray(scip, &highthresholds, nrows) );
479 SCIP_CALL( SCIPallocBufferArray(scip, &vbcons, nrows) );
480
481 for( c = 0; c < ncols; c++ )
482 {
483 SCIP_VAR* var;
484
485 var = SCIPmatrixGetVar(matrix, c);
486
488 continue;
489
490 /* search vubs per variable */
491 nvbcons = 0;
492 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
493 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
494 for( ; (colpnt < colend); colpnt++ )
495 {
496 SCIP_Real lowthreshold;
497 SCIP_Real highthreshold;
498 int conidx;
499 int binidx;
500
501 if( isVub(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
502 {
503 vbcons[nvbcons] = *colpnt;
504 lowthresholds[nvbcons] = lowthreshold;
505 highthresholds[nvbcons] = highthreshold;
506 conidxs[nvbcons] = conidx;
507 binidxs[nvbcons] = binidx;
508 nvbcons++;
509 }
510 }
511 if( nvbcons >= 2 )
512 {
513 SCIP_CALL( detectDominatingVubs(scip, matrix, nvbcons, vbcons,
514 lowthresholds, highthresholds, conidxs, binidxs,
515 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
516 }
517
518 /* search vlbs per variable */
519 nvbcons = 0;
520 colpnt = SCIPmatrixGetColIdxPtr(matrix, c);
521 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, c);
522 for( ; (colpnt < colend); colpnt++ )
523 {
524 SCIP_Real lowthreshold;
525 SCIP_Real highthreshold;
526 int conidx;
527 int binidx;
528
529 if( isVlb(scip, matrix, *colpnt, &lowthreshold, &highthreshold, &conidx, &binidx) )
530 {
531 vbcons[nvbcons] = *colpnt;
532 lowthresholds[nvbcons] = lowthreshold;
533 highthresholds[nvbcons] = highthreshold;
534 conidxs[nvbcons] = conidx;
535 binidxs[nvbcons] = binidx;
536 nvbcons++;
537 }
538 }
539 if( nvbcons >= 2 )
540 {
541 SCIP_CALL( detectDominatingVlbs(scip, matrix, nvbcons, vbcons,
542 lowthresholds, highthresholds, conidxs, binidxs,
543 nvaragg, isvartoagg, aggvars, ndeletecons, deletecons) );
544 }
545 }
546
547 SCIPfreeBufferArray(scip, &vbcons);
548 SCIPfreeBufferArray(scip, &highthresholds);
549 SCIPfreeBufferArray(scip, &lowthresholds);
550 SCIPfreeBufferArray(scip, &conidxs);
551 SCIPfreeBufferArray(scip, &binidxs);
552
553 return SCIP_OKAY;
554}
555
556/*
557 * Callback methods of presolver
558 */
559
560/** copy method for presolver plugins (called when SCIP copies plugins) */
561static
562SCIP_DECL_PRESOLCOPY(presolCopyRedvub)
563{ /*lint --e{715}*/
564 assert(scip != NULL);
565 assert(presol != NULL);
566 assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
567
568 /* call inclusion method of presolver */
570
571 return SCIP_OKAY;
572}
573
574/** execution method of presolver */
575static
576SCIP_DECL_PRESOLEXEC(presolExecRedvub)
577{ /*lint --e{715}*/
578 SCIP_MATRIX* matrix;
579 SCIP_Bool initialized;
580 SCIP_Bool complete;
581 SCIP_Bool infeasible;
582
583 assert(result != NULL);
584 *result = SCIP_DIDNOTRUN;
585
587 return SCIP_OKAY;
588
590 return SCIP_OKAY;
591
592 *result = SCIP_DIDNOTFIND;
593
594 matrix = NULL;
595 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
596 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
597
598 /* if infeasibility was detected during matrix creation, return here */
599 if( infeasible )
600 {
601 if( initialized )
602 SCIPmatrixFree(scip, &matrix);
603
604 *result = SCIP_CUTOFF;
605 return SCIP_OKAY;
606 }
607
608 if( initialized && complete )
609 {
610 int nvaragg;
611 SCIP_Bool* isvartoagg;
612 int ndeletecons;
613 SCIP_Bool* deletecons;
614 SCIP_VAR** aggvars;
615 int ncols;
616 int nrows;
617
618 ncols = SCIPmatrixGetNColumns(matrix);
619 nrows = SCIPmatrixGetNRows(matrix);
620
621 nvaragg = 0;
622 ndeletecons = 0;
623
624 SCIP_CALL( SCIPallocBufferArray(scip, &isvartoagg, ncols) );
625 BMSclearMemoryArray(isvartoagg, ncols);
626
627 SCIP_CALL( SCIPallocBufferArray(scip, &deletecons, nrows) );
628 BMSclearMemoryArray(deletecons, nrows);
629
630 SCIP_CALL( SCIPallocBufferArray(scip, &aggvars, ncols) );
631 BMSclearMemoryArray(aggvars, ncols);
632
633 SCIP_CALL( findVarAggrRedVbcons(scip, matrix, &nvaragg, isvartoagg, aggvars, &ndeletecons, deletecons) );
634
635 if( nvaragg > 0 )
636 {
637 int v;
638 for( v = 0; v < ncols; v++ )
639 {
640 if( isvartoagg[v] )
641 {
642 SCIP_Bool redundant;
643 SCIP_Bool aggregated;
644
645 /* substitute/aggregate binary variable */
646 assert(aggvars[v] != NULL);
647 SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix,v), aggvars[v], 1.0, -1.0,
648 0.0, &infeasible, &redundant, &aggregated) );
649
650 if( infeasible )
651 {
652 SCIPdebugMsg(scip, " -> infeasible aggregation\n");
653 *result = SCIP_CUTOFF;
654 return SCIP_OKAY;
655 }
656
657 if( aggregated )
658 {
659 (*naggrvars)++;
660
661 /* set result pointer */
662 if( (*result) == SCIP_DIDNOTFIND )
663 *result = SCIP_SUCCESS;
664 }
665 }
666 }
667 }
668
669 if( ndeletecons > 0 )
670 {
671 int r;
672 for( r = 0; r < nrows; r++ )
673 {
674 if( deletecons[r] )
675 {
676 SCIP_CONS* cons;
677
678 /* remove redundant variable bound constraint */
679 cons = SCIPmatrixGetCons(matrix, r);
680 SCIP_CALL( SCIPdelCons(scip, cons) );
681
682 (*ndelconss)++;
683
684 /* set result pointer */
685 if( (*result) == SCIP_DIDNOTFIND )
686 *result = SCIP_SUCCESS;
687 }
688 }
689 }
690
691 SCIPfreeBufferArray(scip, &aggvars);
692 SCIPfreeBufferArray(scip, &deletecons);
693 SCIPfreeBufferArray(scip, &isvartoagg);
694 }
695
696 SCIPmatrixFree(scip, &matrix);
697
698 return SCIP_OKAY;
699}
700
701/*
702 * presolver specific interface methods
703 */
704
705/** creates the redvub presolver and includes it in SCIP */
707 SCIP* scip /**< SCIP data structure */
708 )
709{
710 SCIP_PRESOL* presol;
711
712 /* include presolver */
714 PRESOL_TIMING, presolExecRedvub, NULL) );
715
716 /* set non fundamental callbacks via setter functions */
717 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyRedvub) );
718
719 return SCIP_OKAY;
720}
SCIP_Real * r
Definition: circlepacking.c:59
#define NULL
Definition: def.h:266
#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 SCIP_CALL(x)
Definition: def.h:373
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:734
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:390
int SCIPgetNContVars(SCIP *scip)
Definition: scip_prob.c:2172
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2843
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:2537
#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:140
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:105
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition: presol.c:599
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip_pricer.c:348
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:97
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_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:8524
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17946
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17604
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17439
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18098
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11495
int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1580
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1708
int SCIPmatrixGetColNDownlocks(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1648
int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1592
SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1766
int SCIPmatrixGetColNUplocks(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1636
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1742
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1684
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:454
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition: matrix.c:1604
SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1860
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition: matrix.c:1072
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1660
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1696
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition: matrix.c:1732
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:62
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:73