Scippy

SCIP

Solving Constraint Integer Programs

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