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