Scippy

SCIP

Solving Constraint Integer Programs

presol_tworowbnd.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-2016 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_tworowbnd.c
17  * @brief do bound tightening by using two rows
18  * @author Dieter Weninger
19  *
20  * Perform bound tightening on two inequalities with some common variables.
21  *
22  * Let two constraints be given:
23  * \f{eqnarray*}{
24  * A_{iR} x_R + A_{iS} x_S \geq b_i\\
25  * A_{kR} x_R + A_{kT} x_T \geq b_k
26  * \f}
27  * with \f$N\f$ the set of variable indexes, \f$R \subseteq N\f$, \f$S \subseteq N\f$, \f$T \subseteq N\f$,
28  * \f$R \cap S = \emptyset\f$, \f$R \cap T = \emptyset\f$, \f$S \cap T = \emptyset\f$ and \f$i \not= k\f$.
29  *
30  * Solve the following two LPs
31  * \f{eqnarray*}{
32  * L = \min \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i \}\\
33  * U = \max \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i \}
34  * \f}
35  * and use \f$L\f$ and \f$U\f$ for getting bounds on \f$x_T\f$.
36  *
37  * If \f$L + \mbox{infimum}(A_{kT}x_T) \geq b_k\f$, then the second constraint above is redundant.
38  */
39 
40 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
41 
42 #include <stdio.h>
43 #include <assert.h>
44 #include <string.h>
45 
46 #include "scip/pub_matrix.h"
47 #include "presol_tworowbnd.h"
48 
49 #define PRESOL_NAME "tworowbnd"
50 #define PRESOL_DESC "do bound tigthening by using two rows"
51 #define PRESOL_PRIORITY -500000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
52 #define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
53 #define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
54 
55 #define SUPPORT_THRESHOLD 0.5 /**< threshold for two constraints overlap */
56 #define FASTMODE_THRESHOLD 1000 /**< max number of baserows for switching to fast mode */
57 
58 /* uncomment the following define to debug solving the small LPs */
59 /* #define DEBUG_WRITE_CHECK_LPS */
60 
61 /** type of bound change */
63 {
67 };
68 typedef enum Bndchgtype BNDCHGTYPE;
69 
70 /*
71  * Local methods
72  */
73 
74 #ifdef DEBUG_WRITE_CHECK_LPS
75 /** write min and max LP to file */
76 static
77 void writeLPs(
78  SCIP* scip, /**< SCIP data structure */
79  SCIP_MATRIX* matrix, /**< constraint matrix object */
80  int otherrow, /**< other row index */
81  int numoverlap, /**< overlap-size */
82  int* overlapidx, /**< overlap column indexes */
83  int* othernonoverlapidx, /**< other row non overlap indexes */
84  SCIP_Real* coefbaseoverlap, /**< base row overlap coefficients */
85  SCIP_Real* coefotheroverlap, /**< other row overlap coefficients */
86  SCIP_Real* coefothernonoverlap,/**< other row non overlap coefficients */
87  SCIP_Real* lowerbds, /**< lower bounds */
88  SCIP_Real* upperbds /**< upper bounds */
89  )
90 {
91  FILE* filemax;
92  FILE* filemin;
93  SCIP_Real lhs;
94  int i;
95  int nothernonolap;
96 
97  lhs = SCIPmatrixGetRowLhs(matrix, otherrow);
98 
99  filemax = fopen("max.lp", "wt");
100  filemin = fopen("min.lp", "wt");
101  if( filemax != NULL && filemin != NULL )
102  {
103  fprintf(filemax, "max\n\t");
104  fprintf(filemin, "min\n\t");
105 
106  for( i = 0; i < numoverlap; i++ )
107  {
108  if( coefbaseoverlap[i] > 0.0 )
109  {
110  fprintf(filemax, "+%.24f %s ", coefbaseoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
111  fprintf(filemin, "+%.24f %s ", coefbaseoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
112  }
113  else
114  {
115  fprintf(filemax, "%.24f %s ", coefbaseoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
116  fprintf(filemin, "%.24f %s ", coefbaseoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
117  }
118  }
119 
120  fprintf(filemax, "\ns.t.\n\t");
121  fprintf(filemin, "\ns.t.\n\t");
122 
123  for( i = 0; i < numoverlap; i++ )
124  {
125  if( coefotheroverlap[i] > 0.0 )
126  {
127  fprintf(filemax, "+%.24f %s ", coefotheroverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
128  fprintf(filemin, "+%.24f %s ", coefotheroverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
129  }
130  else
131  {
132  fprintf(filemax, "%.24f %s ", coefotheroverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
133  fprintf(filemin, "%.24f %s ", coefotheroverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
134  }
135  }
136 
137  nothernonolap = SCIPmatrixGetRowNNonzs(matrix, otherrow) - numoverlap;
138 
139  for( i = 0; i < nothernonolap; i++ )
140  {
141  if( coefothernonoverlap[i] > 0.0 )
142  {
143  fprintf(filemax, "+%.24f %s ", coefothernonoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
144  fprintf(filemin, "+%.24f %s ", coefothernonoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
145  }
146  else
147  {
148  fprintf(filemax, "%.24f %s ", coefothernonoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
149  fprintf(filemin, "%.24f %s ", coefothernonoverlap[i], SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
150  }
151  }
152  fprintf(filemax, " >= %.24f\n", lhs);
153  fprintf(filemin, " >= %.24f\n", lhs);
154 
155  fprintf(filemax, "bounds\n");
156  fprintf(filemin, "bounds\n");
157 
158  for( i = 0; i < numoverlap; i++ )
159  {
160  if( !SCIPisInfinity(scip, -lowerbds[overlapidx[i]]) && !SCIPisInfinity(scip, upperbds[overlapidx[i]]) )
161  {
162  fprintf(filemax, "\t%.24f <= %s <= %.24f\n", lowerbds[overlapidx[i]],
163  SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])), upperbds[overlapidx[i]]);
164  fprintf(filemin, "\t%.24f <= %s <= %.24f\n", lowerbds[overlapidx[i]],
165  SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])), upperbds[overlapidx[i]]);
166  }
167  else if( !SCIPisInfinity(scip, -lowerbds[overlapidx[i]]) )
168  {
169  fprintf(filemax, "\t%.24f <= %s\n", lowerbds[overlapidx[i]], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
170  fprintf(filemin, "\t%.24f <= %s\n", lowerbds[overlapidx[i]], SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])));
171  }
172  else if( !SCIPisInfinity(scip, upperbds[overlapidx[i]]) )
173  {
174  fprintf(filemax, "\t%s <= %.24f\n", SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])), upperbds[overlapidx[i]]);
175  fprintf(filemin, "\t%s <= %.24f\n", SCIPvarGetName(SCIPmatrixGetVar(matrix, overlapidx[i])), upperbds[overlapidx[i]]);
176  }
177  }
178 
179  for( i = 0; i < nothernonolap; i++ )
180  {
181  if( !SCIPisInfinity(scip, -lowerbds[othernonoverlapidx[i]]) && !SCIPisInfinity(scip, upperbds[othernonoverlapidx[i]]) )
182  {
183  fprintf(filemax, "\t%.24f <= %s <= %.24f\n", lowerbds[othernonoverlapidx[i]],
184  SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])), upperbds[othernonoverlapidx[i]]);
185  fprintf(filemin, "\t%.24f <= %s <= %.24f\n", lowerbds[othernonoverlapidx[i]],
186  SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])), upperbds[othernonoverlapidx[i]]);
187  }
188  else if( !SCIPisInfinity(scip, -lowerbds[othernonoverlapidx[i]]) )
189  {
190  fprintf(filemax, "\t%.24f <= %s\n", lowerbds[othernonoverlapidx[i]],
191  SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
192  fprintf(filemin, "\t%.24f <= %s\n", lowerbds[othernonoverlapidx[i]],
193  SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])));
194  }
195  else if( !SCIPisInfinity(scip, upperbds[othernonoverlapidx[i]]) )
196  {
197  fprintf(filemax, "\t%s <= %.24f\n", SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])), upperbds[othernonoverlapidx[i]]);
198  fprintf(filemin, "\t%s <= %.24f\n", SCIPvarGetName(SCIPmatrixGetVar(matrix, othernonoverlapidx[i])), upperbds[othernonoverlapidx[i]]);
199  }
200  }
201 
202 
203  fprintf(filemax, "end\n");
204  fprintf(filemin, "end\n");
205 
206  fclose(filemax);
207  fclose(filemin);
208  }
209  else
210  SCIPABORT();
211 }
212 #endif
213 
214 
215 /** solve two LPs with one row (single constraint) each
216  *
217  * a1x + a3y >= b1 (other row)
218  * a2x + a4z >= b2 (base row)
219  *
220  * minact = min{a2x : a1x + a3y >= b1}
221  * maxact = max{a2x : a1x + a3y >= b1}
222  */
223 static
225  SCIP* scip, /**< SCIP data structure */
226  SCIP_MATRIX* matrix, /**< constraint matrix object */
227  int baserow, /**< base row index */
228  int otherrow, /**< other row index */
229  int numoverlap, /**< overlap-size */
230  int* overlapidx, /**< overlap column indexes */
231  int* othernonoverlapidx, /**< other row non overlap indexes */
232  SCIP_Real* coefbaseoverlap, /**< base row overlap coefficients */
233  SCIP_Real* coefotheroverlap, /**< other row overlap coefficients */
234  SCIP_Real* coefothernonoverlap,/**< other row non overlap coefficients */
235  SCIP_Real* lowerbds, /**< lower bounds */
236  SCIP_Real* upperbds, /**< upper bounds */
237  SCIP_Real* tmplowerbds, /**< tmp lower bounds */
238  SCIP_Real* tmpupperbds, /**< tmp upper bounds */
239  SCIP_Real* minratios, /**< min LP ratios */
240  SCIP_Real* maxratios, /**< max LP ratios */
241  int* minsortedidx, /**< min LP sorted indexes */
242  int* maxsortedidx, /**< max LP sorted indexes */
243  SCIP_Real* minact, /**< calculated overlap minimal activity w.r.t. to the other row */
244  SCIP_Real* maxact /**< calculated overlap maximal activity w.r.t. to the other row */
245  )
246 {/*lint --e{715}*/
247  SCIP_Real val;
248  int nothernonoverlap;
249  SCIP_Real lhs;
250  SCIP_Real minlhs;
251  SCIP_Real maxlhs;
252  SCIP_Bool consred;
253  int nminratios;
254  int nmaxratios;
255  int i;
256 
257  *minact = 0;
258  *maxact = 0;
259 
260 #ifdef DEBUG_WRITE_CHECK_LPS
261  SCIPmatrixPrintRow(scip,matrix,baserow);
262  SCIPmatrixPrintRow(scip,matrix,otherrow);
263  writeLPs(scip, matrix, otherrow, numoverlap, overlapidx, othernonoverlapidx,
264  coefbaseoverlap, coefotheroverlap, coefothernonoverlap, lowerbds, upperbds);
265 #endif
266 
267  lhs = SCIPmatrixGetRowLhs(matrix, otherrow);
268  assert(!SCIPisInfinity(scip, -lhs));
269 
270  nothernonoverlap = SCIPmatrixGetRowNNonzs(matrix, otherrow) - numoverlap;
271  val = 0;
272  consred = FALSE;
273 
274  /* compute maximal contribution of non-overlap part of the
275  single constraint to the activity.
276  maybe the single constraint is redundant */
277  for( i = 0; i < nothernonoverlap; i++ )
278  {
279  if( coefothernonoverlap[i] < 0.0 )
280  {
281  if( SCIPisInfinity(scip, -lowerbds[othernonoverlapidx[i]]) )
282  {
283  consred = TRUE;
284  break;
285  }
286  else
287  {
288  val += coefothernonoverlap[i] * lowerbds[othernonoverlapidx[i]];
289  }
290  }
291  else if( coefothernonoverlap[i] > 0.0 )
292  {
293  if( SCIPisInfinity(scip, upperbds[othernonoverlapidx[i]]) )
294  {
295  consred = TRUE;
296  break;
297  }
298  else
299  {
300  val += coefothernonoverlap[i] * upperbds[othernonoverlapidx[i]];
301  }
302  }
303  }
304 
305  if( !consred )
306  {
307  SCIP_Real minlowerbnd;
308  minlowerbnd = SCIPinfinity(scip);
309 
310  /* we want that every coefficient in the single constraint
311  has a negative sign and hence we need to multiply
312  some columns by -1 */
313  for( i = 0; i < numoverlap; i++ )
314  {
315  tmplowerbds[i] = lowerbds[overlapidx[i]];
316  tmpupperbds[i] = upperbds[overlapidx[i]];
317 
318  if( coefotheroverlap[i] > 0.0 )
319  {
320  /* multiply column by -1 and swap bounds */
321  double tmp;
322  tmp = tmplowerbds[i];
323  tmplowerbds[i] = -tmpupperbds[i];
324  tmpupperbds[i] = -tmp;
325 
326  coefotheroverlap[i] = -coefotheroverlap[i];
327  coefbaseoverlap[i] = -coefbaseoverlap[i];
328  }
329 
330  if( tmplowerbds[i] < minlowerbnd )
331  {
332  if( SCIPisInfinity(scip, -tmplowerbds[i]) )
333  {
334  /* lower bounds have to be finite for later boundshift */
335  *minact = -SCIPinfinity(scip);
336  *maxact = SCIPinfinity(scip);
337  return;
338  }
339  minlowerbnd = tmplowerbds[i];
340  }
341  }
342 
343  if( minlowerbnd < 0.0 )
344  {
345  SCIP_Real bndshift = -minlowerbnd;
346  if( bndshift > (SCIP_Real)SCIP_LONGINT_MAX )
347  {
348  /* shift value is too large */
349  *minact = -SCIPinfinity(scip);
350  *maxact = SCIPinfinity(scip);
351  return;
352  }
353  }
354 
355  /* init left hand side values and consider non-overlapping contribution */
356  minlhs = lhs - val;
357  nminratios = 0;
358  maxlhs = lhs - val;
359  nmaxratios = 0;
360 
361  if( minlowerbnd < 0.0 )
362  {
363  double bndshift = -minlowerbnd;
364  if( bndshift > (double)SCIP_LONGINT_MAX )
365  {
366  /* shift value is too large */
367  *minact = -SCIPinfinity(scip);
368  *maxact = SCIPinfinity(scip);
369  return;
370  }
371 
372  /* shift polyhedra into the positive orthant */
373  for( i = 0; i < numoverlap; i++ )
374  {
375  minlhs += coefotheroverlap[i] * bndshift;
376  *minact -= coefbaseoverlap[i] * bndshift;
377 
378  maxlhs += coefotheroverlap[i] * bndshift;
379  *maxact -= coefbaseoverlap[i] * bndshift;
380 
381  tmplowerbds[i] += bndshift;
382  tmpupperbds[i] += bndshift;
383 
384  assert(tmplowerbds[i] >= 0.0);
385  }
386  }
387 
388  /*
389  * solve minimization LP
390  *
391  * we distinguish two column cases:
392  *
393  * a) b)
394  * min - min +
395  * s.t. - s.t. -
396  */
397 
398  for( i = 0; i < numoverlap; i++ )
399  {
400  if( coefbaseoverlap[i] > 0.0 )
401  {
402  /* b): fix variable to its lower bound */
403  minlhs -= coefotheroverlap[i] * tmplowerbds[i];
404  *minact += coefbaseoverlap[i] * tmplowerbds[i];
405  }
406  else
407  {
408  /* a): save coefficient ratios for later sorting */
409  minratios[nminratios] = coefbaseoverlap[i] / coefotheroverlap[i];
410  minsortedidx[nminratios] = i;
411  nminratios++;
412 
413  /* consider lower bounds for left hand side and obj value */
414  minlhs -= coefotheroverlap[i] * tmplowerbds[i];
415  *minact += coefbaseoverlap[i] * tmplowerbds[i];
416  }
417  }
418 
419  /* sort the ratios for case a) */
420  if( nminratios > 1 )
421  SCIPsortRealInt(minratios, minsortedidx, nminratios);
422 
423  /* pack every variable on the highest possible value as long as we are feasible */
424  for( i = nminratios-1; 0 <= i; i-- )
425  {
426  SCIP_Real tmpval;
427 
428  /* consider contribution from lower bounds */
429  if( tmplowerbds[minsortedidx[i]] > 0 )
430  {
431  *minact -= coefbaseoverlap[minsortedidx[i]] * tmplowerbds[minsortedidx[i]];
432  minlhs += coefotheroverlap[minsortedidx[i]] * tmplowerbds[minsortedidx[i]];
433  }
434 
435  /* calculate highest possible variable value */
436  tmpval = minlhs / coefotheroverlap[minsortedidx[i]];
437  if( tmpval < tmplowerbds[minsortedidx[i]] )
438  {
439  /* infeasible */
440  *minact = -SCIPinfinity(scip);
441  break;
442  }
443 
444  /* if the upper bound is large enough we are ready
445  otherwise we set the variable to its upper bound and iterate */
446  if( tmpval <= tmpupperbds[minsortedidx[i]] )
447  {
448  *minact += coefbaseoverlap[minsortedidx[i]] * tmpval;
449  minlhs -= coefotheroverlap[minsortedidx[i]] * tmpval;
450  break;
451  }
452  else
453  {
454  *minact += coefbaseoverlap[minsortedidx[i]] * tmpupperbds[minsortedidx[i]];
455  minlhs -= coefotheroverlap[minsortedidx[i]] * tmpupperbds[minsortedidx[i]];
456  }
457  }
458 
459 
460  /*
461  * solve maximization LP
462  *
463  * we distinguish two column cases:
464  *
465  * c) d)
466  * max + max -
467  * s.t. - s.t. -
468  */
469  for( i = 0; i < numoverlap; i++ )
470  {
471  if( coefbaseoverlap[i] < 0.0 )
472  {
473  /* d): fix variable to its lower bound */
474  maxlhs -= coefotheroverlap[i] * tmplowerbds[i];
475  *maxact += coefbaseoverlap[i] * tmplowerbds[i];
476  }
477  else
478  {
479  /* c): save coefficient ratios for later sorting */
480  maxratios[nmaxratios] = coefbaseoverlap[i] / coefotheroverlap[i];
481  maxsortedidx[nmaxratios] = i;
482  nmaxratios++;
483 
484  /* consider lower bounds for left hand side and obj value */
485  maxlhs -= coefotheroverlap[i] * tmplowerbds[i];
486  *maxact += coefbaseoverlap[i] * tmplowerbds[i];
487  }
488  }
489 
490  /* sort the ratios for case a) */
491  if( nmaxratios > 1 )
492  SCIPsortRealInt(maxratios, maxsortedidx, nmaxratios);
493 
494  /* pack every variable on the highest possible value as long as we are feasible */
495  for( i = 0; i < nmaxratios; i++ )
496  {
497  SCIP_Real tmpval;
498 
499  /* consider contribution from lower bounds */
500  if( tmplowerbds[maxsortedidx[i]] > 0 )
501  {
502  *maxact -= coefbaseoverlap[maxsortedidx[i]] * tmplowerbds[maxsortedidx[i]];
503  maxlhs += coefotheroverlap[maxsortedidx[i]] * tmplowerbds[maxsortedidx[i]];
504  }
505 
506  /* calculate highest possible variable value */
507  tmpval = maxlhs / coefotheroverlap[maxsortedidx[i]];
508  if( tmpval < tmplowerbds[maxsortedidx[i]] )
509  {
510  /* infeasible */
511  *maxact = SCIPinfinity(scip);
512  break;
513  }
514 
515  /* if the upper bound is large enough we are ready
516  otherwise we set the variable to its upper bound and iterate */
517  if( tmpval <= tmpupperbds[maxsortedidx[i]] )
518  {
519  *maxact += coefbaseoverlap[maxsortedidx[i]] * tmpval;
520  maxlhs -= coefotheroverlap[maxsortedidx[i]] * tmpval;
521  break;
522  }
523  else
524  {
525  *maxact += coefbaseoverlap[maxsortedidx[i]] * tmpupperbds[maxsortedidx[i]];
526  maxlhs -= coefotheroverlap[maxsortedidx[i]] * tmpupperbds[maxsortedidx[i]];
527  }
528  }
529  }
530  else
531  {
532  /* single constraint is redundant.
533  we calculate the value of the objective function */
534 
535  /* minimization LP */
536  for( i = 0; i < numoverlap; i++ )
537  {
538  if( coefbaseoverlap[i] > 0.0 )
539  {
540  if( !SCIPisInfinity(scip, -lowerbds[overlapidx[i]]) )
541  {
542  *minact += coefbaseoverlap[i] * lowerbds[overlapidx[i]];
543  }
544  else
545  {
546  *minact = -SCIPinfinity(scip);
547  break;
548  }
549  }
550  else if( coefbaseoverlap[i] < 0.0 )
551  {
552  if( !SCIPisInfinity(scip, upperbds[overlapidx[i]]) )
553  {
554  *minact += coefbaseoverlap[i] * upperbds[overlapidx[i]];
555  }
556  else
557  {
558  *minact = -SCIPinfinity(scip);
559  break;
560  }
561  }
562  }
563 
564  /* maximization LP */
565  for( i = 0; i < numoverlap; i++ )
566  {
567  if( coefbaseoverlap[i] > 0.0 )
568  {
569  if( !SCIPisInfinity(scip, upperbds[overlapidx[i]]) )
570  {
571  *maxact += coefbaseoverlap[i] * upperbds[overlapidx[i]];
572  }
573  else
574  {
575  *maxact = SCIPinfinity(scip);
576  break;
577  }
578  }
579  else if( coefbaseoverlap[i] < 0.0 )
580  {
581  if( !SCIPisInfinity(scip, -lowerbds[overlapidx[i]]) )
582  {
583  *maxact += coefbaseoverlap[i] * lowerbds[overlapidx[i]];
584  }
585  else
586  {
587  *maxact = SCIPinfinity(scip);
588  break;
589  }
590  }
591  }
592  }
593 
594 #ifdef DEBUG_WRITE_CHECK_LPS
595  {
596  SCIP_Real minsolve = 0.0;
597  SCIP* subscip;
598  SCIP_RETCODE retcode;
599  SCIP_SOL* sol;
600  SCIP_STATUS status;
601  SCIP_VAR** vars;
602  int nvars;
603  int objnonzeros = 0;
604  retcode = SCIPcreate(&subscip);
605  retcode = SCIPincludeDefaultPlugins(subscip);
606  retcode = SCIPreadProb(subscip, "min.lp", NULL);
607  retcode = SCIPsetIntParam(subscip,"presolving/maxrounds",0);
608  vars = SCIPgetVars(subscip);
609  nvars = SCIPgetNVars(subscip);
610  for(i=0; i< nvars; i++)
611  {
612  if(SCIPvarGetObj(vars[i]) != 0.0)
613  objnonzeros++;
614  }
615  assert(numoverlap == objnonzeros);
616 
617  retcode = SCIPsolve(subscip);
618  status = SCIPgetStatus(subscip);
619  if(SCIP_STATUS_OPTIMAL == status)
620  {
621  sol = SCIPgetBestSol(subscip);
622  minsolve = SCIPgetSolOrigObj(subscip, sol);
623  assert(SCIPisEQ(scip,minsolve,*minact));
624  }
625  else
626  {
627  assert(SCIPisEQ(scip,-SCIPinfinity(scip),*minact));
628  }
629  retcode = SCIPfree(&subscip);
630  }
631  {
632  SCIP_Real maxsolve = 0.0;
633  SCIP* subscip;
634  SCIP_RETCODE retcode;
635  SCIP_SOL* sol;
636  SCIP_STATUS status;
637  retcode = SCIPcreate(&subscip);
638  retcode = SCIPincludeDefaultPlugins(subscip);
639  retcode = SCIPreadProb(subscip, "max.lp", NULL);
640  retcode = SCIPsetIntParam(subscip,"presolving/maxrounds",0);
641  retcode = SCIPsolve(subscip);
642  status = SCIPgetStatus(subscip);
643  if(SCIP_STATUS_OPTIMAL == status)
644  {
645  sol = SCIPgetBestSol(subscip);
646  maxsolve = SCIPgetSolOrigObj(subscip, sol);
647  assert(SCIPisEQ(scip,maxsolve,*maxact));
648  }
649  else
650  {
651  assert(SCIPisEQ(scip,SCIPinfinity(scip),*maxact));
652  }
653  retcode = SCIPfree(&subscip);
654  }
655 #endif
656 }/*lint !e438*/
657 
658 /** calculate min activity */
659 static
661  SCIP* scip, /**< SCIP data structure */
662  int len, /**< length */
663  int* varidxs, /**< variables indexes */
664  SCIP_Real* coefs, /**< coefficients */
665  SCIP_Real* lowerbds, /**< lower bounds */
666  SCIP_Real* upperbds /**< upper bounds */
667  )
668 {
669  SCIP_Real infimum;
670  int i;
671 
672  infimum = 0;
673 
674  for( i = 0; i < len; i++ )
675  {
676  if( coefs[i] > 0.0 )
677  {
678  if( SCIPisInfinity(scip, -lowerbds[varidxs[i]]) )
679  {
680  infimum = -SCIPinfinity(scip);
681  break;
682  }
683  else
684  {
685  infimum += coefs[i] * lowerbds[varidxs[i]];
686  }
687  }
688  else
689  {
690  if( SCIPisInfinity(scip, upperbds[varidxs[i]]) )
691  {
692  infimum = -SCIPinfinity(scip);
693  break;
694  }
695  else
696  {
697  infimum += coefs[i] * upperbds[varidxs[i]];
698  }
699  }
700  }
701 
702  return infimum;
703 }
704 
705 /** calculate max activity */
706 static
708  SCIP* scip, /**< SCIP data structure */
709  int len, /**< length */
710  int* varidxs, /**< variable indexes */
711  SCIP_Real* coefs, /**< coefficients */
712  SCIP_Real* lowerbds, /**< lower bounds */
713  SCIP_Real* upperbds, /**< upper bounds */
714  int* infcnt /**< infinity counter */
715  )
716 {
717  SCIP_Real supremum;
718  int i;
719 
720  *infcnt = 0;
721  supremum = 0;
722 
723  for( i = 0; i < len; i++ )
724  {
725  if( coefs[i] < 0.0 )
726  {
727  if( SCIPisInfinity(scip, -lowerbds[varidxs[i]]) )
728  (*infcnt)++;
729  else
730  supremum += coefs[i] * lowerbds[varidxs[i]];
731  }
732  else
733  {
734  if( SCIPisInfinity(scip, upperbds[varidxs[i]]) )
735  (*infcnt)++;
736  else
737  supremum += coefs[i] * upperbds[varidxs[i]];
738  }
739  }
740 
741  if(*infcnt > 0)
742  supremum = SCIPinfinity(scip);
743 
744  return supremum;
745 }
746 
747 /** get max activity without one column */
748 static
750  SCIP* scip, /**< SCIP data structure */
751  int len, /**< length */
752  int* varidxs, /**< variable indexes */
753  SCIP_Real* coefs, /**< coefficients */
754  SCIP_Real* lowerbds, /**< upper bounds */
755  SCIP_Real* upperbds, /**< lower bounds */
756  int idx /**< omitting index */
757  )
758 {
759  SCIP_Real supremum;
760  int i;
761 
762  supremum = 0;
763 
764  for( i = 0; i < len; i++ )
765  {
766  if( i == idx )
767  continue;
768 
769  if( coefs[i] < 0.0 )
770  {
771  assert(!SCIPisInfinity(scip, -lowerbds[varidxs[i]]));
772  supremum += coefs[i] * lowerbds[varidxs[i]];
773  }
774  else
775  {
776  assert(!SCIPisInfinity(scip, upperbds[varidxs[i]]));
777  supremum += coefs[i] * upperbds[varidxs[i]];
778  }
779  }
780 
781  return supremum;
782 }
783 
784 /** apply bound tightening on two overlapping constraints */
785 static
787  SCIP* scip, /**< SCIP data structure */
788  SCIP_MATRIX* matrix, /**< constraint matrix object */
789  int baserow, /**< base row index */
790  int otherrow, /**< other row index */
791  int numoverlap, /**< overlap-size */
792  int* overlapidx, /**< overlap column indexes */
793  int* othernonoverlapidx, /**< other row non overlap indexes */
794  int* basenonoverlapidx, /**< base row non overlap indexes */
795  SCIP_Real* coefbaseoverlap, /**< base row overlap coefficients */
796  SCIP_Real* coefotheroverlap, /**< other row overlap coefficients */
797  SCIP_Real* coefbasenonoverlap, /**< base row non overlap coefficients */
798  SCIP_Real* coefothernonoverlap,/**< other row non overlap coefficients */
799  SCIP_Real* lowerbds, /**< lower bounds */
800  SCIP_Real* upperbds, /**< upper bounds */
801  SCIP_Real* tmplowerbds, /**< tmp lower bounds */
802  SCIP_Real* tmpupperbds, /**< tmp upper bounds */
803  SCIP_Real* minratios, /**< min LP ratios */
804  SCIP_Real* maxratios, /**< max LP ratios */
805  int* minsortedidx, /**< min LP sorted indexes */
806  int* maxsortedidx, /**< max LP sorted indexes */
807  int* ntightenbnds, /**< number of tightened bounds */
808  BNDCHGTYPE* tighten, /**< tightened bounds */
809  int* ndeletecons, /**< number of redundant constraints */
810  SCIP_Bool* deletecons /**< redundant constraints */
811  )
812 {
813  SCIP_Real maxactoverlap;
814  SCIP_Real minactoverlap;
815  SCIP_Real minactnonoverlap;
816  SCIP_Real maxactnonoverlap;
817  int len;
818  SCIP_Real lhs;
819  int i;
820 
821  getActivities(scip, matrix, baserow, otherrow, numoverlap, overlapidx, othernonoverlapidx,
822  coefbaseoverlap, coefotheroverlap, coefothernonoverlap,
823  lowerbds, upperbds, tmplowerbds, tmpupperbds, minratios, maxratios,
824  minsortedidx, maxsortedidx, &minactoverlap, &maxactoverlap);
825 
826  len = SCIPmatrixGetRowNNonzs(matrix, baserow) - numoverlap;
827  lhs = SCIPmatrixGetRowLhs(matrix, baserow);
828 
829  if( !SCIPisInfinity(scip, -minactoverlap) )
830  {
831  /* detect redundant constraints */
832  minactnonoverlap = getMinActivity(scip, len, basenonoverlapidx, coefbasenonoverlap, lowerbds, upperbds);
833  if( !SCIPisInfinity(scip, -minactnonoverlap) )
834  {
835  if( SCIPisGE(scip, minactoverlap + minactnonoverlap, lhs) )
836  {
837  if( !deletecons[baserow] )
838  {
839  (*ndeletecons)++;
840  deletecons[baserow] = TRUE;
841  }
842  }
843  }
844  }
845 
846  if( !SCIPisInfinity(scip, maxactoverlap) )
847  {
848  int infcnt;
849  SCIP_Real bnd;
850  SCIP_Real tmpsup;
851 
852  /* bound tightening */
853  maxactnonoverlap = getMaxActivity(scip, len, basenonoverlapidx, coefbasenonoverlap, lowerbds, upperbds, &infcnt);
854  if( !SCIPisInfinity(scip, maxactnonoverlap) )
855  {
856  for( i = 0; i < len; i++ )
857  {
858  if( coefbasenonoverlap[i] < 0.0 )
859  {
860  /* get ub */
861  tmpsup = maxactnonoverlap - (coefbasenonoverlap[i] * lowerbds[basenonoverlapidx[i]]);
862  bnd = (lhs - (tmpsup + maxactoverlap)) / coefbasenonoverlap[i];
863  if( bnd < upperbds[basenonoverlapidx[i]] )
864  {
865  upperbds[basenonoverlapidx[i]] = bnd;
866  if( tighten[basenonoverlapidx[i]] != UPPERBOUND && tighten[basenonoverlapidx[i]] != BOTHBOUNDS )
867  {
868  (*ntightenbnds)++;
869  if( tighten[basenonoverlapidx[i]] == LOWERBOUND )
870  tighten[basenonoverlapidx[i]] = BOTHBOUNDS;
871  else
872  tighten[basenonoverlapidx[i]] = UPPERBOUND;
873  }
874  }
875  }
876  else
877  {
878  /* get lb */
879  tmpsup = maxactnonoverlap - (coefbasenonoverlap[i] * upperbds[basenonoverlapidx[i]]);
880  bnd = (lhs - (tmpsup + maxactoverlap)) / coefbasenonoverlap[i];
881  if( bnd > lowerbds[basenonoverlapidx[i]] )
882  {
883  lowerbds[basenonoverlapidx[i]] = bnd;
884  if( tighten[basenonoverlapidx[i]] != LOWERBOUND && tighten[basenonoverlapidx[i]] != BOTHBOUNDS )
885  {
886  (*ntightenbnds)++;
887  if( tighten[basenonoverlapidx[i]] == UPPERBOUND )
888  tighten[basenonoverlapidx[i]] = BOTHBOUNDS;
889  else
890  tighten[basenonoverlapidx[i]] = LOWERBOUND;
891  }
892  }
893  }
894  }
895  }
896  /* maximal activity in non-overlapping variables is +infinity */
897  else
898  {
899  /* we can only do bound tightening, if we have exactly one infinite contribution*/
900  if( infcnt == 1 )
901  {
902  for( i = 0; i < len; i++ )
903  {
904  if( coefbasenonoverlap[i] < 0.0 )
905  {
906  if( SCIPisInfinity(scip, -lowerbds[basenonoverlapidx[i]]) )
907  {
908  /* get ub */
909  tmpsup = getMaxResActivity(scip, len, basenonoverlapidx, coefbasenonoverlap, lowerbds, upperbds, i);
910  assert(!SCIPisInfinity(scip, tmpsup));
911  bnd = (lhs - (tmpsup + maxactoverlap)) / coefbasenonoverlap[i];
912  if( bnd < upperbds[basenonoverlapidx[i]] )
913  {
914  upperbds[basenonoverlapidx[i]] = bnd;
915  if( tighten[basenonoverlapidx[i]] != UPPERBOUND && tighten[basenonoverlapidx[i]] != BOTHBOUNDS )
916  {
917  (*ntightenbnds)++;
918  if( tighten[basenonoverlapidx[i]] == LOWERBOUND )
919  tighten[basenonoverlapidx[i]] = BOTHBOUNDS;
920  else
921  tighten[basenonoverlapidx[i]] = UPPERBOUND;
922  }
923  }
924  }
925  }
926  else
927  {
928  if( infcnt == 1 && SCIPisInfinity(scip, upperbds[basenonoverlapidx[i]]) )
929  {
930  /* get lb */
931  tmpsup = getMaxResActivity(scip, len, basenonoverlapidx, coefbasenonoverlap, lowerbds, upperbds, i);
932  assert(!SCIPisInfinity(scip, tmpsup));
933  bnd = (lhs - (tmpsup + maxactoverlap)) / coefbasenonoverlap[i];
934  if( bnd > lowerbds[basenonoverlapidx[i]] )
935  {
936  lowerbds[basenonoverlapidx[i]] = bnd;
937  if( tighten[basenonoverlapidx[i]] != LOWERBOUND && tighten[basenonoverlapidx[i]] != BOTHBOUNDS )
938  {
939  (*ntightenbnds)++;
940  if( tighten[basenonoverlapidx[i]] == UPPERBOUND )
941  tighten[basenonoverlapidx[i]] = BOTHBOUNDS;
942  else
943  tighten[basenonoverlapidx[i]] = LOWERBOUND;
944  }
945  }
946  }
947  }
948  }
949  }
950  }
951  }
952 }
953 
954 /** extract coefficients from matrix */
955 static
957  SCIP* scip, /**< SCIP data structure */
958  SCIP_MATRIX* matrix, /**< constraint matrix object */
959  int baserow, /**< base row index */
960  int otherrow, /**< other row index */
961  int numoverlap, /**< overlap-size */
962  int* olapidxbaseorder, /**< overlap column indexes in baserow order */
963  int* olapidxotherorder, /**< overlap column indexes in otherrow order */
964  int* othernonoverlapidx, /**< other row non overlap indexes */
965  int* basenonoverlapidx, /**< base row non overlap indexes */
966  SCIP_Real* coefbaseoverlap, /**< base row overlap coefficients */
967  SCIP_Real* coefotheroverlap, /**< other row overlap coefficients */
968  SCIP_Real* coefbasenonoverlap, /**< base row non overlap coefficients */
969  SCIP_Real* coefothernonoverlap /**< other row non overlap coefficients */
970  )
971 {
972  SCIP_Real* valpnt;
973  int* rowpnt;
974  int* rowend;
975  int baserowcnt;
976  int otherrowcnt;
977  int olapcnt;
978  int nonolapcnt;
979 
980  /* get number of columns in the rows */
981  baserowcnt = SCIPmatrixGetRowNNonzs(matrix, baserow);
982  otherrowcnt = SCIPmatrixGetRowNNonzs(matrix, otherrow);
983  assert(baserowcnt != 0 && otherrowcnt != 0);
984 
985 #if 1 /* @todo why do we need this? */
986  /* set end marker */
987  if( numoverlap < SCIPmatrixGetNColumns(matrix) )
988  {
989  olapidxbaseorder[numoverlap] = -1;
990  olapidxotherorder[numoverlap] = -1;
991  }
992 #endif
993 
994  olapcnt = 0;
995  nonolapcnt = 0;
996 
997  /* partition columns of base row into overlapping columns and non-overlapping columns (w.r.t. other row) and store
998  * the corresponding coefficients
999  */
1000  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, baserow);
1001  rowend = rowpnt + baserowcnt;
1002  valpnt = SCIPmatrixGetRowValPtr(matrix, baserow);
1003 
1004  for( ; rowpnt < rowend; rowpnt++, valpnt++ )
1005  {
1006  if( olapidxbaseorder[olapcnt] == *rowpnt )
1007  {
1008  coefbaseoverlap[olapcnt] = *valpnt;
1009  olapcnt++;
1010  }
1011  else
1012  {
1013  basenonoverlapidx[nonolapcnt] = *rowpnt;
1014  coefbasenonoverlap[nonolapcnt] = *valpnt;
1015  nonolapcnt++;
1016  }
1017  }
1018 
1019  assert(olapcnt+nonolapcnt == baserowcnt);
1020  assert(olapcnt == numoverlap);
1021  assert(nonolapcnt > 0);
1022 
1023  olapcnt = 0;
1024  nonolapcnt = 0;
1025 
1026  /* partition columns of other row into overlapping columns and non-overlapping columns (w.r.t. base row) and store
1027  * the corresponding coefficients
1028  */
1029  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, otherrow);
1030  rowend = rowpnt + otherrowcnt;
1031  valpnt = SCIPmatrixGetRowValPtr(matrix, otherrow);
1032 
1033  for( ; rowpnt < rowend; rowpnt++, valpnt++ )
1034  {
1035  if( olapidxotherorder[olapcnt] == *rowpnt )
1036  {
1037  coefotheroverlap[olapcnt] = *valpnt;
1038  olapcnt++;
1039  }
1040  else
1041  {
1042  othernonoverlapidx[nonolapcnt] = *rowpnt;
1043  coefothernonoverlap[nonolapcnt] = *valpnt;
1044  nonolapcnt++;
1045  }
1046  }
1047 
1048  assert(olapcnt+nonolapcnt == otherrowcnt);
1049  assert(olapcnt == numoverlap);
1050 }
1051 
1052 /** calculate overlap-size */
1053 static
1055  SCIP* scip, /**< SCIP data structure */
1056  SCIP_MATRIX* matrix, /**< constraint matrix object */
1057  int baserow, /**< base row index */
1058  int otherrow, /**< other row index */
1059  int* countings, /**< overlap counting helper array */
1060  int* clearinfo, /**< reset helper array */
1061  int* numoverlap, /**< overlap-size */
1062  int* olapidxotherorder /**< overlap column indexes in otherrow order */
1063  )
1064 {
1065  int* rowpnt;
1066  int* rowend;
1067  int noverlap;
1068  int baserowcnt;
1069  int otherrowcnt;
1070  int nclear;
1071  int i;
1072 
1073  noverlap = 0;
1074  nclear = 0;
1075 
1076  baserowcnt = SCIPmatrixGetRowNNonzs(matrix, baserow);
1077  otherrowcnt = SCIPmatrixGetRowNNonzs(matrix, otherrow);
1078  if( baserowcnt == 0 || otherrowcnt == 0 )
1079  {
1080  *numoverlap = noverlap;
1081  return;
1082  }
1083 
1084  /* set flags corresponding to baserow non-zeros */
1085  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, baserow);
1086  rowend = rowpnt + baserowcnt;
1087  for( ; rowpnt < rowend; rowpnt++ )
1088  {
1089  countings[*rowpnt] = 1;
1090  clearinfo[nclear] = *rowpnt;
1091  nclear++;
1092  }
1093 
1094  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, otherrow);
1095  rowend = rowpnt + otherrowcnt;
1096  for( ; rowpnt < rowend; rowpnt++ )
1097  {
1098  if( countings[*rowpnt] == 1 )
1099  {
1100  /* collect overlapping indexes in otherrow order */
1101  olapidxotherorder[noverlap] = *rowpnt;
1102  noverlap++;
1103  }
1104  }
1105 
1106  for( i = 0; i < nclear; i++ )
1107  countings[clearinfo[i]] = 0;
1108 
1109  *numoverlap = noverlap;
1110 }
1111 
1112 static
1114  SCIP* scip, /**< SCIP data structure */
1115  SCIP_MATRIX* matrix, /**< constraint matrix object */
1116  int baserow, /**< base row index */
1117  int otherrow, /**< other row index */
1118  int* countings, /**< overlap counting helper array */
1119  int* clearinfo, /**< reset helper array */
1120  int numoverlap, /**< just calculated overlap-size */
1121  int* olapidxbaseorder /**< overlap column indexes in baserow order */
1122  )
1123 {
1124  int* rowpnt;
1125  int* rowend;
1126  int noverlap;
1127  int baserowcnt;
1128  int otherrowcnt;
1129  int nclear;
1130  int i;
1131 
1132  noverlap = 0;
1133  nclear = 0;
1134 
1135  baserowcnt = SCIPmatrixGetRowNNonzs(matrix, baserow);
1136  otherrowcnt = SCIPmatrixGetRowNNonzs(matrix, otherrow);
1137 
1138  /* set flags corresponding to otherrow non-zeros */
1139  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, otherrow);
1140  rowend = rowpnt + otherrowcnt;
1141  for( ; rowpnt < rowend; rowpnt++ )
1142  {
1143  countings[*rowpnt] = 1;
1144  clearinfo[nclear] = *rowpnt;
1145  nclear++;
1146  }
1147 
1148  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, baserow);
1149  rowend = rowpnt + baserowcnt;
1150  for( ; rowpnt < rowend; rowpnt++ )
1151  {
1152  if( countings[*rowpnt] == 1 )
1153  {
1154  /* collect overlapping indexes in baserow order */
1155  olapidxbaseorder[noverlap] = *rowpnt;
1156  noverlap++;
1157  }
1158  }
1159 
1160  for( i = 0; i < nclear; i++ )
1161  countings[clearinfo[i]] = 0;
1162 
1163  assert(noverlap == numoverlap);
1164 }
1165 
1166 
1167 /** perform bound tightening on two rows with a specific support intersection */
1168 static
1170  SCIP* scip, /**< SCIP data structure */
1171  SCIP_MATRIX* matrix, /**< constraint matrix object */
1172  int nbaserows, /**< number of base rows */
1173  int* baserows, /**< base rows indexes */
1174  SCIP_Real* lowerbds, /**< lower bounds */
1175  SCIP_Real* upperbds, /**< upper bounds */
1176  int* ntightenbnds, /**< number of tightened bounds */
1177  BNDCHGTYPE* tighten, /**< bound tighten information */
1178  int* ndeletecons, /**< number of redundant constraints */
1179  SCIP_Bool* deletecons /**< redundant constraints */
1180  )
1181 {
1182  int* rowpnt;
1183  int* rowend;
1184  int rowcnt;
1185  int br;
1186  int col;
1187  int* colpnt;
1188  int* colend;
1189  int colcnt;
1190  int numoverlap;
1191  int* olapidxbaseorder;
1192  int* olapidxotherorder;
1193  SCIP_Real threshold;
1194  int rowcnt2;
1195  int nrows;
1196  int ncols;
1197  int* othernonoverlapidx;
1198  int* basenonoverlapidx;
1199  SCIP_Real* coefbaseoverlap;
1200  SCIP_Real* coefotheroverlap;
1201  SCIP_Real* coefbasenonoverlap;
1202  SCIP_Real* coefothernonoverlap;
1203  int* countings;
1204  int* clearinfo;
1205  SCIP_Real* tmplowerbds;
1206  SCIP_Real* tmpupperbds;
1207  SCIP_Real* minratios;
1208  SCIP_Real* maxratios;
1209  int* minsortedidx;
1210  int* maxsortedidx;
1211  SCIP_Bool usefastmode;
1212  int* ignorerowidx;
1213  SCIP_Bool* ignorerow;
1214  int ignorerowcnt;
1215  int i;
1216 
1217  nrows = SCIPmatrixGetNRows(matrix);
1218  ncols = SCIPmatrixGetNColumns(matrix);
1219 
1220  SCIP_CALL( SCIPallocBufferArray(scip, &olapidxbaseorder, ncols) );
1221  SCIP_CALL( SCIPallocBufferArray(scip, &olapidxotherorder, ncols) );
1222  SCIP_CALL( SCIPallocBufferArray(scip, &othernonoverlapidx, ncols) );
1223  SCIP_CALL( SCIPallocBufferArray(scip, &basenonoverlapidx, ncols) );
1224  SCIP_CALL( SCIPallocBufferArray(scip, &coefbaseoverlap, ncols) );
1225  SCIP_CALL( SCIPallocBufferArray(scip, &coefotheroverlap, ncols) );
1226  SCIP_CALL( SCIPallocBufferArray(scip, &coefbasenonoverlap, ncols) );
1227  SCIP_CALL( SCIPallocBufferArray(scip, &coefothernonoverlap, ncols) );
1228  SCIP_CALL( SCIPallocBufferArray(scip, &countings, ncols) );
1229  BMSclearMemoryArray(countings, ncols);
1230  SCIP_CALL( SCIPallocBufferArray(scip, &clearinfo, ncols) );
1231  SCIP_CALL( SCIPallocBufferArray(scip, &tmplowerbds, ncols) );
1232  SCIP_CALL( SCIPallocBufferArray(scip, &tmpupperbds, ncols) );
1233  SCIP_CALL( SCIPallocBufferArray(scip, &minratios, ncols) );
1234  SCIP_CALL( SCIPallocBufferArray(scip, &maxratios, ncols) );
1235  SCIP_CALL( SCIPallocBufferArray(scip, &minsortedidx, ncols) );
1236  SCIP_CALL( SCIPallocBufferArray(scip, &maxsortedidx, ncols) );
1237  SCIP_CALL( SCIPallocBufferArray(scip, &ignorerowidx, nrows) );
1238  SCIP_CALL( SCIPallocBufferArray(scip, &ignorerow, nrows) );
1239  BMSclearMemoryArray(ignorerow, nrows);
1240 
1241  /* use fast mode if too many base rows are present */
1242  if( nbaserows > FASTMODE_THRESHOLD )
1243  usefastmode = TRUE;
1244  else
1245  usefastmode = FALSE;
1246 
1247  for( br = 0; br < nbaserows; br++ )
1248  {
1249  ignorerowcnt = 0;
1250 
1251  rowpnt = SCIPmatrixGetRowIdxPtr(matrix, baserows[br]);
1252  rowcnt = SCIPmatrixGetRowNNonzs(matrix, baserows[br]);
1253  if( rowcnt == 0 )
1254  continue;
1255 
1256  rowend = rowpnt + rowcnt;
1257 
1258  for( ; (rowpnt < rowend); rowpnt++ )
1259  {
1260  col = *rowpnt;
1261  colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
1262  colcnt = SCIPmatrixGetColNNonzs(matrix, col);
1263  colend = colpnt + colcnt;
1264  for( ; (colpnt < colend); colpnt++ )
1265  {
1266  if( *colpnt == baserows[br] || ignorerow[*colpnt] )
1267  continue;
1268 
1269  /* we consider only >= constraints */
1270  if( !SCIPmatrixIsRowRhsInfinity(matrix, *colpnt) )
1271  continue;
1272 
1273  /* determine overlap-size */
1274  getNumOverlap(scip, matrix, baserows[br], *colpnt,
1275  countings, clearinfo, &numoverlap, olapidxotherorder);
1276 
1277  if( numoverlap == 0 )
1278  continue;
1279 
1280  rowcnt2 = SCIPmatrixGetRowNNonzs(matrix, *colpnt);
1281  threshold = (SCIP_Real)numoverlap/(SCIP_Real)MIN(rowcnt, rowcnt2);
1282 
1283  /* verify if overlap-size is ok */
1284  if( SUPPORT_THRESHOLD <= threshold && numoverlap < rowcnt )
1285  {
1286  getOverlapBaseOrdered(scip, matrix, baserows[br], *colpnt,
1287  countings, clearinfo, numoverlap, olapidxbaseorder);
1288 
1289  getCoefficients(scip, matrix, baserows[br], *colpnt, numoverlap,
1290  olapidxbaseorder, olapidxotherorder, othernonoverlapidx, basenonoverlapidx,
1291  coefbaseoverlap, coefotheroverlap, coefbasenonoverlap, coefothernonoverlap);
1292 
1293  applyTightening(scip, matrix, baserows[br], *colpnt, numoverlap, olapidxotherorder,
1294  othernonoverlapidx, basenonoverlapidx,
1295  coefbaseoverlap, coefotheroverlap, coefbasenonoverlap, coefothernonoverlap,
1296  lowerbds, upperbds, tmplowerbds, tmpupperbds, minratios, maxratios,
1297  minsortedidx, maxsortedidx, ntightenbnds, tighten, ndeletecons, deletecons);
1298  }
1299 
1300  ignorerow[*colpnt] = TRUE;
1301  ignorerowidx[ignorerowcnt] = *colpnt;
1302  ignorerowcnt++;
1303 
1304  if( usefastmode )
1305  break;
1306  }
1307 
1308  if( usefastmode )
1309  break;
1310  }
1311 
1312  for( i = 0; i < ignorerowcnt; i++ )
1313  ignorerow[ignorerowidx[i]] = FALSE;
1314  }
1315 
1316  SCIPfreeBufferArray(scip, &ignorerow);
1317  SCIPfreeBufferArray(scip, &ignorerowidx);
1318  SCIPfreeBufferArray(scip, &maxsortedidx);
1319  SCIPfreeBufferArray(scip, &minsortedidx);
1320  SCIPfreeBufferArray(scip, &maxratios);
1321  SCIPfreeBufferArray(scip, &minratios);
1322  SCIPfreeBufferArray(scip, &tmpupperbds);
1323  SCIPfreeBufferArray(scip, &tmplowerbds);
1324  SCIPfreeBufferArray(scip, &clearinfo);
1325  SCIPfreeBufferArray(scip, &countings);
1326  SCIPfreeBufferArray(scip, &coefothernonoverlap);
1327  SCIPfreeBufferArray(scip, &coefbasenonoverlap);
1328  SCIPfreeBufferArray(scip, &coefotheroverlap);
1329  SCIPfreeBufferArray(scip, &coefbaseoverlap);
1330  SCIPfreeBufferArray(scip, &basenonoverlapidx);
1331  SCIPfreeBufferArray(scip, &othernonoverlapidx);
1332  SCIPfreeBufferArray(scip, &olapidxotherorder);
1333  SCIPfreeBufferArray(scip, &olapidxbaseorder);
1334 
1335  return SCIP_OKAY;
1336 }
1337 
1338 /** determine base rows */
1339 static
1341  SCIP* scip, /**< SCIP main data structure */
1342  SCIP_MATRIX* matrix, /**< constraint matrix */
1343  int* nbaserows, /**< number of present base rows */
1344  int* baserows /**< indexes of base rows */
1345  )
1346 {
1347  int nrows;
1348  int fill;
1349  int r;
1350 
1351  assert(scip != NULL);
1352  assert(matrix != NULL);
1353  assert(nbaserows != NULL);
1354  assert(baserows != NULL);
1355 
1356  nrows = SCIPmatrixGetNRows(matrix);
1357 
1358  fill = 0;
1359  for( r = 0; r < nrows; r++ )
1360  {
1361  if( !SCIPmatrixIsRowRhsInfinity(matrix, r) )
1362  continue;
1363 
1364  baserows[fill] = r;
1365  fill++;
1366  }
1367 
1368  *nbaserows = fill;
1369 
1370  return SCIP_OKAY;
1371 }
1372 
1373 /** get bounds of variables */
1374 static
1376  SCIP* scip, /**< SCIP main data structure */
1377  SCIP_MATRIX* matrix, /**< constraint matrix */
1378  SCIP_Real* lowerbds, /**< lower bounds */
1379  SCIP_Real* upperbds /**< upper bounds */
1380  )
1381 {
1382  int c;
1383  int ncols;
1384 
1385  assert(scip != NULL);
1386  assert(matrix != NULL);
1387  assert(lowerbds != NULL);
1388  assert(upperbds != NULL);
1389 
1390  ncols = SCIPmatrixGetNColumns(matrix);
1391 
1392  for( c = 0; c < ncols; c++ )
1393  {
1394  SCIP_VAR* var;
1395  var = SCIPmatrixGetVar(matrix, c);
1396  lowerbds[c] = SCIPvarGetLbGlobal(var);
1397  upperbds[c] = SCIPvarGetUbGlobal(var);
1398  }
1399 }
1400 
1401 /*
1402  * Callback methods of presolver
1403  */
1404 
1405 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1406 static
1407 SCIP_DECL_PRESOLCOPY(presolCopyTworowbnd)
1408 { /*lint --e{715}*/
1409  assert(scip != NULL);
1410  assert(presol != NULL);
1411  assert(strcmp(SCIPpresolGetName(presol), PRESOL_NAME) == 0);
1412 
1413  /* call inclusion method of presolver */
1415 
1416  return SCIP_OKAY;
1417 }
1418 
1419 /** execution method of presolver */
1420 static
1421 SCIP_DECL_PRESOLEXEC(presolExecTworowbnd)
1422 { /*lint --e{715}*/
1423  SCIP_MATRIX* matrix;
1424  SCIP_Bool initialized;
1425  SCIP_Bool complete;
1426 
1427  assert(result != NULL);
1428  *result = SCIP_DIDNOTRUN;
1429 
1431  return SCIP_OKAY;
1432 
1434  return SCIP_OKAY;
1435 
1436  *result = SCIP_DIDNOTFIND;
1437 
1438  matrix = NULL;
1439  SCIP_CALL( SCIPmatrixCreate(scip, &matrix, &initialized, &complete) );
1440 
1441  if( initialized && complete )
1442  {
1443  int* baserows;
1444  int nbaserows;
1445  int ntightenbnds;
1446  BNDCHGTYPE* tighten;
1447  int ndeletecons;
1448  SCIP_Bool* deletecons;
1449  int ncols;
1450  int nrows;
1451  SCIP_Real* lowerbds;
1452  SCIP_Real* upperbds;
1453 
1454  ncols = SCIPmatrixGetNColumns(matrix);
1455  nrows = SCIPmatrixGetNRows(matrix);
1456 
1457  ntightenbnds = 0;
1458  ndeletecons = 0;
1459 
1460  SCIP_CALL( SCIPallocBufferArray(scip, &baserows, nrows) );
1461 
1462  SCIP_CALL( SCIPallocBufferArray(scip, &tighten, ncols) );
1463  BMSclearMemoryArray(tighten, ncols);
1464 
1465  SCIP_CALL( SCIPallocBufferArray(scip, &lowerbds, ncols) );
1466  SCIP_CALL( SCIPallocBufferArray(scip, &upperbds, ncols) );
1467  getBounds(scip, matrix, lowerbds, upperbds);
1468 
1469  SCIP_CALL( SCIPallocBufferArray(scip, &deletecons, nrows) );
1470  BMSclearMemoryArray(deletecons, nrows);
1471 
1472  SCIP_CALL( getBaseRows(scip, matrix, &nbaserows, baserows) );
1473 
1474  SCIP_CALL( calcTwoRowBnds(scip, matrix,
1475  nbaserows, baserows, lowerbds, upperbds,
1476  &ntightenbnds, tighten, &ndeletecons, deletecons) );
1477 
1478  if( ntightenbnds > 0 )
1479  {
1480  int c;
1481  SCIP_VAR* var;
1482  SCIP_Bool infeas;
1483  SCIP_Bool tightened;
1484 
1485  for( c = 0; c < ncols; c++ )
1486  {
1487  if( tighten[c] == LOWERBOUND )
1488  {
1489  var = SCIPmatrixGetVar(matrix, c);
1490  SCIP_CALL( SCIPtightenVarLb(scip, var, lowerbds[c], FALSE, &infeas, &tightened) );
1491  if( tightened )
1492  ++(*nchgbds);
1493  }
1494  else if( tighten[c] == UPPERBOUND )
1495  {
1496  var = SCIPmatrixGetVar(matrix, c);
1497  SCIP_CALL( SCIPtightenVarUb(scip, var, upperbds[c], FALSE, &infeas, &tightened) );
1498  if( tightened )
1499  ++(*nchgbds);
1500  }
1501  else if( tighten[c] == BOTHBOUNDS )
1502  {
1503  var = SCIPmatrixGetVar(matrix, c);
1504  SCIP_CALL( SCIPtightenVarLb(scip, var, lowerbds[c], FALSE, &infeas, &tightened) );
1505  if( tightened )
1506  ++(*nchgbds);
1507  SCIP_CALL( SCIPtightenVarUb(scip, var, upperbds[c], FALSE, &infeas, &tightened) );
1508  if( tightened )
1509  ++(*nchgbds);
1510  }
1511  }
1512  }
1513 
1514  if( ndeletecons > 0 )
1515  {
1516  int r;
1517  for( r = 0; r < nrows; r++ )
1518  {
1519  if( deletecons[r] )
1520  {
1521  SCIP_CONS* cons;
1522  cons = SCIPmatrixGetCons(matrix, r);
1523  SCIP_CALL( SCIPdelCons(scip, cons) );
1524 
1525  (*ndelconss)++;
1526  }
1527  }
1528  }
1529 
1530  SCIPfreeBufferArray(scip, &deletecons);
1531  SCIPfreeBufferArray(scip, &upperbds);
1532  SCIPfreeBufferArray(scip, &lowerbds);
1533  SCIPfreeBufferArray(scip, &tighten);
1534  SCIPfreeBufferArray(scip, &baserows);
1535  }
1536 
1537  SCIPmatrixFree(scip, &matrix);
1538 
1539  return SCIP_OKAY;
1540 }
1541 
1542 /*
1543  * presolver specific interface methods
1544  */
1545 
1546 /** creates the tworowbnd presolver and includes it in SCIP */
1548  SCIP* scip /**< SCIP data structure */
1549  )
1550 {
1551  SCIP_PRESOL* presol;
1552 
1553  /* include presolver */
1555  PRESOL_TIMING, presolExecTworowbnd, NULL) );
1556  SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyTworowbnd) );
1557 
1558  return SCIP_OKAY;
1559 }
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
void SCIPmatrixPrintRow(SCIP *scip, SCIP_MATRIX *matrix, int row)
Definition: matrix.c:845
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1325
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition: matrix.c:1397
enum Bndchgtype BNDCHGTYPE
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:908
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11540
static void getActivities(SCIP *scip, SCIP_MATRIX *matrix, int baserow, int otherrow, int numoverlap, int *overlapidx, int *othernonoverlapidx, SCIP_Real *coefbaseoverlap, SCIP_Real *coefotheroverlap, SCIP_Real *coefothernonoverlap, SCIP_Real *lowerbds, SCIP_Real *upperbds, SCIP_Real *tmplowerbds, SCIP_Real *tmpupperbds, SCIP_Real *minratios, SCIP_Real *maxratios, int *minsortedidx, int *maxsortedidx, SCIP_Real *minact, SCIP_Real *maxact)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1525
#define NULL
Definition: lpi_spx.cpp:130
static void getOverlapBaseOrdered(SCIP *scip, SCIP_MATRIX *matrix, int baserow, int otherrow, int *countings, int *clearinfo, int numoverlap, int *olapidxbaseorder)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol, SCIP_DECL_PRESOLCOPY((*presolcopy)))
Definition: scip.c:6226
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
static SCIP_DECL_PRESOLEXEC(presolExecTworowbnd)
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition: presol.c:553
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition: matrix.c:782
static SCIP_Real getMaxResActivity(SCIP *scip, int len, int *varidxs, SCIP_Real *coefs, SCIP_Real *lowerbds, SCIP_Real *upperbds, int idx)
#define FALSE
Definition: def.h:56
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE calcTwoRowBnds(SCIP *scip, SCIP_MATRIX *matrix, int nbaserows, int *baserows, SCIP_Real *lowerbds, SCIP_Real *upperbds, int *ntightenbnds, BNDCHGTYPE *tighten, int *ndeletecons, SCIP_Bool *deletecons)
#define SCIP_CALL(x)
Definition: def.h:266
int SCIPgetNActivePricers(SCIP *scip)
Definition: scip.c:5017
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define SCIP_LONGINT_MAX
Definition: def.h:113
static SCIP_DECL_PRESOLCOPY(presolCopyTworowbnd)
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool *initialized, SCIP_Bool *complete)
Definition: matrix.c:430
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1373
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1407
SCIP_RETCODE SCIPreadProb(SCIP *scip, const char *filename, const char *extension)
Definition: scip.c:9236
Bndchgtype
static void getNumOverlap(SCIP *scip, SCIP_MATRIX *matrix, int baserow, int otherrow, int *countings, int *clearinfo, int *numoverlap, int *olapidxotherorder)
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1361
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1349
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
#define SUPPORT_THRESHOLD
#define PRESOL_MAXROUNDS
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20193
#define PRESOL_NAME
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4001
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:57
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1245
#define FASTMODE_THRESHOLD
SCIP_Bool SCIPisNLPEnabled(SCIP *scip)
Definition: scip.c:28369
public methods for matrix
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
do bound tightening by using two rows
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14503
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
#define PRESOL_TIMING
SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
Definition: matrix.c:1431
static void getCoefficients(SCIP *scip, SCIP_MATRIX *matrix, int baserow, int otherrow, int numoverlap, int *olapidxbaseorder, int *olapidxotherorder, int *othernonoverlapidx, int *basenonoverlapidx, SCIP_Real *coefbaseoverlap, SCIP_Real *coefotheroverlap, SCIP_Real *coefbasenonoverlap, SCIP_Real *coefothernonoverlap)
static SCIP_RETCODE getBaseRows(SCIP *scip, SCIP_MATRIX *matrix, int *nbaserows, int *baserows)
static void applyTightening(SCIP *scip, SCIP_MATRIX *matrix, int baserow, int otherrow, int numoverlap, int *overlapidx, int *othernonoverlapidx, int *basenonoverlapidx, SCIP_Real *coefbaseoverlap, SCIP_Real *coefotheroverlap, SCIP_Real *coefbasenonoverlap, SCIP_Real *coefothernonoverlap, SCIP_Real *lowerbds, SCIP_Real *upperbds, SCIP_Real *tmplowerbds, SCIP_Real *tmpupperbds, SCIP_Real *minratios, SCIP_Real *maxratios, int *minsortedidx, int *maxsortedidx, int *ntightenbnds, BNDCHGTYPE *tighten, int *ndeletecons, SCIP_Bool *deletecons)
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20299
#define MIN(x, y)
Definition: memory.c:67
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:35767
#define SCIPABORT()
Definition: def.h:238
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:6191
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition: matrix.c:1269
#define PRESOL_PRIORITY
static void getBounds(SCIP *scip, SCIP_MATRIX *matrix, SCIP_Real *lowerbds, SCIP_Real *upperbds)
static SCIP_Real getMaxActivity(SCIP *scip, int len, int *varidxs, SCIP_Real *coefs, SCIP_Real *lowerbds, SCIP_Real *upperbds, int *infcnt)
#define PRESOL_DESC
SCIP_RETCODE SCIPincludePresolTworowbnd(SCIP *scip)
static SCIP_Real getMinActivity(SCIP *scip, int len, int *varidxs, SCIP_Real *coefs, SCIP_Real *lowerbds, SCIP_Real *upperbds)
int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
Definition: matrix.c:1257