SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 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_tworowbnd.c
26 * @ingroup DEFPLUGINS_PRESOL
27 * @brief do bound tightening by using two rows
28 * @author Dieter Weninger
29 * @author Patrick Gemander
30 *
31 * Perform bound tightening on two inequalities with some common variables.
32 * Two possible methods are being used.
33 *
34 * 1. LP-bound
35 * Let two constraints be given:
36 * \f{eqnarray*}{
37 * A_{iR} x_R + A_{iS} x_S \geq b_i\\
38 * A_{kR} x_R + A_{kT} x_T \geq b_k
39 * \f}
40 * with \f$N\f$ the set of variable indexes, \f$R \subseteq N\f$, \f$S \subseteq N\f$, \f$T \subseteq N\f$,
41 * \f$R \cap S = \emptyset\f$, \f$R \cap T = \emptyset\f$, \f$S \cap T = \emptyset\f$ and row indices \f$i \not= k\f$.
42 *
43 * Let \f$\ell\f$ and \f$u\f$ be bound vectors for x and solve the following two LPs
44 * \f{eqnarray*}{
45 * L = \min \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i, \ell \leq x \leq u \}\\
46 * U = \max \{ A_{kR} x_R : A_{iR} x_R + A_{iS} x_S \geq b_i, \ell \leq x \leq u \}
47 * \f}
48 * and use \f$L\f$ and \f$U\f$ for getting bounds on \f$x_T\f$.
49 *
50 * If \f$L + \mbox{infimum}(A_{kT}x_T) \geq b_k\f$, then the second constraint above is redundant.
51 *
52 * More details can be found in
53 * - Chen W. et. al "Two-row and two-column mixed-integer presolve using hashing-based pairing methods"
54 */
55
56/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
57
58/*
59 * Additional debug defines in this presolver
60 * SCIP_DEBUG_HASHING
61 * SCIP_DEBUG_BOUNDS
62 * SCIP_DEBUG_SINGLEROWLP
63 */
64
65#include "scip/cons_linear.h"
66#include "scip/scipdefplugins.h"
67#include "scip/pub_matrix.h"
69
70
71#define PRESOL_NAME "tworowbnd"
72#define PRESOL_DESC "do bound tigthening by using two rows"
73#define PRESOL_PRIORITY -2000 /**< priority of the presolver (>= 0: before, < 0: after constraint handlers); combined with propagators */
74#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
75#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
76
77#define DEFAULT_ENABLECOPY TRUE /**< should tworowbnd presolver be copied to sub-SCIPs? */
78#define DEFAULT_MAXCONSIDEREDNONZEROS 100 /**< maximal number of considered non-zeros within one row (-1: no limit) */
79#define DEFAULT_MAXRETRIEVEFAILS 1000 /**< maximal number of consecutive useless hashtable retrieves */
80#define DEFAULT_MAXCOMBINEFAILS 1000 /**< maximal number of consecutive useless row combines */
81#define DEFAULT_MAXHASHFAC 10 /**< maximal number of hashlist entries as multiple of number of rows in the problem (-1: no limit) */
82#define DEFAULT_MAXPAIRFAC 1 /**< maximal number of processed row pairs as multiple of the number of rows in the problem (-1: no limit) */
83
84/*
85 * Data structures
86 */
87
88/** presolver data */
89struct SCIP_PresolData
90{
91 int maxpairfac; /**< maximal number of processed row pairs as multiple of the number of rows in the problem (-1: no limit) */
92 int maxhashfac; /**< maximal number of hashlist entries as multiple of number of rows in the problem (-1: no limit) */
93 int maxretrievefails; /**< maximal number of consecutive useless hashtable retrieves */
94 int maxcombinefails; /**< maximal number of consecutive useless row combines */
95 int maxconsiderednonzeros; /**< maximal number of considered non-zeros within one row (-1: no limit) */
96 int nchgbnds; /**< number of variable bounds changed by this presolver */
97 int nuselessruns; /**< number of runs where this presolver did not apply any changes */
98 SCIP_Bool enablecopy; /**< should tworowbnd presolver be copied to sub-SCIPs? */
99};
100
101/** structure representing a pair of row indices; used for lookup in a hashtable */
103{
104 int row1idx; /**< first row index */
105 int row2idx; /**< second row index */
106};
107
108typedef struct RowPair ROWPAIR;
109
110
111/*
112 * Local methods
113 */
114
115/** encode contents of a rowpair as void* pointer */
116static
118 ROWPAIR* rowpair /**< pointer to rowpair */
119 )
120{
121 uint64_t a = (uint64_t)(long)rowpair->row1idx;
122 uint64_t b = (uint64_t)(long)rowpair->row2idx;
123 return (void*)((a << 32) | b);
124}
125
126/** compute single positive int hashvalue for two ints */
127static
129 int idx1, /**< first integer index */
130 int idx2 /**< second integer index */
131 )
132{
133 uint32_t hash = SCIPhashTwo(idx1, idx2);
134 return (int)(hash >> 1);
135}
136
137/** add hash/rowidx pair to hashlist/rowidxlist */
138static
140 SCIP* scip, /**< SCIP datastructure */
141 int* pos, /**< position of last entry added */
142 int* listsize, /**< size of hashlist and rowidxlist */
143 int** hashlist, /**< block memory array containing hashes */
144 int** rowidxlist, /**< block memory array containing row indices */
145 int hash, /**< hash to be inserted */
146 int rowidx /**< row index to be inserted */
147 )
148{
149 if( (*pos) >= (*listsize) )
150 {
151 int newsize = SCIPcalcMemGrowSize(scip, (*pos) + 1);
152 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, hashlist, (*listsize), newsize) );
153 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, rowidxlist, (*listsize), newsize) );
154 (*listsize) = newsize;
155 }
156
157 (*hashlist)[(*pos)] = hash;
158 (*rowidxlist)[(*pos)] = rowidx;
159 (*pos)++;
160
161 return SCIP_OKAY;
162}
163
164/* Within a sorted list, get next block with same value
165 * E.g. for [h1, h1, h1, h2, h2, h2, h2, h3,...] and end = 0
166 * returns start = 0, end = 3
167 * and on a second call with end = 3 on the same list
168 * returns start = 3, end = 7.
169 */
170static
172 int* list, /**< list of integers */
173 int len, /**< length of list */
174 int* start, /**< variable to contain start index of found block */
175 int* end /**< variable to contain end index of found block */
176 )
177{
178 int i;
179 (*start) = (*end);
180 i = (*end) + 1;
181 while( i < len && list[i] == list[i - 1] )
182 i++;
183
184 (*end) = i;
185}
186
187/* Solve single-row LP of the form
188 * min c^T x
189 * s.t. a^T x >= b
190 * lbs <= x <= ubs
191 *
192 * First, the problem is transformed such that
193 * SCIPselectWeightedReal() can be applied, which
194 * then solves the problem as a continuous knapsack
195 * in linear time.
196 */
197static
199 SCIP* scip, /**< SCIP data structure */
200 SCIP_Real* a, /**< constraint coefficients */
201 SCIP_Real b, /**< right hand side */
202 SCIP_Real* c, /**< objective coefficients */
203 SCIP_Real* lbs, /**< lower variable bounds */
204 SCIP_Real* ubs, /**< upper variable bounds */
205 int len, /**< length of arrays */
206 SCIP_Real* obj, /**< objective value of solution */
207 SCIP_Bool* solvable /**< status whether LP was solvable */
208 )
209{
210 int i;
211 int k;
212 int nvars;
213 SCIP_Real lb;
214 SCIP_Real ub;
215 SCIP_Real mincost;
216 SCIP_Real maxgain;
217
218#ifdef SCIP_DEBUG_SINGLEROWLP
219 SCIPdebugMsg(scip, "solving single row LP with %d variables\n", len);
220#endif
221
222 nvars = 0;
223 (*obj) = 0;
224 (*solvable) = TRUE;
225 mincost = SCIPinfinity(scip);
226 maxgain = 0;
227 for( i = 0; i < len; i++)
228 {
229 /* Handle variables with zero weight */
230 if( SCIPisZero(scip, a[i]) )
231 {
232 /* a[i] = 0, c[i] > 0 */
233 if( SCIPisPositive(scip, c[i]) )
234 {
235 if( SCIPisInfinity(scip, -lbs[i]) )
236 {
237 (*solvable) = FALSE;
238 return SCIP_OKAY;
239 }
240 else
241 (*obj) += c[i] * lbs[i];
242 }
243 /* a[i] = 0, c[i] < 0 */
244 else if( SCIPisNegative(scip, c[i]) )
245 {
246 if( SCIPisInfinity(scip, ubs[i]) )
247 {
248 (*solvable) = FALSE;
249 return SCIP_OKAY;
250 }
251 else
252 (*obj) += c[i] * ubs[i];
253 }
254 /* Note that variables with a[i] = 0, c[i] = 0 can be ignored */
255 continue;
256 }
257
258 /* Handle free variables */
259 if( SCIPisInfinity(scip, -lbs[i]) && SCIPisInfinity(scip, ubs[i]) )
260 {
261 /* The problem is unbounded */
262 if( (SCIPisPositive(scip, c[i]) && SCIPisNegative(scip, a[i])) ||
264 {
265 (*solvable) = FALSE;
266 return SCIP_OKAY;
267 }
268 else
269 {
270 mincost = MIN(mincost, c[i] / a[i]);
271 maxgain = MAX(maxgain, c[i] / a[i]);
272 }
273 continue;
274 }
275
276 /* Swap variable orientation if lower bound is infinite */
277 if( SCIPisInfinity(scip, -lbs[i]) )
278 {
279 c[i] = -c[i];
280 a[i] = -a[i];
281 lb = -ubs[i];
282 ub = -lbs[i];
283 }
284 else
285 {
286 lb = lbs[i];
287 ub = ubs[i];
288 }
289
290 /* Handle variables with infinite upper bound */
291 if( SCIPisInfinity(scip, ub) )
292 {
293 if( SCIPisPositive(scip, a[i]) )
294 {
295 /* a[i] > 0, c[i] >= 0 */
296 if( !SCIPisNegative(scip, c[i]) )
297 {
298 mincost = MIN(mincost, c[i]/a[i]);
299 }
300 /* a[i] > 0, c[i] < 0 */
301 else
302 {
303 (*solvable) = FALSE;
304 return SCIP_OKAY;
305 }
306 }
307 /* a[i] < 0, c[i] < 0 */
308 else if( SCIPisNegative(scip, c[i]) )
309 {
310 maxgain = MAX(maxgain, c[i] / a[i]);
311 }
312 /* a[i] < 0, c[i] >= 0 results in dual fixing of this variable, which is included in the bound shift below */
313
314 /* Shift lower bound to zero */
315 if( !SCIPisZero(scip, lb) )
316 {
317 (*obj) += c[i] * lb;
318 b -= a[i] * lb;
319 }
320 continue;
321 }
322
323 /* Handle fixed variables */
324 if( SCIPisEQ(scip, lb, ub) )
325 {
326 (*obj) += c[i] * lb;
327 b -= a[i] * lb;
328 continue;
329 }
330
331 /* Dual fixing for variables with finite bounds */
332 if( !SCIPisNegative(scip, c[i]) && SCIPisNegative(scip, a[i]) )
333 {
334 (*obj) += c[i] * lb;
335 b -= a[i] * lb;
336 continue;
337 }
338 else if( !SCIPisPositive(scip, c[i]) && SCIPisPositive(scip, a[i]) )
339 {
340 (*obj) += c[i] * ub;
341 b -= a[i] * ub;
342 continue;
343 }
344
345 assert(!SCIPisInfinity(scip, -lb));
347
348 /* At this point the variable has finite bounds and a[i],c[i] are both positive or both negative.
349 * Normalize variable such that
350 * 1. x_i \in [0,1]
351 * 2. a[i] > 0
352 * 3. c[i] >= 0
353 * and calculate its "unit price" c[i]/a[i].
354 */
355 if( SCIPisNegative(scip, a[i]) )
356 {
357 c[i] = -c[i];
358 a[i] = -a[i];
359 lb = -ubs[i];
360 ub = -lbs[i];
361 }
362
363 /* All variables with a <= 0 have been handled and variables with a[i] = 0, c[i] = 0 ignored */
365
366 /* Adjust objective offset and b to shift lower bound to zero */
367 (*obj) += c[i] * lb;
368 b -= a[i] * lb;
369
370 /* Calculate unit price */
371 c[nvars] = c[i] / a[i];
372
373 /* Normalize bound [0, ub] to [0,1] */
374 a[nvars] = (ub - lb) * a[i];
375 nvars++;
376 }
377
378#ifdef SCIP_DEBUG_SINGLEROWLP
379 SCIPdebugMsg(scip, "After preprocessing: obj = %g, b = %g, nvars = %d, mincost = %g, maxgain = %g\n", (*obj), b, nvars, mincost, maxgain);
380#endif
381
382 /* Actual solving starts here.
383 * If maxgain > 0 holds, we have a variable that can relax the constraint to an arbitrary degree while yielding
384 * a certain profit per unit. This will be called downslack. If mincost < inf holds, we have a variable that can
385 * always satisfy the constraint at a certain unit price. This will be called upslack.
386 */
387
388 /* Problem is unbounded since the downslack variable yields higher gains than the upslack variable costs */
389 if( SCIPisLT(scip, mincost, maxgain) )
390 {
391 (*solvable) = FALSE;
392 return SCIP_OKAY;
393 }
394 /* Solution is trivial as we have slack variables of equal price for both directions */
395 else if( SCIPisEQ(scip, mincost, maxgain) )
396 {
397 /* Use all elements with cost smaller than maxgain */
398 for( i = 0; i < nvars; i++ )
399 {
400 if( SCIPisLT(scip, c[i], maxgain) )
401 {
402 (*obj) += c[i] * a[i];
403 b -= a[i];
404 }
405 }
406 /* Use slack variable to satisfy constraint */
407 (*obj) += mincost * b;
408 return SCIP_OKAY;
409 }
410 /* mincost > maxgain
411 * In this case we need to solve the problem for the remaining variables with mincost > c[i] > maxgain.
412 */
413 else
414 {
415 /* Only keep variables that are cheaper than the upslack variable */
416 if( !SCIPisInfinity(scip, mincost) )
417 {
418 k = 0;
419 for( i = 0; i < nvars; i++ )
420 {
421 if( SCIPisLT(scip, c[i], mincost) )
422 {
423 c[k] = c[i];
424 a[k] = a[i];
425 k++;
426 }
427 }
428 nvars = k;
429 }
430
431 /* Exploit all variables that are cheaper than the downslack variable */
432 if( !SCIPisZero(scip, maxgain) )
433 {
434 k = 0;
435 for( i = 0; i < nvars; i++ )
436 {
437 if( SCIPisLE(scip, c[i], maxgain) )
438 {
439 (*obj) += c[i] * a[i];
440 b -= a[i];
441 }
442 else
443 {
444 c[k] = c[i];
445 a[k] = a[i];
446 k++;
447 }
448 }
449 if( !SCIPisPositive(scip, b) )
450 {
451 (*obj) += maxgain * b;
452 return SCIP_OKAY;
453 }
454 nvars = k;
455 }
456
457#ifdef SCIP_DEBUG_SINGLEROWLP
458 SCIPdebugMsg(scip, "After exploiting slacks: obj = %g, nvars = %d\n", (*obj), nvars);
459#endif
460
461 /* If there are no variables left we can trivially put together a solution or determine infeasibility */
462 if( nvars == 0 )
463 {
464 if( !SCIPisInfinity(scip, mincost) )
465 {
466 (*obj) += mincost * b;
467 return SCIP_OKAY;
468 }
469 else
470 {
471 (*solvable) = FALSE;
472 return SCIP_OKAY;
473 }
474 }
475 /* Solve the remaining part of the problem */
476 else
477 {
478 assert(nvars > 0);
479#ifdef SCIP_DEBUG_SINGLEROWLP
480 for( i = 0; i < nvars; i++ )
481 SCIPdebugMsg(scip, "c[%d] = %g, a[%d] = %g\n", i, c[i], i, a[i]);
482#endif
483
485
486#ifdef SCIP_DEBUG_SINGLEROWLP
487 SCIPdebugMsg(scip, "k-mean = %g at index %d\n", c[k], k, b);
488 for( i = 0; i < nvars; i++ )
489 SCIPdebugMsg(scip, "c[%d] = %g, a[%d] = %g\n", i, c[i], i, a[i]);
490#endif
491
492 /* Finalize objective value of solution. First we use all elements cheaper than the k-median */
493 for( i = 0; i < k; i++ )
494 {
495 (*obj) += c[i] * a[i];
496 b -= a[i];
497 }
498
499#ifdef SCIP_DEBUG_SINGLEROWLP
500 SCIPdebugMsg(scip, "LP is solved: b = %g\n", b);
501#endif
502
503 /* If the constraint is not yet satisfied, we have to fix that */
504 if( SCIPisPositive(scip, b) )
505 {
506 /* There exists an element to satisfy the constraint */
507 if( k < nvars )
508 {
509 (*obj) += c[k] * b;
510 return SCIP_OKAY;
511 }
512 /* There is an upslack variable to satisfy the constraint */
513 else if( !SCIPisInfinity(scip, mincost) )
514 {
515#ifdef SCIP_DEBUG_SINGLEROWLP
516 SCIPdebugMsg(scip, "We use %g units of upslack to satisfy the constraint\n", b);
517#endif
518 (*obj) += mincost * b;
519 return SCIP_OKAY;
520 }
521 /* We cannot satisfy the constraint so the problem is infeasible */
522 else
523 {
524 (*solvable) = FALSE;
525 return SCIP_OKAY;
526 }
527 }
528 /* The constraint is already satisfied, i.e. b <= 0 */
529 else
530 {
531 return SCIP_OKAY;
532 }
533 }
534 }
535}
536
537/** Transform rows into single row LPs, solve them and and tighten bounds
538 *
539 * During transformation, create coefficient arrays where variables with a zero coefficient in both rows are ignored
540 * and bring the LP in the form min c^T x, s.t. a^T x >= b, lbs <= x <= ubs.
541 * These LPs are then solved and bounds tightened as described in LP-bound (see above).
542 */
543static
545 SCIP* scip, /**< SCIP data structure */
546 SCIP_MATRIX* matrix, /**< constraint matrix object, rows specified by row1idx/row2idx must be sorted */
547 int row1idx, /**< index of first row */
548 int row2idx, /**< index of second row */
549 SCIP_Bool swaprow1, /**< should row1 <= rhs be used in addition to lhs <= row1 */
550 SCIP_Bool swaprow2, /**< should row2 <= rhs be used in addition to lhs <= row2 */
551 SCIP_Real* aoriginal, /**< buffer array for original constraint coefficients */
552 SCIP_Real* acopy, /**< buffer array for coefficients adjusted to single-row LP to be solved */
553 SCIP_Real* coriginal, /**< buffer array for original objective coefficients */
554 SCIP_Real* ccopy, /**< buffer array for coefficients adjusted to single-row LP to be solved */
555 SCIP_Bool* cangetbnd, /**< buffer array for flags of which variables a bound can be generated */
556 SCIP_Real* lbs, /**< buffer array for lower bounds for single-row LP */
557 SCIP_Real* ubs, /**< buffer array for upper bounds for single-row LP */
558 SCIP_Real* newlbsoriginal, /**< buffer array for new lower bounds not adjusted to individual single-row LPs */
559 SCIP_Real* newlbscopy, /**< buffer array for adjusted lower bounds */
560 SCIP_Real* newubsoriginal, /**< buffer array for new upper bounds not adjusted to individual single-row LPs */
561 SCIP_Real* newubscopy, /**< buffer array for adjusted upper bounds */
562 SCIP_Bool* success, /**< return (success || "found better bounds") */
563 SCIP_Bool* infeasible /**< we return (infeasible || "detected infeasibility") */
564 )
565{
566 int i;
567 int j;
568 int idx1;
569 int idx2;
570 int row1len;
571 int row2len;
572 int* row1idxptr;
573 int* row2idxptr;
574 SCIP_Real* row1valptr;
575 SCIP_Real* row2valptr;
576 int nvars;
577 SCIP_Real minact;
578 SCIP_Real maxact;
579 int maxinfs;
580 int mininfs;
581
582 SCIP_Bool minsolvable;
584 SCIP_Bool maxsolvable;
585 SCIP_Real maxobj;
586 SCIP_Bool minswapsolvable;
587 SCIP_Real minswapobj = 0.0;
588 SCIP_Bool maxswapsolvable;
589 SCIP_Real maxswapobj;
590
591 SCIP_Real newbnd;
592
593 assert(!swaprow1 || !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, row1idx)));
594 assert(!swaprow2 || !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, row2idx)));
595
596 row1len = SCIPmatrixGetRowNNonzs(matrix, row1idx);
597 row2len = SCIPmatrixGetRowNNonzs(matrix, row2idx);
598 row1idxptr = SCIPmatrixGetRowIdxPtr(matrix, row1idx);
599 row2idxptr = SCIPmatrixGetRowIdxPtr(matrix, row2idx);
600 row1valptr = SCIPmatrixGetRowValPtr(matrix, row1idx);
601 row2valptr = SCIPmatrixGetRowValPtr(matrix, row2idx);
602
603 /* Preprocess rows:
604 * 1. Calculate minimal and maximal activity of variables not appearing in both rows,
605 * as this represents the right-hand sides of the single-row LPs to be solved.
606 * 2. Transform rows into format required by solveSingleRowLP where
607 * first row represents the objective vector c and second row represents the constraint vector a.
608 * 3. Determine for which variables new bounds can be calculated.
609 */
610 i = 0;
611 j = 0;
612 nvars = 0;
613 mininfs = 0;
614 maxinfs = 0;
615 minact = 0;
616 maxact = 0;
617 while( i < row1len && j < row2len )
618 {
619 idx1 = row1idxptr[i];
620 idx2 = row2idxptr[j];
621
622 if( idx1 == idx2 )
623 {
624 coriginal[nvars] = row1valptr[i];
625 aoriginal[nvars] = row2valptr[j];
626 newlbsoriginal[nvars] = lbs[idx1];
627 newubsoriginal[nvars] = ubs[idx1];
628 cangetbnd[idx1] = FALSE;
629 nvars++;
630#ifdef SCIP_DEBUG_2RB
631 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and %g, %d LP vars\n",
632 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
633 ubs[idx1], row1valptr[i], row2valptr[j], nvars);
634#endif
635 i++;
636 j++;
637 }
638 else if( idx1 < idx2 )
639 {
640 if( SCIPisPositive(scip, row1valptr[i]) )
641 {
642 if( SCIPisInfinity(scip, ubs[idx1]) )
643 maxinfs++;
644 else
645 maxact -= row1valptr[i] * ubs[idx1];
646
647 if( SCIPisInfinity(scip, -lbs[idx1]) )
648 mininfs++;
649 else
650 minact -= row1valptr[i] * lbs[idx1];
651 }
652 else
653 {
654 if( SCIPisInfinity(scip, -lbs[idx1]) )
655 maxinfs++;
656 else
657 maxact -= row1valptr[i] * lbs[idx1];
658
659 if( SCIPisInfinity(scip, ubs[idx1]) )
660 mininfs++;
661 else
662 minact -= row1valptr[i] * ubs[idx1];
663
664 cangetbnd[idx1] = TRUE;
665 }
666 if( maxinfs > 1 && mininfs > 1 )
667 {
668 (*success) = FALSE;
669 return SCIP_OKAY;
670 }
671 i++;
672#ifdef SCIP_DEBUG_2RB
673 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and 0.0, minact = %g, maxact = %g\n",
674 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
675 ubs[idx1], row1valptr[i], minact, maxact);
676#endif
677 }
678 else
679 {
680 coriginal[nvars] = 0.0;
681 aoriginal[nvars] = row2valptr[j];
682 newlbsoriginal[nvars] = lbs[idx2];
683 newubsoriginal[nvars] = ubs[idx2];
684 cangetbnd[idx2] = FALSE;
685 nvars++;
686#ifdef SCIP_DEBUG_2RB
687 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs 0.0 and %g, %d LP vars\n",
688 lbs[idx2], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx2)),
689 ubs[idx2], row2valptr[j], nvars);
690#endif
691 j++;
692 }
693 }
694 while( i < row1len )
695 {
696 idx1 = row1idxptr[i];
697 if( SCIPisPositive(scip, row1valptr[i]) )
698 {
699 if( SCIPisInfinity(scip, ubs[idx1]) )
700 maxinfs++;
701 else
702 maxact -= row1valptr[i] * ubs[idx1];
703
704 if( SCIPisInfinity(scip, -lbs[idx1]) )
705 mininfs++;
706 else
707 minact -= row1valptr[i] * lbs[idx1];
708 }
709 else
710 {
711 if( SCIPisInfinity(scip, -lbs[idx1]) )
712 maxinfs++;
713 else
714 maxact -= row1valptr[i] * lbs[idx1];
715
716 if( SCIPisInfinity(scip, ubs[idx1]) )
717 mininfs++;
718 else
719 minact -= row1valptr[i] * ubs[idx1];
720 }
721 cangetbnd[idx1] = TRUE;
722#ifdef SCIP_DEBUG_2RB
723 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs %g and 0.0, minact = %g, maxact = %g\n",
724 lbs[idx1], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx1)),
725 ubs[idx1], row1valptr[i], minact, maxact);
726#endif
727 i++;
728 }
729 while( j < row2len )
730 {
731 idx2 = row2idxptr[j];
732 coriginal[nvars] = 0.0;
733 aoriginal[nvars] = row2valptr[j];
734 newlbsoriginal[nvars] = lbs[idx2];
735 newubsoriginal[nvars] = ubs[idx2];
736 nvars++;
737#ifdef SCIP_DEBUG_2RB
738 SCIPdebugMsg(scip, "%g <= (%s) <= %g has coefs 0.0 and %g, %d LP vars\n",
739 lbs[idx2], SCIPvarGetName(SCIPmatrixGetVar(matrix, idx2)),
740 ubs[idx2], row2valptr[j], nvars);
741#endif
742 j++;
743 }
744
745#ifdef SCIP_DEBUG_2RB
746 SCIPdebugMsg(scip, "right hand sides: %g and %g\n",
748#endif
749
750 /* solve single-row LPs */
751 maxsolvable = FALSE;
752 minsolvable = FALSE;
753 maxswapsolvable = FALSE;
754 minswapsolvable = FALSE;
755 /* maximize overlap in first row with lhs <= row2 as constraint */
756 if( maxinfs <= 1 )
757 {
758 for( i = 0; i < nvars; i++ )
759 {
760 acopy[i] = aoriginal[i];
761 ccopy[i] = -coriginal[i];
762 newlbscopy[i] = newlbsoriginal[i];
763 newubscopy[i] = newubsoriginal[i];
764 }
766 ccopy, newlbscopy, newubscopy, nvars, &maxobj, &maxsolvable) );
767#ifdef SCIP_DEBUG_2RB
768 SCIPdebugMsg(scip, "max-LP solved: obj = %g\n", maxobj);
769#endif
770 }
771
772 /* minimize overlap in first row with lhs <= row2 as constraint */
773 if( mininfs == 0 || (mininfs == 1 && swaprow1) )
774 {
775 /* copy coefficients */
776 for( i = 0; i < nvars; i++ )
777 {
778 acopy[i] = aoriginal[i];
779 ccopy[i] = coriginal[i];
780 newlbscopy[i] = newlbsoriginal[i];
781 newubscopy[i] = newubsoriginal[i];
782 }
784 ccopy, newlbscopy, newubscopy, nvars, &minobj, &minsolvable) );
785#ifdef SCIP_DEBUG_2RB
786 SCIPdebugMsg(scip, "min-LP solved: obj = %g\n", minobj);
787#endif
788 }
789
790 if( swaprow2 )
791 {
792 /* maximize overlap in first row with row2 <= rhs as constraint */
793 if( maxinfs <= 1 )
794 {
795 /* copy coefficients */
796 for( i = 0; i < nvars; i++ )
797 {
798 acopy[i] = -aoriginal[i];
799 ccopy[i] = -coriginal[i];
800 newlbscopy[i] = newlbsoriginal[i];
801 newubscopy[i] = newubsoriginal[i];
802 }
804 ccopy, newlbscopy, newubscopy, nvars, &maxswapobj, &maxswapsolvable) );
805#ifdef SCIP_DEBUG_2RB
806 SCIPdebugMsg(scip, "maxswap-LP solved: obj = %g\n", maxswapobj);
807#endif
808 }
809
810 /* minimize overlap in first row with row2 <= rhs as constraint */
811 if( mininfs == 0 || (mininfs == 1 && swaprow1) )
812 {
813 /* copy coefficients */
814 for( i = 0; i < nvars; i++ )
815 {
816 acopy[i] = -aoriginal[i];
817 ccopy[i] = coriginal[i];
818 newlbscopy[i] = newlbsoriginal[i];
819 newubscopy[i] = newubsoriginal[i];
820 }
822 ccopy, newlbscopy, newubscopy, nvars, &minswapobj, &minswapsolvable) );
823#ifdef SCIP_DEBUG_2RB
824 SCIPdebugMsg(scip, "minswap-LP solved: obj = %g\n", minswapobj);
825#endif
826 }
827 }
828
829 /* perform bound tightening, infeasibility checks and redundancy checks */
830 if( maxinfs <= 1 && (maxsolvable || maxswapsolvable) )
831 {
832 SCIP_Real activity;
833
834 if( maxsolvable && maxswapsolvable )
835 activity = MAX(maxobj, maxswapobj) + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
836 else if( maxsolvable )
837 activity = maxobj + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
838 else
839 activity = maxswapobj + SCIPmatrixGetRowLhs(matrix, row1idx) + maxact; /*lint !e644*/
840
841 /* infeasibility check */
842 if( maxinfs == 0 && SCIPisPositive(scip, activity) )
843 {
844 (*infeasible) = TRUE;
845 (*success) = TRUE;
846 return SCIP_OKAY;
847 }
848 /* strengthen bounds of all variables outside overlap */
849 else if( maxinfs == 0 )
850 {
851 for( i = 0; i < row1len; i++ )
852 {
853 idx1 = row1idxptr[i];
854 if( cangetbnd[idx1] )
855 {
856 if( SCIPisPositive(scip, row1valptr[i]) )
857 {
858 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
859 newbnd = SCIPceil(scip, (activity + row1valptr[i] * ubs[idx1]) / row1valptr[i]);
860 else
861 newbnd = (activity + row1valptr[i] * ubs[idx1]) / row1valptr[i];
862
863 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
864 {
865#ifdef SCIP_DEBUG_BOUNDS
866 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
867 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
868#endif
869 lbs[idx1] = newbnd;
870 (*success) = TRUE;
871 }
872 }
873 else
874 {
875 assert(SCIPisNegative(scip, row1valptr[i]));
876 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
877 newbnd = SCIPfloor(scip, (activity + row1valptr[i] * lbs[idx1]) / row1valptr[i]);
878 else
879 newbnd = (activity + row1valptr[i] * lbs[idx1]) / row1valptr[i];
880
881 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
882 {
883#ifdef SCIP_DEBUG_BOUNDS
884 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
885 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
886#endif
887 ubs[idx1] = newbnd;
888 (*success) = TRUE;
889 }
890 }
891 }
892 }
893 }
894 /* strengthen bound of the single variable contributing the infinity */
895 else
896 {
897 assert(maxinfs == 1);
898 for( i = 0; i < row1len; i++ )
899 {
900 idx1 = row1idxptr[i];
901 if( cangetbnd[idx1] )
902 {
903 if( SCIPisPositive(scip, row1valptr[i]) && SCIPisInfinity(scip, ubs[idx1]) )
904 {
905 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
906 newbnd = SCIPceil(scip, activity / row1valptr[i]);
907 else
908 newbnd = activity / row1valptr[i];
909
910 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
911 {
912#ifdef SCIP_DEBUG_BOUNDS
913 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
914 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
915#endif
916 lbs[idx1] = newbnd;
917 (*success) = TRUE;
918 }
919 }
920 else if( SCIPisInfinity(scip, -lbs[idx1]) )
921 {
922 assert(SCIPisNegative(scip, row1valptr[i]));
923 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
924 newbnd = SCIPfloor(scip, activity / row1valptr[i]);
925 else
926 newbnd = activity / row1valptr[i];
927
928 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
929 {
930#ifdef SCIP_DEBUG_BOUNDS
931 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
932 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
933#endif
934 ubs[idx1] = newbnd;
935 (*success) = TRUE;
936 }
937 }
938 }
939 }
940 }
941 }
942
943 /* in this case the objective is swapped. therefore the minimum and the maximum of the support switch roles */
944 if( swaprow1 )
945 {
946 /* perform bound tightening, infeasibility checks and redundancy checks */
947 if( mininfs <= 1 && (minsolvable || minswapsolvable) )
948 {
949 SCIP_Real activity;
950
951 assert(minobj != SCIP_INVALID); /*lint !e777*/
952 if( minsolvable && minswapsolvable )
953 activity = MAX(minobj, minswapobj) - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
954 else if( minsolvable )
955 activity = minobj - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
956 else
957 activity = minswapobj - SCIPmatrixGetRowRhs(matrix, row1idx) - minact;
958
959 /* infeasibility check */
960 if( mininfs == 0 && SCIPisPositive(scip, activity) )
961 {
962 (*infeasible) = TRUE;
963 (*success) = TRUE;
964 return SCIP_OKAY;
965 }
966 /* strengthen bounds of all variables outside overlap */
967 else if( mininfs == 0 )
968 {
969 for( i = 0; i < row1len; i++ )
970 {
971 idx1 = row1idxptr[i];
972 if( cangetbnd[idx1] )
973 {
974 if( SCIPisNegative(scip, row1valptr[i]) ) /* since we look at the swapped case, this represents a positive coefficient */
975 {
976 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
977 newbnd = SCIPceil(scip, (activity - row1valptr[i] * ubs[idx1]) / (-row1valptr[i]));
978 else
979 newbnd = (activity - row1valptr[i] * ubs[idx1]) / (-row1valptr[i]);
980
981 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
982 {
983#ifdef SCIP_DEBUG_BOUNDS
984 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n",
985 lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
986#endif
987 lbs[idx1] = newbnd;
988 (*success) = TRUE;
989 }
990 }
991 else
992 {
993 /* since we look at the swapped case, this represents a negative coefficient */
994 assert(SCIPisPositive(scip, row1valptr[i]));
995 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
996 newbnd = SCIPfloor(scip, (activity - row1valptr[i] * lbs[idx1]) / (-row1valptr[i]));
997 else
998 newbnd = (activity - row1valptr[i] * lbs[idx1]) / (-row1valptr[i]);
999
1000 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
1001 {
1002#ifdef SCIP_DEBUG_BOUNDS
1003 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
1004 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
1005#endif
1006 ubs[idx1] = newbnd;
1007 (*success) = TRUE;
1008 }
1009 }
1010 }
1011 }
1012 }
1013 /* strengthen bound of the single variable contributing the infinity */
1014 else
1015 {
1016 assert(mininfs == 1);
1017 for( i = 0; i < row1len; i++ )
1018 {
1019 idx1 = row1idxptr[i];
1020 if( cangetbnd[idx1] )
1021 {
1022 /* since we look at the swapped case, this represents a positive coefficient */
1023 if( SCIPisNegative(scip, row1valptr[i]) && SCIPisInfinity(scip, ubs[idx1]) )
1024 {
1025 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
1026 newbnd = SCIPceil(scip, activity / (-row1valptr[i]));
1027 else
1028 newbnd = activity / (-row1valptr[i]);
1029
1030 if( SCIPisGT(scip, newbnd, lbs[idx1]) )
1031 {
1032#ifdef SCIP_DEBUG_BOUNDS
1033 SCIPdebugMsg(scip, "%g <= %g <= %s <= %g\n", lbs[idx1], newbnd, SCIPmatrixGetColName(matrix, idx1), ubs[idx1]);
1034#endif
1035 lbs[idx1] = newbnd;
1036 (*success) = TRUE;
1037 }
1038 }
1039 else if( SCIPisInfinity(scip, -lbs[idx1]) )
1040 {
1041 /* since we look at the swapped case, this represents a negative coefficient */
1042 assert(SCIPisPositive(scip, row1valptr[i]));
1043 if( SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, idx1)) )
1044 newbnd = SCIPfloor(scip, activity / (-row1valptr[i]));
1045 else
1046 newbnd = activity / (-row1valptr[i]);
1047
1048 if( SCIPisLT(scip, newbnd, ubs[idx1]) )
1049 {
1050#ifdef SCIP_DEBUG_BOUNDS
1051 SCIPdebugMsg(scip, "%g <= %s <= %g <= %g\n",
1052 lbs[idx1], SCIPmatrixGetColName(matrix, idx1), newbnd, ubs[idx1]);
1053#endif
1054 ubs[idx1] = newbnd;
1055 (*success) = TRUE;
1056 }
1057 }
1058 }
1059 }
1060 }
1061 }
1062 }
1063
1064 return SCIP_OKAY;
1065}
1066
1067/** create required buffer arrays and apply LP-based bound tightening in both directions */
1068static
1070 SCIP* scip, /**< SCIP data structure */
1071 SCIP_MATRIX* matrix, /**< constraint matrix object */
1072 int row1, /**< index of first row */
1073 int row2, /**< index of seond row */
1074 SCIP_Bool swaprow1, /**< should row1 <= rhs be used in addition to lhs <= row1 */
1075 SCIP_Bool swaprow2, /**< should row2 <= rhs be used in addition to lhs <= row2 */
1076 SCIP_Real* lbs, /**< lower variable bounds */
1077 SCIP_Real* ubs, /**< upper variable bounds */
1078 SCIP_Bool* success /**< return (success || "found better bounds") */
1079 )
1080{
1081 SCIP_Real* aoriginal;
1082 SCIP_Real* acopy;
1083 SCIP_Real* coriginal;
1084 SCIP_Real* ccopy;
1085 SCIP_Real* newlbsoriginal;
1086 SCIP_Real* newlbscopy;
1087 SCIP_Real* newubsoriginal;
1088 SCIP_Real* newubscopy;
1089 SCIP_Bool* cangetbnd;
1090 SCIP_Bool infeasible;
1091
1092#ifdef SCIP_DEBUG_2RB
1093 SCIPdebugMsg(scip, "combining rows %d (%s) and %d (%s)\n",
1094 row1, SCIPmatrixGetRowName(matrix, row1), row2, SCIPmatrixGetRowName(matrix, row2));
1095#endif
1096
1101 SCIP_CALL( SCIPallocBufferArray(scip, &newlbsoriginal, SCIPmatrixGetNColumns(matrix)) );
1102 SCIP_CALL( SCIPallocBufferArray(scip, &newlbscopy, SCIPmatrixGetNColumns(matrix)) );
1103 SCIP_CALL( SCIPallocBufferArray(scip, &newubsoriginal, SCIPmatrixGetNColumns(matrix)) );
1104 SCIP_CALL( SCIPallocBufferArray(scip, &newubscopy, SCIPmatrixGetNColumns(matrix)) );
1106
1107 /* Sort matrix rows */
1109 SCIPmatrixGetRowNNonzs(matrix, row1));
1111 SCIPmatrixGetRowNNonzs(matrix, row2));
1112
1113 /* Use row2 to strengthen row1 */
1114 infeasible = FALSE;
1115 SCIP_CALL( transformAndSolve(scip, matrix, row1, row2, swaprow1, swaprow2, aoriginal, acopy,
1116 coriginal, ccopy, cangetbnd, lbs, ubs, newlbsoriginal, newlbscopy,
1117 newubsoriginal, newubscopy, success, &infeasible) );
1118
1119 /* Switch roles and use row1 to strengthen row2 */
1120 SCIP_CALL( transformAndSolve(scip, matrix, row2, row1, swaprow2, swaprow1, aoriginal, acopy,
1121 coriginal, ccopy, cangetbnd, lbs, ubs, newlbsoriginal, newlbscopy,
1122 newubsoriginal, newubscopy, success, &infeasible) );
1123
1124 SCIPfreeBufferArray(scip, &cangetbnd);
1125 SCIPfreeBufferArray(scip, &newubscopy);
1126 SCIPfreeBufferArray(scip, &newubsoriginal);
1127 SCIPfreeBufferArray(scip, &newlbscopy);
1128 SCIPfreeBufferArray(scip, &newlbsoriginal);
1129 SCIPfreeBufferArray(scip, &ccopy);
1130 SCIPfreeBufferArray(scip, &coriginal);
1131 SCIPfreeBufferArray(scip, &acopy);
1132 SCIPfreeBufferArray(scip, &aoriginal);
1133
1134 return SCIP_OKAY;
1135}
1136
1137/* Find hashes contained in both hashlists, and apply LP-bound
1138 * on their corresponding rows. Both hashlists must be sorted.
1139 */
1140static
1142 SCIP* scip, /**< SCIP data structure */
1143 SCIP_PRESOLDATA* presoldata, /**< presolver data structure */
1144 SCIP_MATRIX* matrix, /**< constraint matrix object */
1145 int* hashlist1, /**< first list of hashes */
1146 int* hashlist2, /**< second list of hashes */
1147 int lenhashlist1, /**< length of first hashlist */
1148 int lenhashlist2, /**< length of second hashlist */
1149 int* rowidxlist1, /**< list of row indices corresponding to hashes in hashlist1 */
1150 int* rowidxlist2, /**< list of row indices corresponding to hashes in hashlist2 */
1151 SCIP_Real* newlbs, /**< lower variable bounds, new bounds will be written here */
1152 SCIP_Real* newubs /**< upper variable bounds, new bound will be written here */
1153 )
1154{
1155 int i;
1156 int j;
1157 int block1start;
1158 int block1end;
1159 int block2start;
1160 int block2end;
1161 SCIP_Longint maxcombines;
1162 SCIP_Bool finished;
1163 SCIP_Bool success;
1164 SCIP_Bool swaprow1;
1165 SCIP_Bool swaprow2;
1166 int ncombines;
1167 int combinefails;
1168 int retrievefails;
1169 ROWPAIR rowpair;
1170 SCIP_HASHSET* pairhashset;
1171
1172 SCIP_CALL( SCIPhashsetCreate(&pairhashset, SCIPblkmem(scip), 1) );
1173
1174 finished = FALSE;
1175 block1start = 0;
1176 block1end = 0;
1177 block2start = 0;
1178 block2end = 0;
1179 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)SCIPmatrixGetNRows(matrix)) * presoldata->maxpairfac);
1180
1181 ncombines = 0;
1182 combinefails = 0;
1183 retrievefails = 0;
1184 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
1185 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
1186 while( !finished )
1187 {
1188 if( hashlist1[block1start] == hashlist2[block2start] )
1189 {
1190 for( i = block1start; i < block1end; i++ )
1191 {
1192 for( j = block2start; j < block2end; j++ )
1193 {
1194 if( rowidxlist1[i] != rowidxlist2[j] )
1195 {
1196 rowpair.row1idx = MIN(rowidxlist1[i], rowidxlist2[j]);
1197 rowpair.row2idx = MAX(rowidxlist1[i], rowidxlist2[j]);
1198 if( !SCIPhashsetExists(pairhashset, encodeRowPair(&rowpair)) )
1199 {
1202
1203 success = FALSE;
1204
1205 /* apply lp-based bound tightening */
1206 swaprow1 = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, rowpair.row1idx));
1207 swaprow2 = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, rowpair.row2idx));
1208
1209 SCIP_CALL( applyLPboundTightening(scip, matrix, rowpair.row1idx, rowpair.row2idx,
1210 swaprow1, swaprow2, newlbs, newubs, &success) );
1211
1212 if( success )
1213 combinefails = 0;
1214 else
1215 combinefails++;
1216
1217 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeRowPair(&rowpair)) );
1218 ncombines++;
1219
1220 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
1221 finished = TRUE;
1222
1223 retrievefails = 0;
1224 }
1225 else if( retrievefails < presoldata->maxretrievefails )
1226 retrievefails++;
1227 else
1228 finished = TRUE;
1229 }
1230 /* check if SCIP ran into a time limit already */
1231 if( j % 10 == 0 && SCIPisStopped(scip) )
1232 finished = TRUE;
1233 if( finished )
1234 break;
1235 }
1236 /* check if SCIP ran into a time limit already */
1237 if( SCIPisStopped(scip) )
1238 finished = TRUE;
1239 if( finished )
1240 break;
1241 }
1242
1243 if( block1end < lenhashlist1 && block2end < lenhashlist2 )
1244 {
1245 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
1246 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
1247 }
1248 else
1249 finished = TRUE;
1250 }
1251 else if( hashlist1[block1start] < hashlist2[block2start] && block1end < lenhashlist1 )
1252 findNextBlock(hashlist1, lenhashlist1, &block1start, &block1end);
1253 else if( hashlist1[block1start] > hashlist2[block2start] && block2end < lenhashlist2 )
1254 findNextBlock(hashlist2, lenhashlist2, &block2start, &block2end);
1255 else
1256 finished = TRUE;
1257 }
1258
1259 SCIPhashsetFree(&pairhashset, SCIPblkmem(scip));
1260
1261 return SCIP_OKAY;
1262}
1263
1264
1265/*
1266 * Callback methods of presolver
1267 */
1268
1269/** copy method for constraint handler plugins (called when SCIP copies plugins) */
1270static
1271SCIP_DECL_PRESOLCOPY(presolCopyTworowbnd)
1272{
1273 SCIP_PRESOLDATA* presoldata;
1274
1275 assert(scip != NULL);
1276 assert(presol != NULL);
1277
1279
1280 /* call inclusion method of presolver if copying is enabled */
1281 presoldata = SCIPpresolGetData(presol);
1282 assert(presoldata != NULL);
1283 if( presoldata->enablecopy )
1284 {
1286 }
1287
1288 return SCIP_OKAY;
1289}
1290
1291/** destructor of presolver to free user data (called when SCIP is exiting) */
1292static
1293SCIP_DECL_PRESOLFREE(presolFreeTworowbnd)
1294{ /*lint --e{715}*/
1295 SCIP_PRESOLDATA* presoldata;
1296
1297 /* free presolver data */
1298 presoldata = SCIPpresolGetData(presol);
1299 assert(presoldata != NULL);
1300
1301 SCIPfreeBlockMemory(scip, &presoldata);
1302 SCIPpresolSetData(presol, NULL);
1303
1304 return SCIP_OKAY;
1305}
1306
1307/** initialization method of presolver (called after problem was transformed) */
1308static
1309SCIP_DECL_PRESOLINIT(presolInitTworowbnd)
1310{
1311 SCIP_PRESOLDATA* presoldata;
1312
1313 presoldata = SCIPpresolGetData(presol);
1314 presoldata->nchgbnds = 0;
1315 presoldata->nuselessruns = 0;
1316
1317 return SCIP_OKAY;
1318}
1319
1320/** execution method of presolver */
1321static
1322SCIP_DECL_PRESOLEXEC(presolExecTworowbnd)
1323{ /*lint --e{715}*/
1324 SCIP_MATRIX* matrix;
1325 SCIP_Bool initialized;
1326 SCIP_Bool complete;
1327 SCIP_Bool infeasible;
1328 SCIP_PRESOLDATA* presoldata;
1329 int oldnchgbds;
1330 int oldnfixedvars;
1331 int nrows;
1332 int ncols;
1333 SCIP_Real* oldlbs;
1334 SCIP_Real* oldubs;
1335 SCIP_Real* newlbs;
1336 SCIP_Real* newubs;
1337 int* rowidxptr;
1338 SCIP_Real* rowvalptr;
1339 SCIP_VAR* var;
1340
1341 SCIP_Longint maxhashes;
1342
1343 int maxlen;
1344 int pospp;
1345 int listsizepp;
1346 int posmm;
1347 int listsizemm;
1348 int pospm;
1349 int listsizepm;
1350 int posmp;
1351 int listsizemp;
1352
1353 int* hashlistpp;
1354 int* hashlistmm;
1355 int* hashlistpm;
1356 int* hashlistmp;
1357
1358 int* rowidxlistpp;
1359 int* rowidxlistmm;
1360 int* rowidxlistpm;
1361 int* rowidxlistmp;
1362
1363 SCIP_Bool finiterhs;
1364
1365 int i;
1366 int j;
1367 int k;
1368
1369 assert(result != NULL);
1371 infeasible = FALSE;
1372
1373 if( SCIPisStopped(scip) )
1374 return SCIP_OKAY;
1375
1376 presoldata = SCIPpresolGetData(presol);
1377 assert(presoldata != NULL);
1378
1379 if( presoldata->nuselessruns >= 5 )
1380 return SCIP_OKAY;
1381
1383
1384 matrix = NULL;
1385 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
1386 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
1387
1388 /* if infeasibility was detected during matrix creation, return here */
1389 if( infeasible )
1390 {
1391 if( initialized )
1392 SCIPmatrixFree(scip, &matrix);
1393
1395 return SCIP_OKAY;
1396 }
1397
1398 if( !initialized )
1399 return SCIP_OKAY;
1400
1401 nrows = SCIPmatrixGetNRows(matrix);
1402 ncols = SCIPmatrixGetNColumns(matrix);
1403
1404 if( nrows <= 1 )
1405 {
1406 SCIPmatrixFree(scip, &matrix);
1407 return SCIP_OKAY;
1408 }
1409
1410 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpp, nrows) );
1411 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmm, nrows) );
1412 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpm, nrows) );
1413 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmp, nrows) );
1414
1415 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistpp, nrows) );
1416 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistmm, nrows) );
1417 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistpm, nrows) );
1418 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &rowidxlistmp, nrows) );
1419
1420 pospp = 0;
1421 posmm = 0;
1422 pospm = 0;
1423 posmp = 0;
1424 listsizepp = nrows;
1425 listsizemm = nrows;
1426 listsizepm = nrows;
1427 listsizemp = nrows;
1428 maxhashes = presoldata->maxhashfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)nrows) * presoldata->maxhashfac);
1429
1430 /* skim through the problem and create hashlists for combination candidates */
1431 for( i = 0; i < nrows; i++)
1432 {
1433 if( ((SCIP_Longint)pospp) + posmm + pospm + posmp > maxhashes )
1434 break;
1435
1436 rowvalptr = SCIPmatrixGetRowValPtr(matrix, i);
1437 rowidxptr = SCIPmatrixGetRowIdxPtr(matrix, i);
1438 finiterhs = !SCIPisInfinity(scip, SCIPmatrixGetRowRhs(matrix, i));
1439 maxlen = MIN(presoldata->maxconsiderednonzeros, SCIPmatrixGetRowNNonzs(matrix, i)); /*lint !e666*/
1440 for( j = 0; j < maxlen; j++)
1441 {
1442 for( k = j+1; k < maxlen; k++)
1443 {
1444 if( SCIPisPositive(scip, rowvalptr[j]) )
1445 {
1446 if(SCIPisPositive(scip, rowvalptr[k]) )
1447 {
1448 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &rowidxlistpp,
1449 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1450 if( finiterhs )
1451 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &rowidxlistmm,
1452 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1453 }
1454 else
1455 {
1456 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &rowidxlistpm,
1457 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1458 if( finiterhs )
1459 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &rowidxlistmp,
1460 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1461 }
1462 }
1463 else
1464 {
1465 if(SCIPisPositive(scip, rowvalptr[k]) )
1466 {
1467 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &rowidxlistmp,
1468 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1469 if( finiterhs )
1470 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &rowidxlistpm,
1471 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1472 }
1473 else
1474 {
1475 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &rowidxlistmm,
1476 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1477 if( finiterhs )
1478 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &rowidxlistpp,
1479 hashIndexPair(rowidxptr[j],rowidxptr[k]), i) );
1480 }
1481 }
1482 }
1483 }
1484 }
1485
1486#ifdef SCIP_DEBUG_HASHING
1487 SCIPdebugMsg(scip, "pp\n");
1488 for( i = 0; i < pospp; i++)
1489 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpp[i], rowidxlistpp[i]);
1490 SCIPdebugMsg(scip, "mm\n");
1491 for( i = 0; i < posmm; i++)
1492 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmm[i], rowidxlistmm[i]);
1493 SCIPdebugMsg(scip, "pm\n");
1494 for( i = 0; i < pospm; i++)
1495 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpm[i], rowidxlistpm[i]);
1496 SCIPdebugMsg(scip, "mp\n");
1497 for( i = 0; i < posmp; i++)
1498 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmp[i], rowidxlistmp[i]);
1499#endif
1500 SCIPdebugMsg(scip, "hashlist sizes: pp %d, mm %d, pm %d, mp %d \n", pospp, posmm, pospm, posmp);
1501
1502 SCIPsortIntInt(hashlistpp, rowidxlistpp, pospp);
1503 SCIPsortIntInt(hashlistmm, rowidxlistmm, posmm);
1504 SCIPsortIntInt(hashlistpm, rowidxlistpm, pospm);
1505 SCIPsortIntInt(hashlistmp, rowidxlistmp, posmp);
1506
1507#ifdef SCIP_DEBUG_HASHING
1508 SCIPdebugMsg(scip, "sorted pp\n");
1509 for( i = 0; i < pospp; i++)
1510 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpp[i], rowidxlistpp[i]);
1511 SCIPdebugMsg(scip, "sorted mm\n");
1512 for( i = 0; i < posmm; i++)
1513 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmm[i], rowidxlistmm[i]);
1514 SCIPdebugMsg(scip, "sorted pm\n");
1515 for( i = 0; i < pospm; i++)
1516 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistpm[i], rowidxlistpm[i]);
1517 SCIPdebugMsg(scip, "sorted mp\n");
1518 for( i = 0; i < posmp; i++)
1519 SCIPdebugMsg(scip, "%d: hash = %d, rowidx = %d\n", i, hashlistmp[i], rowidxlistmp[i]);
1520#endif
1521
1522 SCIP_CALL( SCIPallocBufferArray(scip, &oldlbs, ncols) );
1523 SCIP_CALL( SCIPallocBufferArray(scip, &oldubs, ncols) );
1524 SCIP_CALL( SCIPallocBufferArray(scip, &newlbs, ncols) );
1525 SCIP_CALL( SCIPallocBufferArray(scip, &newubs, ncols) );
1526
1527 for( i = 0; i < SCIPmatrixGetNColumns(matrix); i++ )
1528 {
1529 var = SCIPmatrixGetVar(matrix, i);
1530 oldlbs[i] = SCIPvarGetLbLocal(var);
1531 oldubs[i] = SCIPvarGetUbLocal(var);
1532 newlbs[i] = oldlbs[i];
1533 newubs[i] = oldubs[i];
1534 }
1535
1536 /* Process pp and mm hashlists */
1537 if( pospp > 0 && posmm > 0 )
1538 {
1539 SCIPdebugMsg(scip, "processing pp and mm\n");
1540 SCIP_CALL( processHashlists(scip, presoldata, matrix, hashlistpp, hashlistmm, pospp, posmm, rowidxlistpp,
1541 rowidxlistmm, newlbs, newubs) );
1542 }
1543
1544 /* Process pm and mp hashlists */
1545 if( pospm > 0 && posmp > 0 )
1546 {
1547 SCIPdebugMsg(scip, "processing pm and mp\n");
1548 SCIP_CALL( processHashlists(scip, presoldata, matrix, hashlistpm, hashlistmp, pospm, posmp, rowidxlistpm,
1549 rowidxlistmp, newlbs, newubs) );
1550 }
1551
1552 /* Apply reductions */
1553 oldnchgbds = *nchgbds;
1554 oldnfixedvars = *nfixedvars;
1555 for( i = 0; i < SCIPmatrixGetNColumns(matrix); i++ )
1556 {
1557 SCIP_Bool bndwastightened;
1558 SCIP_Bool fixed;
1559
1560 var = SCIPmatrixGetVar(matrix, i);
1561
1563 || (SCIPisEQ(scip, newlbs[i], SCIPceil(scip, newlbs[i])) && SCIPisEQ(scip, newubs[i], SCIPfloor(scip, newubs[i]))));
1564
1565 if( SCIPisEQ(scip, newlbs[i], newubs[i]) )
1566 {
1567 SCIP_CALL( SCIPfixVar(scip, var, newlbs[i], &infeasible, &fixed) );
1568
1569 if( infeasible )
1570 {
1571 SCIPdebugMessage(" -> infeasible fixing of variable %s\n", SCIPvarGetName(var));
1572 break;
1573 }
1574
1575 if( fixed )
1576 {
1577 SCIPdebugMessage("variable %s fixed to %g\n", SCIPvarGetName(var), newlbs[i]);
1578 (*nfixedvars)++;
1579 }
1580 }
1581
1582 if( SCIPisLT(scip, oldlbs[i], newlbs[i]) )
1583 {
1584 SCIP_CALL( SCIPtightenVarLb(scip, var, newlbs[i], FALSE, &infeasible, &bndwastightened) );
1585
1586 if( infeasible )
1587 {
1588 SCIPdebugMessage(" -> infeasible lower bound tightening: %s >= %g\n", SCIPvarGetName(var), newlbs[i]);
1589 break;
1590 }
1591
1592 if( bndwastightened )
1593 {
1594 SCIPdebugMessage("lower bound of %s changed from %g to %g\n", SCIPvarGetName(var), oldlbs[i], newlbs[i]);
1595 (*nchgbds)++;
1596 }
1597 }
1598
1599 if( SCIPisGT(scip, oldubs[i], newubs[i]) )
1600 {
1601 SCIP_CALL( SCIPtightenVarUb(scip, var, newubs[i], FALSE, &infeasible, &bndwastightened) );
1602
1603 if( infeasible )
1604 {
1605 SCIPdebugMessage(" -> infeasible upper bound tightening: %s <= %g\n", SCIPvarGetName(var), newubs[i]);
1606 break;
1607 }
1608
1609 if( bndwastightened )
1610 {
1611 SCIPdebugMessage("upper bound of %s changed from %g to %g\n", SCIPvarGetName(var), oldubs[i], newubs[i]);
1612 (*nchgbds)++;
1613 }
1614 }
1615 }
1616
1617 /* set result */
1618 if( *nchgbds > oldnchgbds || *nfixedvars > oldnfixedvars )
1619 {
1621 presoldata->nuselessruns = 0;
1622 }
1623 else if( infeasible )
1624 {
1626 }
1627 else
1628 {
1629 presoldata->nuselessruns++;
1630 }
1631
1632 SCIPfreeBufferArray(scip, &newubs);
1633 SCIPfreeBufferArray(scip, &newlbs);
1634 SCIPfreeBufferArray(scip, &oldubs);
1635 SCIPfreeBufferArray(scip, &oldlbs);
1636 SCIPfreeBlockMemoryArray(scip, &rowidxlistmp, listsizemp);
1637 SCIPfreeBlockMemoryArray(scip, &rowidxlistpm, listsizepm);
1638 SCIPfreeBlockMemoryArray(scip, &rowidxlistmm, listsizemm);
1639 SCIPfreeBlockMemoryArray(scip, &rowidxlistpp, listsizepp);
1640 SCIPfreeBlockMemoryArray(scip, &hashlistmp, listsizemp);
1641 SCIPfreeBlockMemoryArray(scip, &hashlistpm, listsizepm);
1642 SCIPfreeBlockMemoryArray(scip, &hashlistmm, listsizemm);
1643 SCIPfreeBlockMemoryArray(scip, &hashlistpp, listsizepp);
1644
1645 SCIPmatrixFree(scip, &matrix);
1646
1647 return SCIP_OKAY;
1648}
1649
1650
1651/*
1652 * presolver specific interface methods
1653 */
1654
1655/** creates the tworowbndb presolver and includes it in SCIP */
1657 SCIP* scip /**< SCIP data structure */
1658 )
1659{
1660 SCIP_PRESOLDATA* presoldata;
1661 SCIP_PRESOL* presol;
1662
1663 /* create tworowbnd presolver data */
1664 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
1665
1666 presol = NULL;
1667
1668 /* include presolver */
1670 presolExecTworowbnd,
1671 presoldata) );
1672
1673 assert(presol != NULL);
1674
1675 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyTworowbnd) );
1676 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeTworowbnd) );
1677 SCIP_CALL( SCIPsetPresolInit(scip, presol, presolInitTworowbnd) );
1678
1679 /* add tworowbnd presolver parameters */
1681 "presolving/tworowbnd/enablecopy",
1682 "should tworowbnd presolver be copied to sub-SCIPs?",
1683 &presoldata->enablecopy, TRUE, DEFAULT_ENABLECOPY, NULL, NULL) );
1685 "presolving/tworowbnd/maxconsiderednonzeros",
1686 "maximal number of considered non-zeros within one row (-1: no limit)",
1687 &presoldata->maxconsiderednonzeros, FALSE, DEFAULT_MAXCONSIDEREDNONZEROS, -1, INT_MAX, NULL, NULL) );
1689 "presolving/tworowbnd/maxretrievefails",
1690 "maximal number of consecutive useless hashtable retrieves",
1691 &presoldata->maxretrievefails, FALSE, DEFAULT_MAXRETRIEVEFAILS, -1, INT_MAX, NULL, NULL) );
1693 "presolving/tworowbnd/maxcombinefails",
1694 "maximal number of consecutive useless row combines",
1695 &presoldata->maxcombinefails, FALSE, DEFAULT_MAXCOMBINEFAILS, -1, INT_MAX, NULL, NULL) );
1697 "presolving/tworowbnd/maxhashfac",
1698 "Maximum number of hashlist entries as multiple of number of rows in the problem (-1: no limit)",
1699 &presoldata->maxhashfac, FALSE, DEFAULT_MAXHASHFAC, -1, INT_MAX, NULL, NULL) );
1701 "presolving/tworowbnd/maxpairfac",
1702 "Maximum number of processed row pairs as multiple of the number of rows in the problem (-1: no limit)",
1703 &presoldata->maxpairfac, FALSE, DEFAULT_MAXPAIRFAC, -1, INT_MAX, NULL, NULL) );
1704
1705 return SCIP_OKAY;
1706}
SCIP_VAR * a
SCIP_VAR ** b
Constraint handler for linear constraints in their most general form, .
#define NULL
Definition def.h:257
#define SCIP_Longint
Definition def.h:150
#define SCIP_INVALID
Definition def.h:187
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
SCIP_Bool SCIPisStopped(SCIP *scip)
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition misc.c:3833
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition misc.c:3860
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition misc.c:3843
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition misc.c:3802
#define SCIPhashTwo(a, b)
Definition pub_misc.h:568
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:57
SCIP_RETCODE SCIPincludePresolTworowbnd(SCIP *scip)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition scip_mem.c:57
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition scip_mem.h:99
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_RETCODE SCIPsetPresolFree(SCIP *scip, SCIP_PRESOL *presol,)
void SCIPpresolSetData(SCIP_PRESOL *presol, SCIP_PRESOLDATA *presoldata)
Definition presol.c:538
SCIP_PRESOLDATA * SCIPpresolGetData(SCIP_PRESOL *presol)
Definition presol.c:528
SCIP_RETCODE SCIPsetPresolCopy(SCIP *scip, SCIP_PRESOL *presol,)
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)
SCIP_RETCODE SCIPsetPresolInit(SCIP *scip, SCIP_PRESOL *presol,)
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition presol.c:625
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6401
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23538
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:6651
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
void SCIPselectWeightedReal(SCIP_Real *realarray, SCIP_Real *weights, SCIP_Real capacity, int len, int *medianpos)
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)
return SCIP_OKAY
int c
SCIP_Real minobj
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2013
const char * SCIPmatrixGetRowName(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2025
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2047
const char * SCIPmatrixGetColName(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1965
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition matrix.c:1977
SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2059
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
Definition matrix.c:703
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition matrix.c:1897
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition matrix.c:1348
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1953
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2001
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition matrix.c:2037
#define PRESOL_NAME
#define PRESOL_PRIORITY
#define PRESOL_MAXROUNDS
#define PRESOL_TIMING
#define PRESOL_DESC
#define DEFAULT_MAXCONSIDEREDNONZEROS
#define DEFAULT_MAXHASHFAC
#define DEFAULT_MAXCOMBINEFAILS
#define DEFAULT_MAXRETRIEVEFAILS
#define DEFAULT_MAXPAIRFAC
#define DEFAULT_ENABLECOPY
static SCIP_RETCODE addEntry(SCIP *scip, int *pos, int *listsize, int **hashlist, int **rowidxlist, int hash, int rowidx)
static SCIP_RETCODE transformAndSolve(SCIP *scip, SCIP_MATRIX *matrix, int row1idx, int row2idx, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *aoriginal, SCIP_Real *acopy, SCIP_Real *coriginal, SCIP_Real *ccopy, SCIP_Bool *cangetbnd, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *newlbsoriginal, SCIP_Real *newlbscopy, SCIP_Real *newubsoriginal, SCIP_Real *newubscopy, SCIP_Bool *success, SCIP_Bool *infeasible)
static int hashIndexPair(int idx1, int idx2)
struct RowPair ROWPAIR
static SCIP_RETCODE solveSingleRowLP(SCIP *scip, SCIP_Real *a, SCIP_Real b, SCIP_Real *c, SCIP_Real *lbs, SCIP_Real *ubs, int len, SCIP_Real *obj, SCIP_Bool *solvable)
static SCIP_RETCODE processHashlists(SCIP *scip, SCIP_PRESOLDATA *presoldata, SCIP_MATRIX *matrix, int *hashlist1, int *hashlist2, int lenhashlist1, int lenhashlist2, int *rowidxlist1, int *rowidxlist2, SCIP_Real *newlbs, SCIP_Real *newubs)
static void * encodeRowPair(ROWPAIR *rowpair)
static void findNextBlock(int *list, int len, int *start, int *end)
static SCIP_RETCODE applyLPboundTightening(SCIP *scip, SCIP_MATRIX *matrix, int row1, int row2, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *success)
do bound tightening by using two rows
public methods for matrix
#define SCIPdebugMessage
Definition pub_message.h:96
default SCIP plugins
struct SCIP_Matrix SCIP_MATRIX
Definition type_matrix.h:42
struct SCIP_HashSet SCIP_HASHSET
Definition type_misc.h:112
#define SCIP_DECL_PRESOLCOPY(x)
Definition type_presol.h:60
struct SCIP_PresolData SCIP_PRESOLDATA
Definition type_presol.h:51
#define SCIP_DECL_PRESOLFREE(x)
Definition type_presol.h:68
struct SCIP_Presol SCIP_PRESOL
Definition type_presol.h:50
#define SCIP_DECL_PRESOLINIT(x)
Definition type_presol.h:76
#define SCIP_DECL_PRESOLEXEC(x)
@ 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_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166