SCIP Doxygen Documentation
Loading...
Searching...
No Matches
presol_dualinfer.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/**@file presol_dualinfer.c
25 * @ingroup DEFPLUGINS_PRESOL
26 * @brief dual inference presolver
27 * @author Dieter Weninger
28 * @author Patrick Gemander
29 *
30 * This presolver does bound strengthening on continuous variables (columns) for getting bounds on dual variables y.
31 * The bounds of the dual variables are then used to fix primal variables or change the side of constraints.
32 * For ranged rows one needs to decide which side (rhs or lhs) determines the equality.
33 *
34 * We distinguish two cases concerning complementary slackness:
35 * i) reduced cost fixing: c_j - sup_y(y^T A_{.j}) > 0 => x_j = l_j
36 * c_j - inf_y(y^T A_{.j}) < 0 => x_j = u_j
37 * ii) positive dual lower bound: y_i > 0 => A_{i.}x = b_i
38 *
39 * Further information on this presolving approach are given in
40 * Achterberg et al. "Presolve reductions in mixed integer programming"
41 * and for a two-column extension in
42 * Chen et al. "Two-row and two-column mixed-integer presolve using hasing-based pairing methods".
43 */
44
45/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
46
47#include "scip/scipdefplugins.h"
48#include "scip/pub_matrix.h"
50#include "scip/cons_linear.h"
52#include "scip/pub_cons.h"
53#include "scip/pub_matrix.h"
54#include "scip/pub_message.h"
55#include "scip/pub_presol.h"
56#include "scip/pub_var.h"
57#include "scip/scip_general.h"
58#include "scip/scip_mem.h"
59#include "scip/scip_message.h"
60#include "scip/scip_numerics.h"
61#include "scip/scip_presol.h"
62#include "scip/scip_prob.h"
63#include "scip/scip_probing.h"
64#include "scip/scip_var.h"
65
66#define PRESOL_NAME "dualinfer"
67#define PRESOL_DESC "exploit dual information for fixings and side changes"
68#define PRESOL_PRIORITY (-3000) /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */
69#define PRESOL_MAXROUNDS 0 /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */
70#define PRESOL_TIMING SCIP_PRESOLTIMING_EXHAUSTIVE /* timing of the presolver (fast, medium, or exhaustive) */
71
72#define DEFAULT_TWOCOLUMN_COMBINE TRUE /**< should two column convex combination be used per default */
73#define DEFAULT_MAXLOOPS_DUALBNDSTR 12 /**< default maximal number of loops for dual bound strengthening */
74#define DEFAULT_MAXCONSIDEREDNONZEROS 100 /**< default maximal number of considered non-zeros within one row */
75#define DEFAULT_MAXRETRIEVEFAILS 1000 /**< default maximal number of consecutive useless hashtable retrieves */
76#define DEFAULT_MAXCOMBINEFAILS 1000 /**< default maximal number of consecutive useless row combines */
77#define DEFAULT_MAXHASHFAC 10 /**< default maximal number of hashlist entries as multiple of number of rows in the problem */
78#define DEFAULT_MAXPAIRFAC 1 /**< default maximal number of processed row pairs as multiple of the number of rows in the problem */
79#define DEFAULT_MAXROWSUPPORT 3 /**< default maximal number of non-zeros in one row for turning an inequality into an equality */
80
81
82/*
83 * Data structures
84 */
85
86/** control parameters */
87struct SCIP_PresolData
88{
89 SCIP_Bool usetwocolcombine; /**< use convex combination of two columns */
90 int maxdualbndloops; /**< default number of dual bound strengthening loops */
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 maxrowsupport; /**< maximal number of non-zeros in one row for turning an inequality into an equality */
97};
98
99/** type of variable fixing direction */
101{
102 FIXATLB = -1, /** fix variable at its lower bound */
103 NOFIX = 0, /** no fixing */
104 FIXATUB = 1 /** fix variable at its upper bound */
105};
107
108/** type of constraint side change */
110{
111 RHSTOLHS = -1, /** set rhs to value of lhs */
112 NOCHANGE = 0, /** no side change */
113 LHSTORHS = 1 /** set lhs to value of rhs */
114};
116
117/** Signum for convex-combined variable coefficients \f$(\lambda * A_{ri} + (1 - \lambda) * A_{si})\f$
118 * UP - Coefficient changes from negative to positive for increasing lambda
119 * DN - Coefficient changes from positive to negative for increasing lambda
120 * POS - Coefficient is positive for all lambda in (0,1)
121 * NEG - Coefficient is negative for all lambda in (0,1)
122 */
123enum signum {UP, DN, POS, NEG};
124
125/** structure representing a pair of column indices; used for lookup in a hashtable */
127{
128 int col1idx; /**< first row index */
129 int col2idx; /**< second row index */
130};
131typedef struct ColPair COLPAIR;
132
133/*
134 * Local methods
135 */
136
137/** encode contents of a colpair as void* pointer */
138static
139void*
141 COLPAIR* colpair /**< pointer to colpair */
142 )
143{
144 uint64_t a;
145 uint64_t b;
146
147 assert(colpair->col1idx >= 0);
148 assert(colpair->col2idx >= 0);
149
150 a = (uint64_t)(long)colpair->col1idx;
151 b = (uint64_t)(long)colpair->col2idx;
152 return (void*)((a << 32) | b);
153}
154
155/** compute single positive int hashvalue for two ints */
156static
157int
159 int idx1, /**< first integer index */
160 int idx2 /**< second integer index */
161 )
162{
163 uint32_t hash = SCIPhashTwo(idx1, idx2);
164 return (int)(hash>>1);
165}
166
167/** add hash/rowidx pair to hashlist/rowidxlist **/
168static
170 SCIP* scip, /**< SCIP datastructure */
171 int* pos, /**< position of last entry added */
172 int* listsize, /**< size of hashlist and rowidxlist */
173 int** hashlist, /**< block memory array containing hashes */
174 int** colidxlist, /**< block memory array containing column indices */
175 int hash, /**< hash to be inserted */
176 int colidx /**< column index to be inserted */
177 )
178{
179 if( (*pos) >= (*listsize) )
180 {
181 int newsize = SCIPcalcMemGrowSize(scip, (*pos) + 1);
182 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, hashlist, (*listsize), newsize) );
183 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, colidxlist, (*listsize), newsize) );
184 (*listsize) = newsize;
185 }
186
187 (*hashlist)[(*pos)] = hash;
188 (*colidxlist)[(*pos)] = colidx;
189 (*pos)++;
190
191 return SCIP_OKAY;
192}
193
194/** Within a sorted list, get next block with same value
195 * E.g. for [h1, h1, h1, h2, h2, h2, h2, h3,...] and end = 0
196 * returns start = 0, end = 3
197 * and on a second call with end = 3 on the same list
198 * returns start = 3, end = 7.
199 */
200static
202 const int* list, /**< list of integers */
203 int len, /**< length of list */
204 int* start, /**< variable to contain start index of found block */
205 int* end /**< variable to contain end index of found block */
206 )
207{
208 int i;
209 (*start) = (*end);
210 i = (*end) + 1;
211 while( i < len && list[i] == list[i - 1] )
212 i++;
213
214 (*end) = i;
215}
216
217/**
218 * The algorithm described in Belotti P. "Bound reduction using pairs of linear inequalities"
219 * tries to derive upper and lower bounds for all variables via convex combinations of linear inequalities
220 * We apply Belotti's algorithm to pairs of columns of continuous variables.
221 */
222static
224 SCIP* scip, /**< SCIP datastructure */
225 int* row1idxptr, /**< indices specifying bound positions in lbs and ubs for first row */
226 int* row2idxptr, /**< indices specifying bound positions in lbs und ubs for second row */
227 SCIP_Real* row1valptr, /**< first row coefficients */
228 SCIP_Real* row2valptr, /**< second row coefficients */
229 SCIP_Real b1, /**< rhs of first row */
230 SCIP_Real b2, /**< rhs of second row*/
231 int row1len, /**< length of first row (e.g. row1idxptr and row1valptr)*/
232 int row2len, /**< length of second row (e.g. row2idxptr and row2valptr)*/
233 int ncols, /**< length of bound arrays lbs and ubs */
234 SCIP_Bool swaprow1, /**< should the sense of the first row be swapped to <= ? */
235 SCIP_Bool swaprow2, /**< should the sense of the second row be swapped to <= ? */
236 SCIP_Real* lbs, /**< lower bound array */
237 SCIP_Real* ubs, /**< upper bound array */
238 SCIP_Bool* success /**< we return (success || found better bounds") */
239 )
240{
241 int i;
242 int j;
243 int nvars;
244 int* varinds;
245 int nbreakpoints;
246 SCIP_Real* breakpoints;
247 int idx;
248 int idx1;
249 int idx2;
250 SCIP_Real* row1coefs;
251 SCIP_Real* row2coefs;
252 enum signum* signs;
253 int ninfs;
254 int l1infs;
255 SCIP_Real l1;
256 SCIP_Real l2;
257 SCIP_Real* newlbs;
258 SCIP_Real* newubs;
259 SCIP_Real coef;
260 int sign;
261 int shift;
262
263 SCIP_CALL( SCIPallocBufferArray(scip, &row1coefs, ncols) );
264 SCIP_CALL( SCIPallocBufferArray(scip, &row2coefs, ncols) );
265
266 SCIPsortIntReal(row1idxptr, row1valptr, row1len);
267 SCIPsortIntReal(row2idxptr, row2valptr, row2len);
268
269 /* swap rows if necessary */
270 if( swaprow1 )
271 {
272 for( i = 0; i < row1len; i++ )
273 row1coefs[row1idxptr[i]] = -row1valptr[i];
274 b1 = -b1;
275 }
276 else
277 {
278 for( i = 0; i < row1len; i++ )
279 row1coefs[row1idxptr[i]] = row1valptr[i];
280 }
281
282 if( swaprow2 )
283 {
284 for( i = 0; i < row2len; i++ )
285 row2coefs[row2idxptr[i]] = -row2valptr[i];
286 b2 = -b2;
287 }
288 else
289 {
290 for( i = 0; i < row2len; i++ )
291 row2coefs[row2idxptr[i]] = row2valptr[i];
292 }
293
294 SCIP_CALL( SCIPallocBufferArray(scip, &varinds, ncols) );
295 SCIP_CALL( SCIPallocBufferArray(scip, &signs, ncols) );
296 SCIP_CALL( SCIPallocBufferArray(scip, &breakpoints, ncols) );
297
298 /* calculate cancellation breakpoints and sign behaviour */
299 i = 0;
300 j = 0;
301 nvars = 0;
302 nbreakpoints = 0;
303 while( i < row1len && j < row2len )
304 {
305 assert(i + 1 == row1len || row1idxptr[i] < row1idxptr[i + 1]);
306 assert(j + 1 == row2len || row2idxptr[j] < row2idxptr[j + 1]);
307
308 idx1 = row1idxptr[i];
309 idx2 = row2idxptr[j];
310
311 /* We use 2.0 as default value for "no cancellation". For cancellations, this will be replaced by values in (0,1).
312 * A value larger than 1.0 is used because we sort the array and want to put non-cancellations to the end. */
313 breakpoints[nvars] = 2.0;
314
315 if( idx1 == idx2 )
316 {
317 if( (SCIPisNegative(scip, row1coefs[idx1]) && SCIPisPositive(scip, row2coefs[idx2])) ||
318 (SCIPisPositive(scip, row1coefs[idx1]) && SCIPisNegative(scip, row2coefs[idx2])) )
319 {
320 if( SCIPisNegative(scip, row2coefs[idx2]) )
321 signs[idx1] = UP;
322 else
323 signs[idx1] = DN;
324
325 breakpoints[nvars] = row2coefs[idx2] / (row2coefs[idx2] - row1coefs[idx1]);
326 nbreakpoints++;
327 }
328 else if( SCIPisPositive(scip, row1coefs[idx1]) )
329 signs[idx1] = POS;
330 else
331 signs[idx1] = NEG;
332
333 varinds[nvars] = idx1;
334 i++;
335 j++;
336 }
337 else if( idx1 < idx2 )
338 {
339 if( SCIPisPositive(scip, row1coefs[idx1]) )
340 signs[idx1] = POS;
341 else
342 signs[idx1] = NEG;
343
344 /* We will access this entry later on, so we explicitly write a zero here */
345 row2coefs[idx1] = 0.0;
346
347 varinds[nvars] = idx1;
348 i++;
349 }
350 else
351 {
352 assert(idx1 > idx2);
353 if( SCIPisPositive(scip, row2coefs[idx2]) )
354 signs[idx2] = POS;
355 else
356 signs[idx2] = NEG;
357
358 /* We will access this entry later on, so we explicitly write a zero here */
359 row1coefs[idx2] = 0.0;
360
361 varinds[nvars] = idx2;
362 j++;
363 }
364 nvars++;
365 }
366
367 while( i < row1len )
368 {
369 idx1 = row1idxptr[i];
370
371 if( SCIPisPositive(scip, row1coefs[idx1]) )
372 signs[idx1] = POS;
373 else
374 signs[idx1] = NEG;
375
376 /* We will access this entry later on, so we explicitly write a zero here */
377 row2coefs[idx1] = 0.0;
378
379 varinds[nvars] = idx1;
380 breakpoints[nvars] = 2.0;
381 nvars++;
382 i++;
383 }
384
385 while( j < row2len )
386 {
387 idx2 = row2idxptr[j];
388
389 if( SCIPisPositive(scip, row2coefs[idx2]) )
390 signs[idx2] = POS;
391 else
392 signs[idx2] = NEG;
393
394 /* We will access this entry later on, so we explicitly write a zero here */
395 row1coefs[idx2] = 0.0;
396
397 varinds[nvars] = idx2;
398 breakpoints[nvars] = 2.0;
399 nvars++;
400 j++;
401 }
402
403 SCIPsortRealInt(breakpoints, varinds, nvars);
404
405 /* The obvious preconditions for bound tightenings are met, so we try to calculate new bounds. */
406 if( nbreakpoints >= 1 )
407 {
410
411 for( i = 0; i < nvars; i++)
412 {
413 idx = varinds[i];
414 newlbs[i] = lbs[idx];
415 newubs[i] = ubs[idx];
416 }
417
418 /* calculate activity contributions of each row */
419 l1 = b1;
420 l2 = b2;
421 l1infs = 0;
422 ninfs = 0;
423 for( i = 0; i < nvars; i++ )
424 {
425 idx = varinds[i];
426 if( !SCIPisZero(scip, row2coefs[idx]) )
427 {
428 if( SCIPisNegative(scip, row2coefs[idx]) )
429 {
430 if( !SCIPisInfinity(scip, -lbs[idx]) )
431 {
432 l1 -= row1coefs[idx] * lbs[idx];
433 l2 -= row2coefs[idx] * lbs[idx];
434 }
435 else
436 ninfs++;
437 }
438 else
439 {
440 /* coefficient of second row is positive */
441 if( !SCIPisInfinity(scip, ubs[idx]) )
442 {
443 l1 -= row1coefs[idx] * ubs[idx];
444 l2 -= row2coefs[idx] * ubs[idx];
445 }
446 else
447 ninfs++;
448 }
449 }
450 else
451 {
452 /* since row2coefs[idx] is zero, we have to choose the bound using row1coefs[idx] */
453 assert(!SCIPisZero(scip, row1coefs[idx]) && SCIPisZero(scip, row2coefs[idx]));
454 if( SCIPisNegative(scip, row1coefs[idx]) )
455 {
456 if( !SCIPisInfinity(scip, -lbs[idx]) )
457 l1 -= row1coefs[idx] * lbs[idx];
458 else
459 l1infs++;
460 }
461 else
462 {
463 /* coefficient of first row is positive */
464 if( !SCIPisInfinity(scip, ubs[idx]) )
465 l1 -= row1coefs[idx] * ubs[idx];
466 else
467 l1infs++;
468 }
469 }
470 }
471
472 /* Calculate bounds for lambda = 0 */
473#ifdef SCIP_MORE_DEBUG
474 SCIPdebugMsg(scip, "lambda = 0, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
475#endif
476
477 if( ninfs <= 1 )
478 {
479#ifdef SCIP_MORE_DEBUG
480 SCIP_Real oldlb;
481 SCIP_Real oldub;
482#endif
483 for( i = 0; i < nvars; i++ )
484 {
485#ifdef SCIP_MORE_DEBUG
486 oldlb = newlbs[i];
487 oldub = newubs[i];
488#endif
489 idx = varinds[i];
490 if( SCIPisPositive(scip, row2coefs[idx]) )
491 {
492 if( ninfs == 0 )
493 newlbs[i] = MAX(newlbs[i], (l2 + row2coefs[idx] * ubs[idx]) / row2coefs[idx]);
494 else if( SCIPisInfinity(scip, ubs[idx]) )
495 newlbs[i] = MAX(newlbs[i], l2 / row2coefs[idx]);
496 }
497 else if ( SCIPisNegative(scip, row2coefs[idx]) )
498 {
499 if( ninfs == 0 )
500 newubs[i] = MIN(newubs[i], (l2 + row2coefs[idx] * lbs[idx]) / row2coefs[idx]);
501 else if( SCIPisInfinity(scip, -lbs[idx]) )
502 newubs[i] = MIN(newubs[i], l2 / row2coefs[idx]);
503 }
504#ifdef SCIP_MORE_DEBUG
505 if( !SCIPisEQ(scip, oldlb, newlbs[i]) || !SCIPisEQ(scip, oldub, newubs[i]) )
506 SCIPdebugMsg(scip, "%g <= %g <= var_%d <= %g <= %g\n", oldlb, newlbs[i], i, newubs[i], oldub);
507#endif
508 }
509 }
510
511 ninfs += l1infs;
512
513 i = 0;
514 while( i < nbreakpoints )
515 {
516 int nnewinfs;
517 SCIP_Real l1update;
518 SCIP_Real l2update;
519 SCIP_Bool updated;
520
521 /* determine number of infinities and compute update for l1 and l2 */
522 shift = 0;
523 nnewinfs = 0;
524 l1update = 0.0;
525 l2update = 0.0;
526 updated = FALSE;
527 j = i;
528 while( !updated )
529 {
530 idx = varinds[j];
531 assert(signs[idx] == UP || signs[idx] == DN);
532 if( signs[idx] == UP )
533 sign = 1;
534 else
535 sign = -1;
536
537 if( !SCIPisInfinity(scip, -lbs[idx]) )
538 {
539 l1update += sign * row1coefs[idx] * lbs[idx];
540 l2update += sign * row2coefs[idx] * lbs[idx];
541 }
542 else
543 {
544 if( signs[idx] == UP )
545 ninfs--;
546 else
547 nnewinfs++;
548 }
549
550 if( !SCIPisInfinity(scip, ubs[idx]) )
551 {
552 l1update -= sign * row1coefs[idx] * ubs[idx];
553 l2update -= sign * row2coefs[idx] * ubs[idx];
554 }
555 else
556 {
557 if( signs[idx] == UP )
558 nnewinfs++;
559 else
560 ninfs--;
561 }
562
563 if( signs[idx] == UP )
564 signs[idx] = POS;
565 else
566 signs[idx] = NEG;
567
568 if( j + 1 >= nbreakpoints || !SCIPisEQ(scip, breakpoints[j], breakpoints[j + 1]) )
569 updated = TRUE;
570
571 shift++;
572 j++;
573 }
574
575#ifdef SCIP_MORE_DEBUG
576 SCIPdebugMsg(scip, "lambda_%d = %g, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
577#endif
578
579 assert(ninfs >= 0);
580
581 /* if more than one infinity destroys our bounds we cannot tighten anything */
582 if( ninfs <= 1 )
583 {
584 /* check for bounds to be tightened */
585 for( j = 0; j < nvars; j++ )
586 {
587#ifdef SCIP_MORE_DEBUG
588 SCIP_Real oldlb = newlbs[j];
589 SCIP_Real oldub = newubs[j];
590#endif
591
592 idx = varinds[j];
593 coef = breakpoints[i] * row1coefs[idx] + (1 - breakpoints[i]) * row2coefs[idx];
594 assert(!SCIPisEQ(scip, breakpoints[i], 2.0));
595
596 /* skip if the coefficient is too close to zero as it becomes numerically unstable */
597 if( SCIPisZero(scip, coef) )
598 continue;
599
600 if( signs[idx] == POS || signs[idx] == DN )
601 {
602 if( ninfs == 0 )
603 newlbs[j] = MAX(newlbs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2 + coef * ubs[idx]) / coef);
604 else if( SCIPisInfinity(scip, ubs[idx]) )
605 newlbs[j] = MAX(newlbs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2) / coef);
606 }
607 else if ( signs[idx] == NEG || signs[idx] == UP )
608 {
609 if( ninfs == 0 )
610 newubs[j] = MIN(newubs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2 + coef * lbs[idx]) / coef);
611 else if( SCIPisInfinity(scip, -lbs[idx]) )
612 newubs[j] = MIN(newubs[j], (breakpoints[i] * l1 + (1 - breakpoints[i]) * l2) / coef);
613 }
614#ifdef SCIP_MORE_DEBUG
615 if( !SCIPisEQ(scip, oldlb, newlbs[j]) || !SCIPisEQ(scip, oldub, newubs[j]) )
616 SCIPdebugMsg(scip, "%g <= %g <= var_%d <= %g <= %g\n", oldlb, newlbs[j], j, newubs[j], oldub);
617#endif
618 }
619 }
620
621 i += shift;
622 ninfs += nnewinfs;
623 l1 += l1update;
624 l2 += l2update;
625 }
626
627 /* check infinities in first row */
628 ninfs = 0;
629 for( i = 0; i < nvars; i++ )
630 {
631 idx = varinds[i];
632 if( (SCIPisPositive(scip, row1coefs[idx]) && SCIPisInfinity(scip, ubs[idx]))
633 || (SCIPisNegative(scip, row1coefs[idx]) && SCIPisInfinity(scip, -lbs[idx])) )
634 ninfs++;
635 }
636
637 /* calculate bounds for lambda = 1 */
638#ifdef SCIP_MORE_DEBUG
639 SCIPdebugMsg(scip, "lambda = 1, l1 = %g, l2 = %g, ninfs = %d\n", i, breakpoints[i], l1, l2, ninfs);
640#endif
641 if( ninfs <= 1 )
642 {
643#ifdef SCIP_MORE_DEBUG
644 SCIP_Real oldlb;
645 SCIP_Real oldub;
646#endif
647 for( i = 0; i < nvars; i++ )
648 {
649#ifdef SCIP_MORE_DEBUG
650 oldlb = newlbs[i];
651 oldub = newubs[i];
652#endif
653 idx = varinds[i];
654 if( SCIPisPositive(scip, row1coefs[idx]) )
655 {
656 if( ninfs == 0 )
657 newlbs[i] = MAX(newlbs[i], (l1 + row1coefs[idx] * ubs[idx]) / row1coefs[idx]);
658 else if( SCIPisInfinity(scip, ubs[idx]) )
659 newlbs[i] = MAX(newlbs[i], l1 / row1coefs[idx]);
660 }
661 else if ( SCIPisNegative(scip, row1coefs[idx]) )
662 {
663 if( ninfs == 0 )
664 newubs[i] = MIN(newubs[i], (l1 + row1coefs[idx] * lbs[idx]) / row1coefs[idx]);
665 else if( SCIPisInfinity(scip, -lbs[idx]) )
666 newubs[i] = MIN(newubs[i], l1 / row1coefs[idx]);
667 }
668#ifdef SCIP_MORE_DEBUG
669 if( !SCIPisEQ(scip, oldlb, newlbs[i]) || !SCIPisEQ(scip, oldub, newubs[i]) )
670 SCIPdebugMsg(scip, "%g <= %g <= var_%i <= %g <= %g\n", oldlb, newlbs[i], i, newubs[i], oldub);
671#endif
672 }
673 }
674
675 /* update bound arrays and determine success */
676 for( i = 0; i < nvars; i++ )
677 {
678 idx = varinds[i];
679
680 assert(SCIPisLE(scip, lbs[idx], newlbs[i]));
681 assert(SCIPisGE(scip, ubs[idx], newubs[i]));
682
683 if( SCIPisGT(scip, newlbs[i], lbs[idx]) || SCIPisLT(scip, newubs[i], ubs[idx]) )
684 {
685 (*success) = TRUE;
686
687 lbs[idx] = newlbs[i];
688 ubs[idx] = newubs[i];
689 }
690 }
691 SCIPfreeBufferArray(scip, &newubs);
692 SCIPfreeBufferArray(scip, &newlbs);
693 }
694
695 SCIPfreeBufferArray(scip, &breakpoints);
696 SCIPfreeBufferArray(scip, &signs);
697 SCIPfreeBufferArray(scip, &varinds);
698 SCIPfreeBufferArray(scip, &row2coefs);
699 SCIPfreeBufferArray(scip, &row1coefs);
700
701 return SCIP_OKAY;
702}
703
704/** get minimal and maximal residual activities without one specific column */
705static
707 SCIP* scip, /**< SCIP main data structure */
708 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
709 int withoutcol, /**< exclude this column index */
710 int row, /**< row index */
711 SCIP_Real* lbs, /**< lower bounds */
712 SCIP_Real* ubs, /**< upper bounds */
713 SCIP_Real* minresactivity, /**< minimum residual activity of this row */
714 SCIP_Real* maxresactivity, /**< maximum residual activity of this row */
715 SCIP_Bool* isminsettoinfinity, /**< flag indicating if minresactiviy is set to infinity */
716 SCIP_Bool* ismaxsettoinfinity /**< flag indicating if maxresactiviy is set to infinity */
717 )
718{
719 SCIP_Real coef;
720 int* rowpnt;
721 int* rowend;
722 SCIP_Real* valpnt;
723 int nmaxactneginf;
724 int nmaxactposinf;
725 int nminactneginf;
726 int nminactposinf;
727 SCIP_Real maxresact;
728 SCIP_Real minresact;
729 int col;
730
731 assert(scip != NULL);
732 assert(matrix != NULL);
733 assert(minresactivity != NULL);
734 assert(maxresactivity != NULL);
735 assert(isminsettoinfinity != NULL);
736 assert(ismaxsettoinfinity != NULL);
737
738 *isminsettoinfinity = FALSE;
739 *ismaxsettoinfinity = FALSE;
740
741 nmaxactneginf = 0;
742 nmaxactposinf = 0;
743 nminactneginf = 0;
744 nminactposinf = 0;
745 maxresact = 0;
746 minresact = 0;
747
748 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
749 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
750 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
751
752 for( ; rowpnt < rowend; rowpnt++, valpnt++ )
753 {
754 col = *rowpnt;
755
756 if( col == withoutcol )
757 continue;
758
759 coef = *valpnt;
760
761 /* positive coefficient */
762 if( coef > 0.0 )
763 {
764 if( SCIPisInfinity(scip, ubs[col]) )
765 nmaxactposinf++;
766 else
767 maxresact += coef * ubs[col];
768
769 if( SCIPisInfinity(scip, -lbs[col]) )
770 nminactneginf++;
771 else
772 minresact += coef * lbs[col];
773 }
774 else /* negative coefficient */
775 {
776 if( SCIPisInfinity(scip, -lbs[col]) )
777 nmaxactneginf++;
778 else
779 maxresact += coef * lbs[col];
780
781 if( SCIPisInfinity(scip, ubs[col]) )
782 nminactposinf++;
783 else
784 minresact += coef * ubs[col];
785 }
786 }
787
788 if( (nmaxactneginf + nmaxactposinf) > 0 )
789 *ismaxsettoinfinity = TRUE;
790 else
791 *maxresactivity = maxresact;
792
793 if( (nminactneginf + nminactposinf) > 0 )
794 *isminsettoinfinity = TRUE;
795 else
796 *minresactivity = minresact;
797}
798
799/** calculate the upper and lower bound of one variable from one row */
800static
802 SCIP* scip, /**< SCIP main data structure */
803 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
804 int col, /**< column index of variable */
805 int row, /**< row index */
806 SCIP_Real val, /**< coefficient of this column in this row */
807 SCIP_Real* lbs, /**< lower bounds */
808 SCIP_Real* ubs, /**< upper bounds */
809 SCIP_Real* rowub, /**< upper bound of row */
810 SCIP_Bool* ubfound, /**< flag indicating that an upper bound was calculated */
811 SCIP_Real* rowlb, /**< lower bound of row */
812 SCIP_Bool* lbfound /**< flag indicating that a lower bound was caluclated */
813 )
814{
815 SCIP_Bool isminsettoinfinity;
816 SCIP_Bool ismaxsettoinfinity;
817 SCIP_Real minresactivity;
818 SCIP_Real maxresactivity;
819 SCIP_Real lhs;
820 SCIP_Real rhs;
821
822 assert(rowub != NULL);
823 assert(ubfound != NULL);
824 assert(rowlb != NULL);
825 assert(lbfound != NULL);
826
827 *rowub = SCIPinfinity(scip);
828 *ubfound = FALSE;
829 *rowlb = -SCIPinfinity(scip);
830 *lbfound = FALSE;
831
832 getMinMaxActivityResiduals(scip, matrix, col, row, lbs, ubs,
833 &minresactivity, &maxresactivity,
834 &isminsettoinfinity, &ismaxsettoinfinity);
835
836 lhs = SCIPmatrixGetRowLhs(matrix, row);
837 rhs = SCIPmatrixGetRowRhs(matrix, row);
838
839 if( val > 0.0 )
840 {
841 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
842 {
843 *rowub = (rhs - minresactivity) / val; // maybe one wants some kind of numerical guard of check that values is not too small for all these
844 *ubfound = TRUE;
845 }
846
847 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
848 {
849 *rowlb = (lhs - maxresactivity) / val;
850 *lbfound = TRUE;
851 }
852 }
853 else
854 {
855 if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) )
856 {
857 *rowub = (lhs - maxresactivity) / val;
858 *ubfound = TRUE;
859 }
860
861 if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) )
862 {
863 *rowlb = (rhs - minresactivity) / val;
864 *lbfound = TRUE;
865 }
866 }
867}
868
869
870/** detect implied variable bounds */
871static
873 SCIP* scip, /**< SCIP main data structure */
874 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
875 int col, /**< column index for implied free test */
876 SCIP_Real* lbs, /**< lower bounds */
877 SCIP_Real* ubs, /**< upper bounds */
878 SCIP_Bool* ubimplied, /**< flag indicating an implied upper bound */
879 SCIP_Bool* lbimplied /**< flag indicating an implied lower bound */
880 )
881{
882 SCIP_Real impliedub;
883 SCIP_Real impliedlb;
884 int* colpnt;
885 int* colend;
886 SCIP_Real* valpnt;
887
888 assert(scip != NULL);
889 assert(matrix != NULL);
890 assert(lbs != NULL);
891 assert(ubs != NULL);
892 assert(ubimplied != NULL);
893 assert(lbimplied != NULL);
894
895 *ubimplied = FALSE;
896 impliedub = SCIPinfinity(scip);
897
898 *lbimplied = FALSE;
899 impliedlb = -SCIPinfinity(scip);
900
901 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
902 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
903 valpnt = SCIPmatrixGetColValPtr(matrix, col);
904 for( ; (colpnt < colend); colpnt++, valpnt++ )
905 {
906 SCIP_Real rowub;
907 SCIP_Bool ubfound;
908 SCIP_Real rowlb;
909 SCIP_Bool lbfound;
910
911 getVarBoundsOfRow(scip, matrix, col, *colpnt, *valpnt, lbs, ubs,
912 &rowub, &ubfound, &rowlb, &lbfound);
913
914 if( ubfound && (rowub < impliedub) )
915 impliedub = rowub;
916
917 if( lbfound && (rowlb > impliedlb) )
918 impliedlb = rowlb;
919 }
920
921 /* we consider +/-inf bounds as implied bounds */
922 if( SCIPisInfinity(scip, ubs[col]) ||
923 (!SCIPisInfinity(scip, ubs[col]) && SCIPisLE(scip, impliedub, ubs[col])) )
924 *ubimplied = TRUE;
925
926 if( SCIPisInfinity(scip, -lbs[col]) ||
927 (!SCIPisInfinity(scip, -lbs[col]) && SCIPisGE(scip, impliedlb, lbs[col])) )
928 *lbimplied = TRUE;
929}
930
931
932/** calculate minimal column activity from one variable without one row */
933static
935 SCIP* scip, /**< SCIP main data structure */
936 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
937 int col, /**< column index */
938 int withoutrow, /**< exclude this row index */
939 SCIP_Real* lbdual, /**< lower bounds of dual variables */
940 SCIP_Real* ubdual /**< upper bounds of dual variables */
941 )
942{
943 SCIP_Real* valpnt;
944 int* colpnt;
945 int* colend;
946 SCIP_Real val;
947 SCIP_Real mincolactivity;
948 int row;
949
950 assert(scip != NULL);
951 assert(matrix != NULL);
952 assert(lbdual != NULL);
953 assert(ubdual != NULL);
954
955 mincolactivity = 0;
956
957 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
958 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
959 valpnt = SCIPmatrixGetColValPtr(matrix, col);
960
961 for( ; colpnt < colend; colpnt++, valpnt++ )
962 {
963 row = *colpnt;
964 val = *valpnt;
965
966 if( row == withoutrow )
967 continue;
968
969 if( val > 0.0 )
970 {
971 assert(!SCIPisInfinity(scip, -lbdual[row]));
972 mincolactivity += val * lbdual[row];
973 }
974 else if( val < 0.0 )
975 {
976 assert(!SCIPisInfinity(scip, ubdual[row]));
977 mincolactivity += val * ubdual[row];
978 }
979 }
980
981 return mincolactivity;
982}
983
984
985/** In the primal the residual activity of a constraint w.r.t. a variable is the activity of the constraint without the variable.
986 * This function does the same but in the dual.
987 * It computes the residual activity of column 'col' w.r.t. variable 'row'
988 */
989static
991 SCIP* scip, /**< SCIP main data structure */
992 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
993 int col, /**< column index */
994 int row, /**< row index */
995 SCIP_Real val, /**< matrix coefficient */
996 SCIP_Real* lbdual, /**< lower bounds of the dual variables */
997 SCIP_Real* ubdual, /**< upper bounds of the dual variables */
998 const SCIP_Real* mincolact, /**< minimal column activities */
999 const int* mincolactinf, /**< number of infinite contributions to minimal column activity */
1000 SCIP_Real* mincolresact /**< minimal residual column activity */
1001 )
1002{
1003 assert(scip != NULL);
1004 assert(matrix != NULL);
1005 assert(lbdual != NULL);
1006 assert(ubdual != NULL);
1007 assert(mincolact != NULL);
1008 assert(mincolactinf != NULL);
1009 assert(mincolresact != NULL);
1010
1011 *mincolresact = -SCIPinfinity(scip);
1012
1013 if( val > 0.0 )
1014 {
1015 if( SCIPisInfinity(scip, -lbdual[row]) )
1016 {
1017 assert(mincolactinf[col] >= 1);
1018 if( mincolactinf[col] == 1 )
1019 *mincolresact = getMinColActWithoutRow(scip, matrix, col, row, lbdual, ubdual);
1020 else
1021 *mincolresact = -SCIPinfinity(scip);
1022 }
1023 else
1024 {
1025 if( mincolactinf[col] > 0 )
1026 *mincolresact = -SCIPinfinity(scip);
1027 else
1028 *mincolresact = mincolact[col] - val * lbdual[row];
1029 }
1030 }
1031 else if( val < 0.0 )
1032 {
1033 if( SCIPisInfinity(scip, ubdual[row]) )
1034 {
1035 assert(mincolactinf[col] >= 1);
1036 if( mincolactinf[col] == 1 )
1037 *mincolresact = getMinColActWithoutRow(scip, matrix, col, row, lbdual, ubdual);
1038 else
1039 *mincolresact = -SCIPinfinity(scip);
1040 }
1041 else
1042 {
1043 if( mincolactinf[col] > 0 )
1044 *mincolresact = -SCIPinfinity(scip);
1045 else
1046 *mincolresact = mincolact[col] - val * ubdual[row];
1047 }
1048 }
1049}
1050
1051/** calculate minimal column activity of one column */
1052static
1054 SCIP* scip, /**< SCIP main data structure */
1055 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1056 int col, /**< column for activity calculations */
1057 SCIP_Real* lbdual, /**< lower bounds of dual variables */
1058 SCIP_Real* ubdual, /**< upper bounds of dual variables */
1059 SCIP_Real* mincolact, /**< minimal column activities */
1060 int* mincolactinf /**< number of -inf contributions to minimal column activity */
1061 )
1062{
1063 SCIP_Real* valpnt;
1064 int* colpnt;
1065 int* colend;
1066 SCIP_Real val;
1067 int row;
1068
1069 assert(scip != NULL);
1070 assert(matrix != NULL);
1071 assert(lbdual != NULL);
1072 assert(ubdual != NULL);
1073 assert(mincolact != NULL);
1074 assert(mincolactinf != NULL);
1075
1076 /* init activities */
1077 mincolact[col] = 0.0;
1078 mincolactinf[col] = 0;
1079
1080 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
1081 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
1082 valpnt = SCIPmatrixGetColValPtr(matrix, col);
1083
1084 /* calculate column activities */
1085 for( ; colpnt < colend; colpnt++, valpnt++ )
1086 {
1087 row = *colpnt;
1088 val = *valpnt;
1089
1090 if( val > 0.0 )
1091 {
1092 if(SCIPisInfinity(scip, -lbdual[row]))
1093 mincolactinf[col]++;
1094 else
1095 mincolact[col] += val * lbdual[row];
1096 }
1097 else if( val < 0.0 )
1098 {
1099 if(SCIPisInfinity(scip, ubdual[row]))
1100 mincolactinf[col]++;
1101 else
1102 mincolact[col] += val * ubdual[row];
1103 }
1104 }
1105
1106 /* update column activities if infinity counters are greater 0 */
1107 if( mincolactinf[col] > 0 )
1108 mincolact[col] = -SCIPinfinity(scip);
1109}
1110
1111/** calculate maximal column activity of one column */
1112static
1114 SCIP* scip, /**< SCIP main data structure */
1115 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1116 int col, /**< column for activity calculations */
1117 SCIP_Real* lbdual, /**< lower bounds of dual variables */
1118 SCIP_Real* ubdual, /**< upper bounds of dual variables */
1119 SCIP_Real* maxcolact, /**< minimal column activities */
1120 int* maxcolactinf /**< number of -inf contributions to minimal column activity */
1121 )
1122{
1123 SCIP_Real* valpnt;
1124 int* colpnt;
1125 int* colend;
1126 SCIP_Real val;
1127 int row;
1128
1129 assert(scip != NULL);
1130 assert(matrix != NULL);
1131 assert(lbdual != NULL);
1132 assert(ubdual != NULL);
1133 assert(maxcolact != NULL);
1134 assert(maxcolactinf != NULL);
1135
1136 /* init activities */
1137 maxcolact[col] = 0.0;
1138 maxcolactinf[col] = 0;
1139
1140 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
1141 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
1142 valpnt = SCIPmatrixGetColValPtr(matrix, col);
1143
1144 /* calculate column activities */
1145 for( ; colpnt < colend; colpnt++, valpnt++ )
1146 {
1147 row = *colpnt;
1148 val = *valpnt;
1149
1150 if( val > 0.0 )
1151 {
1152 if(SCIPisInfinity(scip, ubdual[row]))
1153 maxcolactinf[col]++;
1154 else
1155 maxcolact[col] += val * ubdual[row];
1156 }
1157 else if( val < 0.0 )
1158 {
1159 if(SCIPisInfinity(scip, -lbdual[row]))
1160 maxcolactinf[col]++;
1161 else
1162 maxcolact[col] += val * lbdual[row];
1163 }
1164 }
1165
1166 /* update column activities if infinity counters are greater 0 */
1167 if( maxcolactinf[col] > 0 )
1168 maxcolact[col] = SCIPinfinity(scip);
1169}
1170
1171
1172/** update minimal/maximal column activity infinity counters */
1173static
1175 SCIP* scip, /**< SCIP main data structure */
1176 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1177 int row, /**< row index */
1178 SCIP_Real* lbdual, /**< lower bounds of dual variables */
1179 SCIP_Real* ubdual, /**< upper bounds of dual variables */
1180 const SCIP_Bool* isubimplied, /**< flags indicating of the upper bound is implied */
1181 SCIP_Real* mincolact, /**< minimal column activities */
1182 int* mincolactinf, /**< number of infinity contributions to minimal column activity */
1183 SCIP_Bool ubinfchange, /**< flag indicating if the upper bound has changed from infinity to a finite value */
1184 SCIP_Bool lbinfchange /**< flag indicating if the lower bound has changed from -infinity to a finite value */
1185 )
1186{
1187 SCIP_Real* valpnt;
1188 int* rowpnt;
1189 int* rowend;
1190 SCIP_Real val;
1191 int col;
1192
1193 rowpnt = SCIPmatrixGetRowIdxPtr(matrix, row);
1194 rowend = rowpnt + SCIPmatrixGetRowNNonzs(matrix, row);
1195 valpnt = SCIPmatrixGetRowValPtr(matrix, row);
1196
1197 /* look at all column entries present within row and update the
1198 * corresponding infinity counters. if one counter gets to zero,
1199 * then calculate this column activity new.
1200 */
1201
1202 for(; (rowpnt < rowend); rowpnt++, valpnt++ )
1203 {
1204 col = *rowpnt;
1205 val = *valpnt;
1206
1207 if( isubimplied[col] )
1208 {
1209 if( val < 0 )
1210 {
1211 if( ubinfchange )
1212 {
1213 assert(mincolactinf[col] > 0);
1214 mincolactinf[col]--;
1215 }
1216 }
1217 else if( val > 0 )
1218 {
1219 if( lbinfchange )
1220 {
1221 assert(mincolactinf[col] > 0);
1222 mincolactinf[col]--;
1223 }
1224 }
1225
1226 if( mincolactinf[col] == 0 )
1227 calcMinColActivity(scip, matrix, col, lbdual, ubdual, mincolact, mincolactinf);
1228 }
1229 }
1230}
1231
1232#ifdef SCIP_DEBUG
1233/** use LP calculations for determining the best dual variable bounds from a specific row index */
1234static
1236 SCIP* scip, /**< SCIP main data structure */
1237 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1238 int row, /**< row index for dual bound calculations */
1239 SCIP_Bool solveLP, /**< flag indicating to solve subscip LP */
1240 SCIP_Real* lowerbnddual, /**< lower bound of dual variable */
1241 SCIP_Real* upperbnddual /**< upper bound of dual variable */
1242 )
1243{
1244 int i;
1245 int nrows;
1246 int ncols;
1247 int numberconvars;
1248 SCIP_VAR* var;
1249 SCIP_VAR** variables;
1250 SCIP_VAR** tmpvars;
1251 SCIP_Real* tmpcoef;
1252 SCIP_CONS** constraints;
1253 int numDualVars;
1254 SCIP* subscip;
1255 SCIP_RETCODE retcode;
1256 char name[SCIP_MAXSTRLEN+3];
1257 int fillcnt;
1258 int* colpnt;
1259 int* colend;
1260 SCIP_Real* valpnt;
1261 int* colmap;
1262
1263 *lowerbnddual = -SCIPinfinity(scip);
1264 *upperbnddual = SCIPinfinity(scip);
1265
1266 nrows = SCIPmatrixGetNRows(matrix);
1267 assert(0 <= row && row < nrows);
1268 ncols = SCIPmatrixGetNColumns(matrix);
1269
1270 SCIP_CALL( SCIPcreate(&subscip) );
1271 SCIP_CALL( SCIPcreateProbBasic(subscip, "subscip") );
1273
1274 /* avoid recursive calls */
1275 SCIP_CALL( SCIPsetIntParam(subscip, "presolving/dualinfer/maxrounds", 0) );
1276 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
1277 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", TRUE) );
1278
1279 SCIP_CALL( SCIPallocBufferArray(scip, &colmap, ncols) );
1280 numberconvars = 0;
1281 for(i = 0; i < ncols; i++)
1282 {
1283 var = SCIPmatrixGetVar(matrix, i);
1285 {
1286 colmap[i] = numberconvars; /* start numbering with 0 */
1287 numberconvars++;
1288 }
1289 else
1290 colmap[i] = -1;
1291 }
1292 numDualVars = nrows + 2 * numberconvars;
1293
1294 /* create dual variables */
1295 SCIP_CALL( SCIPallocBufferArray(scip, &variables, numDualVars) );
1296 for( i = 0; i < nrows; i++ )
1297 {
1298 variables[i] = NULL;
1299 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "y%d", i);
1300 if( !SCIPmatrixIsRowRhsInfinity(matrix, i ) )
1301 {
1302 /* dual variable for equation or ranged row */
1303 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[i], name,
1305 }
1306 else
1307 {
1308 /* dual variable for >= inequality */
1309 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[i], name,
1311 }
1312 SCIP_CALL( SCIPaddVar(subscip, variables[i]) );
1313 assert( variables[i] != NULL );
1314 }
1315
1316 /* in addition, we introduce dual variables for the bounds,
1317 because we treat each continuous variable as a free variable */
1318 fillcnt = nrows;
1319 for( i = 0; i < numberconvars; i++ )
1320 {
1321 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ylb%d", fillcnt);
1322 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[fillcnt], name,
1324 SCIP_CALL( SCIPaddVar(subscip, variables[fillcnt]) );
1325 assert( variables[fillcnt] != NULL );
1326 fillcnt++;
1327
1328 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "yub%d", fillcnt);
1329 SCIP_CALL( SCIPcreateVarBasic(subscip, &variables[fillcnt], name,
1331 SCIP_CALL( SCIPaddVar(subscip, variables[fillcnt]) );
1332 assert( variables[fillcnt] != NULL );
1333 fillcnt++;
1334 }
1335 assert(numDualVars == fillcnt);
1336
1337 SCIP_CALL( SCIPallocBufferArray(scip, &tmpvars, numDualVars) );
1338 SCIP_CALL( SCIPallocBufferArray(scip, &tmpcoef, numDualVars) );
1339
1340 SCIP_CALL( SCIPallocBufferArray(scip, &constraints, numberconvars) );
1341 for( i = 0; i <numberconvars; i++)
1342 constraints[i] = NULL;
1343
1344 for(i = 0; i < ncols; i++)
1345 {
1346 var = SCIPmatrixGetVar(matrix, i);
1348 {
1350 int cidx = colmap[i];
1351 assert(0 <= cidx && cidx < numberconvars);
1352
1353 colpnt = SCIPmatrixGetColIdxPtr(matrix, i);
1354 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, i);
1355 valpnt = SCIPmatrixGetColValPtr(matrix, i);
1356 fillcnt = 0;
1357 for( ; colpnt < colend; colpnt++, valpnt++ )
1358 {
1359 assert(0 <= *colpnt && *colpnt < nrows);
1360 assert(variables[*colpnt] != NULL);
1361 tmpvars[fillcnt] = variables[*colpnt];
1362 tmpcoef[fillcnt] = *valpnt;
1363 fillcnt++;
1364 }
1365
1366 /* consider dual variable for a lower bound */
1368 {
1369 assert(variables[nrows + 2 * cidx] != NULL);
1370 tmpvars[fillcnt] = variables[nrows + 2 * cidx];
1371 tmpcoef[fillcnt] = 1.0;
1372 fillcnt++;
1373 }
1374
1375 /* consider dual variable for an upper bound */
1377 {
1378 assert(variables[nrows + 2 * cidx + 1] != NULL);
1379 tmpvars[fillcnt] = variables[nrows + 2 * cidx + 1];
1380 tmpcoef[fillcnt] = -1.0;
1381 fillcnt++;
1382 }
1383
1384 /* because we treat the continuous columns as free variable,
1385 we need here an equality */
1386 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "c%d", cidx);
1387 SCIP_CALL( SCIPcreateConsBasicLinear(subscip, &constraints[cidx], name,
1388 fillcnt, tmpvars, tmpcoef, objval, objval) );
1389 SCIP_CALL( SCIPaddCons(subscip, constraints[cidx]) );
1390 }
1391 }
1392
1393 /* determine lower dual bound via a minimization problem */
1395 SCIP_CALL( SCIPchgVarObj(subscip, variables[row], 1.0) );
1396 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "dbg_min_%s.lp", SCIPvarGetName(variables[row]));
1397 SCIP_CALL( SCIPwriteOrigProblem(subscip, name, "lp", FALSE) );
1398 if( solveLP )
1399 {
1400 retcode = SCIPsolve(subscip);
1401 if( retcode != SCIP_OKAY )
1402 SCIPwarningMessage(scip, "Error subscip: <%d>\n", retcode);
1403 else
1404 {
1405 if( SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
1406 {
1407 SCIP_SOL* sol;
1408 SCIP_Bool feasible;
1409 sol = SCIPgetBestSol(subscip);
1410 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, TRUE, TRUE) );
1411
1412 if(feasible)
1413 *lowerbnddual = SCIPgetSolOrigObj(subscip, sol);
1414 }
1415 }
1416 SCIP_CALL( SCIPfreeTransform(subscip) );
1417 }
1418
1419 /* determine upper dual bound via a maximization problem */
1421 SCIP_CALL( SCIPchgVarObj(subscip, variables[row], 1.0) );
1422 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "dbg_max_%s.lp", SCIPvarGetName(variables[row]));
1423 SCIP_CALL( SCIPwriteOrigProblem(subscip, name, "lp", FALSE) );
1424 if( solveLP )
1425 {
1426 retcode = SCIPsolve(subscip);
1427 if( retcode != SCIP_OKAY )
1428 SCIPwarningMessage(scip, "Error subscip: <%d>\n", retcode);
1429 else
1430 {
1431 if( SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL )
1432 {
1433 SCIP_SOL* sol;
1434 SCIP_Bool feasible;
1435 sol = SCIPgetBestSol(subscip);
1436 SCIP_CALL( SCIPcheckSolOrig(subscip, sol, &feasible, TRUE, TRUE) );
1437
1438 if(feasible)
1439 *upperbnddual = SCIPgetSolOrigObj(subscip, sol);
1440 }
1441 }
1442 SCIP_CALL( SCIPfreeTransform(subscip) );
1443 }
1444
1445 /* release variables and constraints */
1446 for( i = 0; i < numDualVars; i++ )
1447 {
1448 if(variables[i] != NULL)
1449 SCIP_CALL( SCIPreleaseVar(subscip, &variables[i]) );
1450 }
1451 for( i = 0; i < numberconvars; i++ )
1452 {
1453 if(constraints[i] != NULL)
1454 SCIP_CALL( SCIPreleaseCons(subscip, &constraints[i]) );
1455 }
1456
1457 SCIPfreeBufferArray(scip, &constraints);
1458 SCIPfreeBufferArray(scip, &tmpcoef);
1459 SCIPfreeBufferArray(scip, &tmpvars);
1460 SCIPfreeBufferArray(scip, &variables);
1461 SCIP_CALL( SCIPfree(&subscip) );
1462 SCIPfreeBufferArray(scip, &colmap);
1463
1464 return SCIP_OKAY;
1465}
1466#endif
1467
1468/** update bounds of the dual variables */
1469static
1471 SCIP* scip, /**< SCIP main data structure */
1472 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1473 SCIP_Real objval, /**< objective function value */
1474 SCIP_Real val, /**< matrix coefficient */
1475 int row, /**< row index */
1476 SCIP_Real mincolresact, /**< minimal column residual activity */
1477 SCIP_Real* lbdual, /**< dual lower bounds */
1478 SCIP_Real* ubdual, /**< dual upper bounds */
1479 int* boundchanges, /**< counter for the number of bound changes */
1480 SCIP_Bool* ubinfchange, /**< flag indicating an upper bound change from infinite to finite */
1481 SCIP_Bool* lbinfchange /**< flag indicating a lower bound change from infinite to finite */
1482 )
1483{
1484 SCIP_Real newlbdual;
1485 SCIP_Real newubdual;
1486
1487 assert(scip != NULL);
1488 assert(matrix != NULL);
1489 assert(lbdual != NULL);
1490 assert(ubdual != NULL);
1491 assert(boundchanges != NULL);
1492 assert(ubinfchange != NULL);
1493 assert(lbinfchange != NULL);
1494
1495 *ubinfchange = FALSE;
1496 *lbinfchange = FALSE;
1497
1498 if( !SCIPisInfinity(scip, -mincolresact) )
1499 {
1500 if( val > 0 )
1501 {
1502 newubdual = (objval - mincolresact) / val;
1503
1504 if( newubdual < ubdual[row] )
1505 {
1506 /* accept the new upper bound only if the numerics are reliable */
1507 if( SCIPisLE(scip,lbdual[row],newubdual) )
1508 {
1509 if( SCIPisInfinity(scip, ubdual[row]) )
1510 *ubinfchange = TRUE;
1511
1512 ubdual[row] = newubdual;
1513 (*boundchanges)++;
1514 }
1515 }
1516 }
1517 else if( val < 0 )
1518 {
1519 newlbdual = (objval - mincolresact) / val;
1520
1521 if( newlbdual > lbdual[row] )
1522 {
1523 /* accept the new lower bound only if the numerics are reliable */
1524 if( SCIPisLE(scip,newlbdual,ubdual[row]) )
1525 {
1526 if( SCIPisInfinity(scip, -lbdual[row]) )
1527 *lbinfchange = TRUE;
1528
1529 lbdual[row] = newlbdual;
1530 (*boundchanges)++;
1531 }
1532 }
1533 }
1534 }
1535}
1536
1537/** dual bound strengthening */
1538static
1540 SCIP* scip, /**< SCIP main data structure */
1541 SCIP_MATRIX* matrix, /**< matrix containing the constraints */
1542 SCIP_PRESOLDATA* presoldata, /**< presolver data structure */
1543 FIXINGDIRECTION* varstofix, /**< array holding information for later upper/lower bound fixing */
1544 int* npossiblefixings, /**< number of possible fixings */
1545 SIDECHANGE* sidestochange, /**< array holding if this is an implied equality */
1546 int* npossiblesidechanges/**< number of possible equality changes */
1547 )
1548{
1549 SCIP_Real* lbdual;
1550 SCIP_Real* ubdual;
1551 SCIP_Real* mincolact;
1552 int* mincolactinf;
1553 SCIP_Real* maxcolact;
1554 int* maxcolactinf;
1555 int* colpnt;
1556 int* colend;
1557 SCIP_Real* valpnt;
1558 int boundchanges;
1559 int loops;
1560 int i;
1561 int j;
1562 int k;
1563 int nrows;
1564 int ncols;
1565 SCIP_Bool* isubimplied;
1566 SCIP_Bool* islbimplied;
1567 SCIP_Real* tmplbs;
1568 SCIP_Real* tmpubs;
1569 SCIP_VAR* var;
1570 int* implubvars;
1571 int nimplubvars;
1572
1573 SCIP_Longint maxhashes;
1574 int maxlen;
1575 int pospp;
1576 int listsizepp;
1577 int posmm;
1578 int listsizemm;
1579 int pospm;
1580 int listsizepm;
1581 int posmp;
1582 int listsizemp;
1583
1584 int* hashlistpp;
1585 int* hashlistmm;
1586 int* hashlistpm;
1587 int* hashlistmp;
1588
1589 int* colidxlistpp;
1590 int* colidxlistmm;
1591 int* colidxlistpm;
1592 int* colidxlistmp;
1593
1594 int block1start;
1595 int block1end;
1596 int block2start;
1597 int block2end;
1598
1599 SCIP_HASHSET* pairhashset;
1600 SCIP_Real* colvalptr;
1601 int* colidxptr;
1602
1603 assert(scip != NULL);
1604 assert(matrix != NULL);
1605 assert(varstofix != NULL);
1606 assert(npossiblefixings != NULL);
1607 assert(sidestochange != NULL);
1608 assert(npossiblesidechanges != NULL);
1609
1610 nrows = SCIPmatrixGetNRows(matrix);
1611 ncols = SCIPmatrixGetNColumns(matrix);
1612
1613 SCIP_CALL( SCIPallocBufferArray(scip, &tmplbs, ncols) );
1614 SCIP_CALL( SCIPallocBufferArray(scip, &tmpubs, ncols) );
1615 for( i = 0; i < ncols; i++ )
1616 {
1617 var = SCIPmatrixGetVar(matrix, i);
1618 tmplbs[i] = SCIPvarGetLbLocal(var);
1619 tmpubs[i] = SCIPvarGetUbLocal(var);
1620 }
1621
1622 /* verify which bounds of continuous variables are implied */
1623 SCIP_CALL( SCIPallocBufferArray(scip, &isubimplied, ncols) );
1624 SCIP_CALL( SCIPallocBufferArray(scip, &islbimplied, ncols) );
1625 SCIP_CALL( SCIPallocBufferArray(scip, &implubvars, ncols) );
1626 nimplubvars = 0;
1627 for( i = 0; i < ncols; i++ )
1628 {
1629 var = SCIPmatrixGetVar(matrix, i);
1630
1633 {
1634 /* we don't care about integral variables or variables that have conflicting locks */
1635 isubimplied[i] = FALSE;
1636 islbimplied[i] = FALSE;
1637 }
1638 else
1639 {
1640 getImpliedBounds(scip, matrix, i, tmplbs, tmpubs, &(isubimplied[i]), &(islbimplied[i]));
1641
1642 /* if a continuous variable has a not implied upper bound we can
1643 * not use this variable (column) for propagating dual bounds.
1644 * not implied lowers bound can usually be treated.
1645 */
1646
1647 /* collect continuous variables with implied upper bound */
1648 if( isubimplied[i] )
1649 {
1650 implubvars[nimplubvars] = i;
1651 nimplubvars++;
1652
1653 /* reset implied bounds for further detections of other implied bounds */
1654 tmpubs[i] = SCIPinfinity(scip);
1655 }
1656
1657 if( islbimplied[i] )
1658 tmplbs[i] = -SCIPinfinity(scip);
1659 }
1660 }
1661
1662 /* initialize bounds of the dual variables */
1663 SCIP_CALL( SCIPallocBufferArray(scip, &lbdual, nrows) );
1664 SCIP_CALL( SCIPallocBufferArray(scip, &ubdual, nrows) );
1665 for( i = 0; i < nrows; i++ )
1666 {
1667 if( !SCIPmatrixIsRowRhsInfinity(matrix, i) )
1668 {
1669 /* dual free variable for equation or ranged row */
1670 lbdual[i] = -SCIPinfinity(scip);
1671 ubdual[i] = SCIPinfinity(scip);
1672 }
1673 else
1674 {
1675 /* dual variable for >= inequality */
1676 lbdual[i] = 0.0;
1677 ubdual[i] = SCIPinfinity(scip);
1678 }
1679 }
1680
1681 /* run convex combination on pairs of continuous variables (columns) using Belotti's algorithm */
1682 if( nimplubvars >= 2 && presoldata->usetwocolcombine )
1683 {
1684 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpp, ncols) );
1685 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmm, ncols) );
1686 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistpm, ncols) );
1687 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &hashlistmp, ncols) );
1688
1689 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistpp, ncols) );
1690 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistmm, ncols) );
1691 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistpm, ncols) );
1692 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &colidxlistmp, ncols) );
1693
1694 pospp = 0;
1695 posmm = 0;
1696 pospm = 0;
1697 posmp = 0;
1698 listsizepp = ncols;
1699 listsizemm = ncols;
1700 listsizepm = ncols;
1701 listsizemp = ncols;
1702 maxhashes = presoldata->maxhashfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxhashfac);
1703
1704 for( i = 0; i < nimplubvars; i++)
1705 {
1706 if( ((SCIP_Longint)pospp) + posmm + pospm + posmp > maxhashes )
1707 break;
1708
1709 colvalptr = SCIPmatrixGetColValPtr(matrix, implubvars[i]);
1710 colidxptr = SCIPmatrixGetColIdxPtr(matrix, implubvars[i]);
1711 maxlen = MIN(presoldata->maxconsiderednonzeros, SCIPmatrixGetColNNonzs(matrix, implubvars[i])); /*lint !e666*/
1712 for( j = 0; j < maxlen; j++)
1713 {
1714 for( k = j + 1; k < maxlen; k++)
1715 {
1716 if( SCIPisPositive(scip, colvalptr[j]) )
1717 {
1718 if(SCIPisPositive(scip, colvalptr[k]) )
1719 {
1720 SCIP_CALL( addEntry(scip, &pospp, &listsizepp, &hashlistpp, &colidxlistpp,
1721 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
1722 }
1723 else
1724 {
1725 SCIP_CALL( addEntry(scip, &pospm, &listsizepm, &hashlistpm, &colidxlistpm,
1726 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
1727 }
1728 }
1729 else
1730 {
1731 if(SCIPisPositive(scip, colvalptr[k]) )
1732 {
1733 SCIP_CALL( addEntry(scip, &posmp, &listsizemp, &hashlistmp, &colidxlistmp,
1734 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
1735 }
1736 else
1737 {
1738 SCIP_CALL( addEntry(scip, &posmm, &listsizemm, &hashlistmm, &colidxlistmm,
1739 hashIndexPair(colidxptr[j], colidxptr[k]), implubvars[i]) );
1740 }
1741 }
1742 }
1743 }
1744 }
1745#ifdef SCIP_MORE_DEBUG
1746 SCIPdebugMsg(scip, "hashlist sizes: pp %d, mm %d, pm %d, mp %d \n", pospp, posmm, pospm, posmp);
1747#endif
1748 SCIPsortIntInt(hashlistpp, colidxlistpp, pospp);
1749 SCIPsortIntInt(hashlistmm, colidxlistmm, posmm);
1750 SCIPsortIntInt(hashlistpm, colidxlistpm, pospm);
1751 SCIPsortIntInt(hashlistmp, colidxlistmp, posmp);
1752
1753 SCIP_CALL( SCIPhashsetCreate(&pairhashset, SCIPblkmem(scip), 1) );
1754
1755 /* Process pp and mm lists */
1756 if( pospp > 0 && posmm > 0 )
1757 {
1758 SCIP_Longint ncombines;
1759 SCIP_Longint maxcombines;
1760 SCIP_Bool finished;
1761 SCIP_Bool success;
1762 int combinefails;
1763 int retrievefails;
1764 COLPAIR colpair;
1765
1766 finished = FALSE;
1767 block1start = 0;
1768 block1end = 0;
1769 block2start = 0;
1770 block2end = 0;
1771
1772 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxpairfac);
1773
1774 ncombines = 0;
1775 combinefails = 0;
1776 retrievefails = 0;
1777 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
1778 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
1779#ifdef SCIP_MORE_DEBUG
1780 SCIPdebugMsg(scip, "processing pp and mm\n");
1781#endif
1782
1783 // same as in the rworowbnd presolver - both while loops to basically the same with one using pp and mm and the other pm and mp
1784 // I would write an additional function and remove the code duplication
1785 while( !finished )
1786 {
1787 if( hashlistpp[block1start] == hashlistmm[block2start] )
1788 {
1789 for( i = block1start; i < block1end; i++ )
1790 {
1791 for( j = block2start; j < block2end; j++ )
1792 {
1793 if( colidxlistpp[i] != colidxlistmm[j] )
1794 {
1795 colpair.col1idx = MIN(colidxlistpp[i], colidxlistmm[j]);
1796 colpair.col2idx = MAX(colidxlistpp[i], colidxlistmm[j]);
1797
1798 if( !SCIPhashsetExists(pairhashset, encodeColPair(&colpair)) )
1799 {
1800 int* colpnt1 = SCIPmatrixGetColIdxPtr(matrix, colpair.col1idx);
1801 SCIP_Real* valpnt1 = SCIPmatrixGetColValPtr(matrix, colpair.col1idx);
1802 int* colpnt2 = SCIPmatrixGetColIdxPtr(matrix, colpair.col2idx);
1803 SCIP_Real* valpnt2 = SCIPmatrixGetColValPtr(matrix, colpair.col2idx);
1804 SCIP_Real obj1 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col1idx));
1805 SCIP_Real obj2 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col2idx));
1806 int collen1 = SCIPmatrixGetColNNonzs(matrix, colpair.col1idx);
1807 int collen2 = SCIPmatrixGetColNNonzs(matrix, colpair.col2idx);
1808
1809 success = FALSE;
1810
1811 SCIP_CALL( combineCols(scip, colpnt1, colpnt2, valpnt1, valpnt2, obj1, obj2, collen1,
1812 collen2, nrows, TRUE, TRUE, lbdual, ubdual, &success) );
1813
1814 if( success )
1815 combinefails = 0;
1816 else
1817 combinefails++;
1818
1819 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeColPair(&colpair)) );
1820 ncombines++;
1821 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
1822 finished = TRUE;
1823#ifdef SCIP_MORE_DEBUG
1824 SCIPdebugMsg(scip, "pm/mp: %d retrievefails before reset, %d combines\n", retrievefails, ncombines);
1825#endif
1826 retrievefails = 0;
1827 }
1828 else if( retrievefails < presoldata->maxretrievefails )
1829 retrievefails++;
1830 else
1831 finished = TRUE;
1832 }
1833 if( finished )
1834 break;
1835 }
1836 if( finished )
1837 break;
1838 }
1839
1840 if( block1end < pospp && block2end < posmm )
1841 {
1842 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
1843 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
1844 }
1845 else
1846 finished = TRUE;
1847 }
1848 else if( hashlistpp[block1start] < hashlistmm[block2start] && block1end < pospp )
1849 findNextBlock(hashlistpp, pospp, &block1start, &block1end);
1850 else if( hashlistpp[block1start] > hashlistmm[block2start] && block2end < posmm )
1851 findNextBlock(hashlistmm, posmm, &block2start, &block2end);
1852 else
1853 finished = TRUE;
1854 }
1855 }
1856
1857 /* Process pm and mp lists */
1858 if( pospm > 0 && posmp > 0 )
1859 {
1860 SCIP_Longint maxcombines;
1861 SCIP_Longint ncombines;
1862 SCIP_Bool finished;
1863 SCIP_Bool success;
1864 int combinefails;
1865 int retrievefails;
1866 COLPAIR colpair;
1867
1868 finished = FALSE;
1869 block1start = 0;
1870 block1end = 0;
1871 block2start = 0;
1872 block2end = 0;
1873
1874 maxcombines = presoldata->maxpairfac == -1 ? SCIP_LONGINT_MAX : (((SCIP_Longint)ncols) * presoldata->maxpairfac);
1875
1876 ncombines = 0;
1877 combinefails = 0;
1878 retrievefails = 0;
1879 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
1880 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
1881#ifdef SCIP_MORE_DEBUG
1882 SCIPdebugMsg(scip, "processing pm and mp\n");
1883#endif
1884
1885 while( !finished )
1886 {
1887 if( hashlistpm[block1start] == hashlistmp[block2start] )
1888 {
1889 for( i = block1start; i < block1end; i++ )
1890 {
1891 for( j = block2start; j < block2end; j++ )
1892 {
1893 if( colidxlistpm[i] != colidxlistmp[j] )
1894 {
1895 colpair.col1idx = MIN(colidxlistpm[i], colidxlistmp[j]);
1896 colpair.col2idx = MAX(colidxlistpm[i], colidxlistmp[j]);
1897
1898 if( !SCIPhashsetExists(pairhashset, encodeColPair(&colpair)) )
1899 {
1900 int* colpnt1 = SCIPmatrixGetColIdxPtr(matrix, colpair.col1idx);
1901 SCIP_Real* valpnt1 = SCIPmatrixGetColValPtr(matrix, colpair.col1idx);
1902 int* colpnt2 = SCIPmatrixGetColIdxPtr(matrix, colpair.col2idx);
1903 SCIP_Real* valpnt2 = SCIPmatrixGetColValPtr(matrix, colpair.col2idx);
1904 SCIP_Real obj1 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col1idx));
1905 SCIP_Real obj2 = SCIPvarGetObj(SCIPmatrixGetVar(matrix, colpair.col2idx));
1906 int collen1 = SCIPmatrixGetColNNonzs(matrix, colpair.col1idx);
1907 int collen2 = SCIPmatrixGetColNNonzs(matrix, colpair.col2idx);
1908
1909 success = FALSE;
1910
1911 SCIP_CALL( combineCols(scip, colpnt1, colpnt2, valpnt1, valpnt2, obj1, obj2, collen1,
1912 collen2, nrows, TRUE, TRUE, lbdual, ubdual, &success) );
1913
1914 if( success )
1915 combinefails = 0;
1916 else
1917 combinefails++;
1918
1919 SCIP_CALL( SCIPhashsetInsert(pairhashset, SCIPblkmem(scip), encodeColPair(&colpair)) );
1920 ncombines++;
1921 if( ncombines >= maxcombines || combinefails >= presoldata->maxcombinefails )
1922 finished = TRUE;
1923
1924 retrievefails = 0;
1925 }
1926 else if( retrievefails < presoldata->maxretrievefails )
1927 retrievefails++;
1928 else
1929 finished = TRUE;
1930 }
1931 if( finished )
1932 break;
1933 }
1934 if( finished )
1935 break;
1936 }
1937
1938 if( block1end < pospm && block2end < posmp )
1939 {
1940 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
1941 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
1942 }
1943 else
1944 finished = TRUE;
1945 }
1946 else if( hashlistpm[block1start] < hashlistmp[block2start] && block1end < pospm )
1947 findNextBlock(hashlistpm, pospm, &block1start, &block1end);
1948 else if( hashlistpm[block1start] > hashlistmp[block2start] && block2end < posmp )
1949 findNextBlock(hashlistmp, posmp, &block2start, &block2end);
1950 else
1951 finished = TRUE;
1952 }
1953 }
1954
1955 SCIPhashsetFree(&pairhashset, SCIPblkmem(scip));
1956 SCIPfreeBlockMemoryArray(scip, &colidxlistmp, listsizemp);
1957 SCIPfreeBlockMemoryArray(scip, &colidxlistpm, listsizepm);
1958 SCIPfreeBlockMemoryArray(scip, &colidxlistmm, listsizemm);
1959 SCIPfreeBlockMemoryArray(scip, &colidxlistpp, listsizepp);
1960 SCIPfreeBlockMemoryArray(scip, &hashlistmp, listsizemp);
1961 SCIPfreeBlockMemoryArray(scip, &hashlistpm, listsizepm);
1962 SCIPfreeBlockMemoryArray(scip, &hashlistmm, listsizemm);
1963 SCIPfreeBlockMemoryArray(scip, &hashlistpp, listsizepp);
1964
1965#ifdef SCIP_MORE_DEBUG
1966 SCIPdebugMsg(scip, "CombCols:\n");
1967 for( i = 0; i < nrows; i++ )
1968 {
1969 assert(SCIPisLE(scip,lbdual[i],ubdual[i]));
1970 SCIPdebugMsg(scip, "y%d=[%g,%g]\n",i,lbdual[i],ubdual[i]);
1971 }
1972 SCIPdebugMsg(scip,"\n");
1973#endif
1974 }
1975
1976 SCIP_CALL( SCIPallocBufferArray(scip, &mincolact, ncols) );
1977 SCIP_CALL( SCIPallocBufferArray(scip, &mincolactinf, ncols) );
1978
1979 /* apply dual bound strengthening */
1980 loops = 0;
1981 boundchanges = 1;
1982 while( 0 < boundchanges && loops < presoldata->maxdualbndloops )
1983 {
1984 loops++;
1985 boundchanges = 0;
1986
1987 for( i = 0; i < nimplubvars; i++ )
1988 {
1989 assert(!SCIPvarIsIntegral(SCIPmatrixGetVar(matrix, implubvars[i]))
1990 || SCIPvarIsImpliedIntegral(SCIPmatrixGetVar(matrix, implubvars[i])));
1991 calcMinColActivity(scip, matrix, implubvars[i], lbdual, ubdual, mincolact, mincolactinf);
1992 }
1993
1994 for( i = 0; i < nimplubvars; i++ )
1995 {
1997 SCIP_Bool ubinfchange;
1998 SCIP_Bool lbinfchange;
1999 int col;
2000
2001 col = implubvars[i];
2002 var = SCIPmatrixGetVar(matrix, col);
2003
2005 colpnt = SCIPmatrixGetColIdxPtr(matrix, col);
2006 colend = colpnt + SCIPmatrixGetColNNonzs(matrix, col);
2007 valpnt = SCIPmatrixGetColValPtr(matrix, col);
2008
2009 for( ; colpnt < colend; colpnt++, valpnt++ )
2010 {
2011 int row;
2012 SCIP_Real val;
2013 SCIP_Real mincolresact;
2014
2015 row = *colpnt;
2016 val = *valpnt;
2017
2018 calcMinColActResidual(scip, matrix, col, row, val, lbdual, ubdual,
2019 mincolact, mincolactinf, &mincolresact);
2020
2021 updateDualBounds(scip, matrix, objval, val, row, mincolresact,
2022 lbdual, ubdual, &boundchanges, &ubinfchange, &lbinfchange);
2023
2024 if( ubinfchange || lbinfchange )
2025 infinityCountUpdate(scip, matrix, row, lbdual, ubdual, isubimplied,
2026 mincolact, mincolactinf, ubinfchange, lbinfchange);
2027 }
2028 }
2029 }
2030
2031#ifdef SCIP_MORE_DEBUG
2032 SCIPdebugMsg(scip, "BndStr:\n");
2033 for( i = 0; i < nrows; i++ )
2034 {
2035 assert(SCIPisLE(scip,lbdual[i],ubdual[i]));
2036 SCIPdebugMsg(scip, "y%d=[%g,%g]\n",i,lbdual[i],ubdual[i]);
2037 }
2038 SCIPdebugMsg(scip,"\n");
2039#endif
2040
2041 SCIP_CALL( SCIPallocBufferArray(scip, &maxcolact, ncols) );
2042 SCIP_CALL( SCIPallocBufferArray(scip, &maxcolactinf, ncols) );
2043
2044 /* calculate final minimal and maximal column activities */
2045 for( i = 0; i < ncols; i++ )
2046 {
2047 calcMinColActivity(scip, matrix, i, lbdual, ubdual, mincolact, mincolactinf);
2048 calcMaxColActivity(scip, matrix, i, lbdual, ubdual, maxcolact, maxcolactinf);
2049 }
2050
2051 for( i = 0; i < ncols; i++ )
2052 {
2054
2055 var = SCIPmatrixGetVar(matrix, i);
2056
2057 /* do not fix variables if the locks do not match */
2058 if( SCIPmatrixUplockConflict(matrix, i) || SCIPmatrixDownlockConflict(matrix, i) )
2059 continue;
2060
2062
2063 /* c_j - sup(y^T A_{.j}) > 0 => fix x_j to its lower bound */
2064 if( SCIPisGT(scip, objval, maxcolact[i]) && varstofix[i] == NOFIX )
2065 {
2067 {
2068 varstofix[i] = FIXATLB;
2069 (*npossiblefixings)++;
2070 }
2071 }
2072
2073 /* c_j - inf(y^T A_{.j}) < 0 => fix x_j to its upper bound */
2074 if( SCIPisLT(scip, objval, mincolact[i]) && varstofix[i] == NOFIX )
2075 {
2077 {
2078 varstofix[i] = FIXATUB;
2079 (*npossiblefixings)++;
2080 }
2081 }
2082 }
2083
2084 for( i = 0; i < nrows; i++ )
2085 {
2086 /* implied equality: y_i > 0 => A_{i.}x - b_i = 0 */
2087 if( SCIPmatrixIsRowRhsInfinity(matrix, i) )
2088 {
2089 if( SCIPisGT(scip, lbdual[i], 0.0) && (sidestochange[i] == NOCHANGE) )
2090 {
2091 /* change >= inequality to equality */
2092 sidestochange[i] = RHSTOLHS;
2093 (*npossiblesidechanges)++;
2094 }
2095 }
2096 else
2097 {
2098 if( !SCIPmatrixIsRowRhsInfinity(matrix, i) &&
2100 {
2101 /* for ranged rows we have to decide which side (lhs or rhs) determines the equality */
2102 if( SCIPisGT(scip, lbdual[i], 0.0) && sidestochange[i]==NOCHANGE )
2103 {
2104 sidestochange[i] = RHSTOLHS;
2105 (*npossiblesidechanges)++;
2106 }
2107
2108 if( SCIPisLT(scip, ubdual[i], 0.0) && sidestochange[i]==NOCHANGE)
2109 {
2110 sidestochange[i] = LHSTORHS;
2111 (*npossiblesidechanges)++;
2112 }
2113 }
2114 }
2115 }
2116
2117 SCIPfreeBufferArray(scip, &maxcolactinf);
2118 SCIPfreeBufferArray(scip, &maxcolact);
2119 SCIPfreeBufferArray(scip, &mincolactinf);
2120 SCIPfreeBufferArray(scip, &mincolact);
2121
2122 SCIPfreeBufferArray(scip, &ubdual);
2123 SCIPfreeBufferArray(scip, &lbdual);
2124 SCIPfreeBufferArray(scip, &implubvars);
2125 SCIPfreeBufferArray(scip, &islbimplied);
2126 SCIPfreeBufferArray(scip, &isubimplied);
2127 SCIPfreeBufferArray(scip, &tmpubs);
2128 SCIPfreeBufferArray(scip, &tmplbs);
2129
2130 return SCIP_OKAY;
2131}
2132
2133/*
2134 * Callback methods of presolver
2135 */
2136
2137/** copy method for constraint handler plugins (called when SCIP copies plugins) */
2138static
2139SCIP_DECL_PRESOLCOPY(presolCopyDualinfer)
2140{ /*lint --e{715}*/
2141 assert(scip != NULL);
2142 assert(presol != NULL);
2143
2145
2146 /* call inclusion method of presolver */
2148
2149 return SCIP_OKAY;
2150}
2151
2152/** destructor of presolver to free user data (called when SCIP is exiting) */
2153static
2154SCIP_DECL_PRESOLFREE(presolFreeDualinfer)
2155{ /*lint --e{715}*/
2156 SCIP_PRESOLDATA* presoldata;
2157
2158 /* free presolver data */
2159 presoldata = SCIPpresolGetData(presol);
2160 assert(presoldata != NULL);
2161
2162 SCIPfreeBlockMemory(scip, &presoldata);
2163 SCIPpresolSetData(presol, NULL);
2164
2165 return SCIP_OKAY;
2166}
2167
2168/** execution method of presolver */
2169static
2170SCIP_DECL_PRESOLEXEC(presolExecDualinfer)
2171{ /*lint --e{715}*/
2172 SCIP_MATRIX* matrix;
2173 SCIP_Bool initialized;
2174 SCIP_Bool complete;
2175 SCIP_Bool infeasible;
2176 SCIP_PRESOLDATA* presoldata;
2177 FIXINGDIRECTION* varstofix;
2178 int npossiblefixings;
2179 int nconvarsfixed;
2180 int nintvarsfixed;
2181 int nbinvarsfixed;
2182 SIDECHANGE* sidestochange;
2183 int npossiblesidechanges;
2184 int nsideschanged;
2185 int i;
2186 int nrows;
2187 int ncols;
2188 SCIP_VAR* var;
2189
2190 assert(result != NULL);
2192
2194 return SCIP_OKAY;
2195
2196 /* the reductions made in this presolver apply to all optimal solutions because of complementary slackness */
2198 return SCIP_OKAY;
2199
2201
2203 {
2204 SCIPdebugMsg(scip, "DualInfer not executed because condition of existing dual solution is not fulfilled.\n");
2205 return SCIP_OKAY;
2206 }
2207
2208 presoldata = SCIPpresolGetData(presol);
2209 assert(presoldata != NULL);
2210
2211 matrix = NULL;
2212 SCIP_CALL( SCIPmatrixCreate(scip, &matrix, TRUE, &initialized, &complete, &infeasible,
2213 naddconss, ndelconss, nchgcoefs, nchgbds, nfixedvars) );
2214
2215 /* if infeasibility was detected during matrix creation, return here */
2216 if( infeasible )
2217 {
2218 if( initialized )
2219 SCIPmatrixFree(scip, &matrix);
2220
2222 return SCIP_OKAY;
2223 }
2224
2225 if( !initialized )
2226 return SCIP_OKAY;
2227
2228 npossiblefixings = 0;
2229 nconvarsfixed = 0;
2230 nintvarsfixed = 0;
2231 nbinvarsfixed = 0;
2232 npossiblesidechanges = 0;
2233 nsideschanged = 0;
2234
2235 nrows = SCIPmatrixGetNRows(matrix);
2236 ncols = SCIPmatrixGetNColumns(matrix);
2237
2238 SCIP_CALL( SCIPallocBufferArray(scip, &varstofix, ncols) );
2239 SCIP_CALL( SCIPallocBufferArray(scip, &sidestochange, nrows) );
2240
2241 BMSclearMemoryArray(varstofix, ncols);
2242 BMSclearMemoryArray(sidestochange, nrows);
2243
2244 SCIP_CALL( dualBoundStrengthening(scip, matrix, presoldata,
2245 varstofix, &npossiblefixings, sidestochange, &npossiblesidechanges) );
2246
2247 if( npossiblefixings > 0 )
2248 {
2249 for( i = ncols - 1; i >= 0; --i )
2250 {
2251 SCIP_Bool fixed;
2252
2253 var = SCIPmatrixGetVar(matrix, i);
2254
2255 /* there should be no fixings for variables with inconsistent locks */
2256 assert(varstofix[i] == NOFIX || (!SCIPmatrixUplockConflict(matrix, i) && !SCIPmatrixDownlockConflict(matrix, i)));
2257
2258 fixed = FALSE;
2259
2260 if( varstofix[i] == FIXATLB )
2261 {
2262 SCIP_Real lb;
2263 lb = SCIPvarGetLbLocal(var);
2264
2265 /* fix at lower bound */
2266 SCIP_CALL( SCIPfixVar(scip, var, lb, &infeasible, &fixed) );
2267 if( infeasible )
2268 {
2269 SCIPdebugMsg(scip, " -> infeasible fixing\n");
2271 break;
2272 }
2273 assert(fixed);
2274 (*nfixedvars)++;
2276 }
2277 else if( varstofix[i] == FIXATUB )
2278 {
2279 SCIP_Real ub;
2280 ub = SCIPvarGetUbLocal(var);
2281
2282 /* fix at upper bound */
2283 SCIP_CALL( SCIPfixVar(scip, var, ub, &infeasible, &fixed) );
2284 if( infeasible )
2285 {
2286 SCIPdebugMsg(scip, " -> infeasible fixing\n");
2288 break;
2289 }
2290 assert(fixed);
2291 (*nfixedvars)++;
2293 }
2294
2295 /* keep a small statistic which types of variables are fixed */
2296 if( fixed )
2297 {
2299 nconvarsfixed++;
2301 nbinvarsfixed++;
2302 else
2303 nintvarsfixed++;
2304 }
2305 }
2306 }
2307
2308 if( npossiblesidechanges > 0 )
2309 {
2310 for( i = 0; i < nrows; i++ )
2311 {
2312 SCIP_CONS* cons;
2313 SCIP_CONSHDLR* conshdlr;
2314 const char* conshdlrname;
2315
2316 if( sidestochange[i] == NOCHANGE )
2317 continue;
2318
2319 if( presoldata->maxrowsupport < SCIPmatrixGetRowNNonzs(matrix, i) )
2320 continue;
2321
2322 cons = SCIPmatrixGetCons(matrix,i);
2323 conshdlr = SCIPconsGetHdlr(cons);
2324 conshdlrname = SCIPconshdlrGetName(conshdlr);
2325
2326 if( strcmp(conshdlrname, "linear") == 0 )
2327 {
2328 SCIP_Real lhs;
2329 SCIP_Real rhs;
2330 SCIP_Real matrixlhs;
2331 SCIP_Real matrixrhs;
2332
2333 lhs = SCIPgetLhsLinear(scip, cons);
2334 rhs = SCIPgetRhsLinear(scip, cons);
2335 matrixlhs = SCIPmatrixGetRowLhs(matrix, i);
2336 matrixrhs = SCIPmatrixGetRowRhs(matrix, i);
2337
2338 assert(!SCIPisEQ(scip, matrixlhs, matrixrhs));
2339
2340 /* when creating the matrix, constraints are multiplied if necessary by (-1)
2341 * to ensure that the following representation is obtained:
2342 * infty >= a x >= b
2343 * or
2344 * c >= ax >= b (ranged rows)
2345 */
2346
2347 /* for ranged constraints we have to distinguish between both sides */
2348 if( sidestochange[i] == RHSTOLHS )
2349 {
2350 if( SCIPisEQ(scip, matrixlhs, lhs) )
2351 {
2352 /* change rhs to lhs */
2353 SCIP_CALL( SCIPchgRhsLinear(scip, cons, matrixlhs) );
2354 }
2355 else
2356 {
2357 /* consider multiplication by (-1) in the matrix */
2358 SCIP_CALL( SCIPchgLhsLinear(scip, cons, -matrixlhs) );
2359 }
2360
2361 nsideschanged++;
2362 (*nchgsides)++;
2363 }
2364 else if( sidestochange[i] == LHSTORHS )
2365 {
2366 if( SCIPisEQ(scip, matrixrhs, rhs) )
2367 {
2368 /* change lhs to rhs */
2369 SCIP_CALL( SCIPchgLhsLinear(scip, cons, matrixrhs) );
2370 }
2371 else
2372 {
2373 /* consider multiplication by (-1) in the matrix */
2374 SCIP_CALL( SCIPchgRhsLinear(scip, cons, -matrixrhs) );
2375 }
2376
2377 nsideschanged++;
2378 (*nchgsides)++;
2379 }
2380 }
2381 }
2382 }
2383
2384 SCIPfreeBufferArray(scip, &sidestochange);
2385 SCIPfreeBufferArray(scip, &varstofix);
2386
2387 if( (nconvarsfixed + nintvarsfixed + nbinvarsfixed) > 0 || npossiblesidechanges > 0 )
2388 {
2389 SCIPdebugMsg(scip, "### fixed vars [cont: %d, int: %d, bin: %d], changed sides [%d]\n",
2390 nconvarsfixed, nintvarsfixed, nbinvarsfixed, nsideschanged);
2391 }
2392
2393 SCIPmatrixFree(scip, &matrix);
2394
2395 return SCIP_OKAY;
2396}
2397
2398
2399/*
2400 * presolver specific interface methods
2401 */
2402
2403/** creates the dual inference presolver and includes it in SCIP */
2405 SCIP* scip /**< SCIP data structure */
2406 )
2407{
2408 SCIP_PRESOL* presol;
2409 SCIP_PRESOLDATA* presoldata;
2410
2411 /* create presolver data */
2412 SCIP_CALL( SCIPallocBlockMemory(scip, &presoldata) );
2413
2414 /* include presolver */
2416 PRESOL_TIMING, presolExecDualinfer, presoldata) );
2417 SCIP_CALL( SCIPsetPresolCopy(scip, presol, presolCopyDualinfer) );
2418 SCIP_CALL( SCIPsetPresolFree(scip, presol, presolFreeDualinfer) );
2419
2421 "presolving/dualinfer/twocolcombine",
2422 "use convex combination of columns for determining dual bounds",
2423 &presoldata->usetwocolcombine, FALSE, DEFAULT_TWOCOLUMN_COMBINE, NULL, NULL) );
2424
2426 "presolving/dualinfer/maxdualbndloops",
2427 "maximal number of dual bound strengthening loops",
2428 &presoldata->maxdualbndloops, FALSE, DEFAULT_MAXLOOPS_DUALBNDSTR, -1, INT_MAX, NULL, NULL) );
2429
2431 "presolving/dualinfer/maxconsiderednonzeros",
2432 "maximal number of considered non-zeros within one column (-1: no limit)",
2433 &presoldata->maxconsiderednonzeros, TRUE, DEFAULT_MAXCONSIDEREDNONZEROS, -1, INT_MAX, NULL, NULL) );
2434
2436 "presolving/dualinfer/maxretrievefails",
2437 "maximal number of consecutive useless hashtable retrieves",
2438 &presoldata->maxretrievefails, TRUE, DEFAULT_MAXRETRIEVEFAILS, -1, INT_MAX, NULL, NULL) );
2439
2441 "presolving/dualinfer/maxcombinefails",
2442 "maximal number of consecutive useless column combines",
2443 &presoldata->maxcombinefails, TRUE, DEFAULT_MAXCOMBINEFAILS, -1, INT_MAX, NULL, NULL) );
2444
2446 "presolving/dualinfer/maxhashfac",
2447 "Maximum number of hashlist entries as multiple of number of columns in the problem (-1: no limit)",
2448 &presoldata->maxhashfac, TRUE, DEFAULT_MAXHASHFAC, -1, INT_MAX, NULL, NULL) );
2449
2451 "presolving/dualinfer/maxpairfac",
2452 "Maximum number of processed column pairs as multiple of the number of columns in the problem (-1: no limit)",
2453 &presoldata->maxpairfac, TRUE, DEFAULT_MAXPAIRFAC, -1, INT_MAX, NULL, NULL) );
2454
2456 "presolving/dualinfer/maxrowsupport",
2457 "Maximum number of row's non-zeros for changing inequality to equality",
2458 &presoldata->maxrowsupport, FALSE, DEFAULT_MAXROWSUPPORT, 2, INT_MAX, NULL, NULL) );
2459
2460 return SCIP_OKAY;
2461}
SCIP_VAR * a
SCIP_VAR ** b
Constraint handler for linear constraints in their most general form, .
static SCIP_RETCODE determineBestBounds(SCIP *scip, SCIP_VAR *var, SCIP_SOL *sol, MIR_DATA *data, SCIP_Real boundswitch, int usevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, SCIP_Bool ignoresol, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real *bestlb, SCIP_Real *bestub, int *bestlbtype, int *bestubtype, SCIP_BOUNDTYPE *selectedbound, SCIP_Bool *freevariable)
Definition cuts.c:4814
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#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_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_RETCODE SCIPfree(SCIP **scip)
SCIP_RETCODE SCIPcreate(SCIP **scip)
SCIP_STATUS SCIPgetStatus(SCIP *scip)
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition scip_prob.c:1907
int SCIPgetNImplVars(SCIP *scip)
Definition scip_prob.c:2387
int SCIPgetNContVars(SCIP *scip)
Definition scip_prob.c:2569
SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition scip_prob.c:742
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3274
SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
Definition scip_prob.c:1417
SCIP_RETCODE SCIPcreateProbBasic(SCIP *scip, const char *name)
Definition scip_prob.c:182
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
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
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 SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition scip_param.c:487
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 SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition scip_param.c:429
SCIP_RETCODE SCIPincludePresolDualinfer(SCIP *scip)
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition cons.c:8413
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition scip_cons.c:1173
SCIP_Real SCIPgetPseudoObjval(SCIP *scip)
Definition scip_lp.c:339
#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)
const char * SCIPpresolGetName(SCIP_PRESOL *presol)
Definition presol.c:625
SCIP_RETCODE SCIPcheckSolOrig(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *feasible, SCIP_Bool printreason, SCIP_Bool completely)
Definition scip_sol.c:4385
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:1890
SCIP_RETCODE SCIPfreeTransform(SCIP *scip)
SCIP_RETCODE SCIPsolve(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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_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_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
Definition var.c:23530
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Bool SCIPvarIsNonimpliedIntegral(SCIP_VAR *var)
Definition var.c:23538
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition scip_var.c:10318
SCIP_RETCODE SCIPcreateVarBasic(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype)
Definition scip_var.c:184
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition scip_var.c:5372
SCIP_Bool SCIPallowWeakDualReds(SCIP *scip)
Definition scip_var.c:10998
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
void SCIPsortIntReal(int *intarray, SCIP_Real *realarray, int len)
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
SCIP_Real objval
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_RETCODE solveLP(SCIP *scip, SCIP_DIVESET *diveset, SCIP_Longint maxnlpiterations, SCIP_DIVECONTEXT divecontext, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition heuristics.c:49
SCIP_Bool SCIPmatrixUplockConflict(SCIP_MATRIX *matrix, int col)
Definition matrix.c:2201
int * SCIPmatrixGetColIdxPtr(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1873
int SCIPmatrixGetRowNNonzs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2013
int SCIPmatrixGetColNNonzs(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1885
SCIP_Bool SCIPmatrixIsRowRhsInfinity(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2095
SCIP_Real SCIPmatrixGetRowLhs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2047
SCIP_Real * SCIPmatrixGetRowValPtr(SCIP_MATRIX *matrix, int row)
Definition matrix.c:1977
SCIP_Bool SCIPmatrixDownlockConflict(SCIP_MATRIX *matrix, int col)
Definition matrix.c:2213
SCIP_Real SCIPmatrixGetRowRhs(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2059
SCIP_Real * SCIPmatrixGetColValPtr(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1861
SCIP_RETCODE SCIPmatrixCreate(SCIP *scip, SCIP_MATRIX **matrixptr, SCIP_Bool onlyifcomplete, SCIP_Bool *initialized, SCIP_Bool *complete, SCIP_Bool *infeasible, int *naddconss, int *ndelconss, int *nchgcoefs, int *nchgbds, int *nfixedvars)
Definition matrix.c:703
int SCIPmatrixGetNColumns(SCIP_MATRIX *matrix)
Definition matrix.c:1897
SCIP_CONS * SCIPmatrixGetCons(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2189
void SCIPmatrixFree(SCIP *scip, SCIP_MATRIX **matrix)
Definition matrix.c:1348
SCIP_VAR * SCIPmatrixGetVar(SCIP_MATRIX *matrix, int col)
Definition matrix.c:1953
int * SCIPmatrixGetRowIdxPtr(SCIP_MATRIX *matrix, int row)
Definition matrix.c:2001
int SCIPmatrixGetNRows(SCIP_MATRIX *matrix)
Definition matrix.c:2037
memory allocation routines
#define BMSclearMemoryArray(ptr, num)
Definition memory.h:130
#define PRESOL_NAME
#define PRESOL_PRIORITY
#define PRESOL_MAXROUNDS
#define PRESOL_TIMING
#define PRESOL_DESC
Fixingdirection
@ FIXATUB
@ FIXATLB
@ NOFIX
enum Fixingdirection FIXINGDIRECTION
#define DEFAULT_TWOCOLUMN_COMBINE
static void calcMaxColActivity(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbdual, SCIP_Real *ubdual, SCIP_Real *maxcolact, int *maxcolactinf)
@ RHSTOLHS
@ LHSTORHS
@ NOCHANGE
static void * encodeColPair(COLPAIR *colpair)
static void calcMinColActResidual(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *lbdual, SCIP_Real *ubdual, const SCIP_Real *mincolact, const int *mincolactinf, SCIP_Real *mincolresact)
#define DEFAULT_MAXCONSIDEREDNONZEROS
static void getImpliedBounds(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *ubimplied, SCIP_Bool *lbimplied)
static void calcMinColActivity(SCIP *scip, SCIP_MATRIX *matrix, int col, SCIP_Real *lbdual, SCIP_Real *ubdual, SCIP_Real *mincolact, int *mincolactinf)
static int hashIndexPair(int idx1, int idx2)
struct ColPair COLPAIR
static void getVarBoundsOfRow(SCIP *scip, SCIP_MATRIX *matrix, int col, int row, SCIP_Real val, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *rowub, SCIP_Bool *ubfound, SCIP_Real *rowlb, SCIP_Bool *lbfound)
static SCIP_RETCODE combineCols(SCIP *scip, int *row1idxptr, int *row2idxptr, SCIP_Real *row1valptr, SCIP_Real *row2valptr, SCIP_Real b1, SCIP_Real b2, int row1len, int row2len, int ncols, SCIP_Bool swaprow1, SCIP_Bool swaprow2, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Bool *success)
static SCIP_Real getMinColActWithoutRow(SCIP *scip, SCIP_MATRIX *matrix, int col, int withoutrow, SCIP_Real *lbdual, SCIP_Real *ubdual)
static void updateDualBounds(SCIP *scip, SCIP_MATRIX *matrix, SCIP_Real objval, SCIP_Real val, int row, SCIP_Real mincolresact, SCIP_Real *lbdual, SCIP_Real *ubdual, int *boundchanges, SCIP_Bool *ubinfchange, SCIP_Bool *lbinfchange)
static void findNextBlock(const int *list, int len, int *start, int *end)
static SCIP_RETCODE dualBoundStrengthening(SCIP *scip, SCIP_MATRIX *matrix, SCIP_PRESOLDATA *presoldata, FIXINGDIRECTION *varstofix, int *npossiblefixings, SIDECHANGE *sidestochange, int *npossiblesidechanges)
#define DEFAULT_MAXHASHFAC
enum SideChange SIDECHANGE
static void getMinMaxActivityResiduals(SCIP *scip, SCIP_MATRIX *matrix, int withoutcol, int row, SCIP_Real *lbs, SCIP_Real *ubs, SCIP_Real *minresactivity, SCIP_Real *maxresactivity, SCIP_Bool *isminsettoinfinity, SCIP_Bool *ismaxsettoinfinity)
#define DEFAULT_MAXCOMBINEFAILS
#define DEFAULT_MAXRETRIEVEFAILS
#define DEFAULT_MAXLOOPS_DUALBNDSTR
#define DEFAULT_MAXPAIRFAC
static void infinityCountUpdate(SCIP *scip, SCIP_MATRIX *matrix, int row, SCIP_Real *lbdual, SCIP_Real *ubdual, const SCIP_Bool *isubimplied, SCIP_Real *mincolact, int *mincolactinf, SCIP_Bool ubinfchange, SCIP_Bool lbinfchange)
#define DEFAULT_MAXROWSUPPORT
static SCIP_RETCODE addEntry(SCIP *scip, int *pos, int *listsize, int **hashlist, int **colidxlist, int hash, int colidx)
dual inference presolver
public methods for managing constraints
public methods for matrix
public methods for message output
public methods for presolvers
public methods for problem variables
general public methods
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for presolving plugins
public methods for global and local (sub)problems
public methods for the probing mode
public methods for SCIP variables
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
default SCIP plugins
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
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_PRESOLEXEC(x)
@ SCIP_OBJSENSE_MAXIMIZE
Definition type_prob.h:47
@ SCIP_OBJSENSE_MINIMIZE
Definition type_prob.h:48
@ 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_Sol SCIP_SOL
Definition type_sol.h:57
@ SCIP_STATUS_OPTIMAL
Definition type_stat.h:43
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71
@ SCIP_VARTYPE_BINARY
Definition type_var.h:64