Scippy

SCIP

Solving Constraint Integer Programs

lpexact_bounding.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
25/**@file lpexact_bounding.c
26 * @brief safe exact rational bounding methods
27 * @author Leon Eifler
28 * @author Kati Wolter
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32#include <stdio.h>
33#include <assert.h>
34
35#include "lpi/lpi.h"
36#include "lpiexact/lpiexact.h"
37#ifdef SCIP_WITH_EXACTSOLVE
38#include "rectlu/rectlu.h"
39#endif
41#include "scip/pub_message.h"
42#include "scip/pub_misc.h"
43#include "scip/pub_var.h"
44#include "scip/clock.h"
45#include "scip/lp.h"
46#include "scip/lpexact.h"
47#include "scip/prob.h"
48#include "scip/rational.h"
49#include "scip/rationalgmp.h"
51#include "scip/scip_message.h"
52#include "scip/scip_prob.h"
53#include "scip/scip_tree.h"
54#include "scip/sepastoreexact.h"
55#include "scip/set.h"
56#include "scip/stat.h"
57#include "scip/struct_lpexact.h"
58#include "scip/struct_scip.h"
59#include "scip/struct_set.h"
60#include "scip/primal.h"
61
62#ifdef SCIP_WITH_BOOST
63
64#define PSBIGM 100LL
65
66/** checks if number is a power of two (negative numbers are reported as false);
67 *
68 * Explanation: any number that is a power of two is 1000...00 in binary representation.
69 * That means that n & (n - 1) is 10000 % 01111 == 0. It is easy to prove that this does
70 * not hold for any other number.
71 */
72static
73bool isPowerOfTwo(
74 int n /**< the number to check */
75 )
76{
77 return (n > 0) && ((n & (n - 1)) == 0);
78}
79
80/** checks if floating point lp is integer feasible */
81static
82SCIP_Bool fpLPisIntFeasible(
83 SCIP_LP* lp, /**< LP data structure */
84 SCIP_SET* set /**< global SCIP settings */
85 )
86{
87 SCIP_Real primsol;
88 SCIP_Bool feasible;
89 SCIP_Real frac;
90 int i;
91
92 assert(SCIPlpIsSolved(lp));
93
94 feasible = TRUE;
95 for( i = 0; i < lp->ncols && feasible; i++ )
96 {
97 SCIP_COL* col;
98 col = lp->cols[i];
100 continue;
101
102 /* we can't use SCIPsetIsIntegral since we have to check here in the same way as in SCIPcalcBranchCands() */
103 primsol = SCIPcolGetPrimsol(col);
104 frac = SCIPsetFeasFrac(set, primsol);
105 if( !SCIPsetIsFeasFracIntegral(set, frac) )
106 {
107 feasible = FALSE;
108 break;
109 }
110 }
111
112 return feasible;
113}
114
115#ifdef SCIP_WITH_GMP
116#ifdef SCIP_WITH_EXACTSOLVE
117/** helper method, compute number of nonzeros in lp */
118static
119int getNNonz(
120 SCIP_LPEXACT* lpexact /**< the exact lp */
121 )
122{
123 int ret = 0;
124
125 assert(lpexact != NULL);
126
127 for( int i = 0; i < lpexact->nrows; ++i )
128 ret+= lpexact->rows[i]->len;
129
130 return ret;
131}
132#endif
133
134/** subroutine of constructProjectShiftData(); chooses which columns of the dual matrix are designated as set S, used
135 * for projections
136 */
137static
138SCIP_RETCODE projectShiftChooseDualSubmatrix(
139 SCIP_LP* lp, /**< LP data */
140 SCIP_LPEXACT* lpexact, /**< exact LP data */
141 SCIP_SET* set, /**< scip settings */
142 SCIP_STAT* stat, /**< statistics pointer */
143 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
144 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
145 SCIP_PROB* prob, /**< problem data */
146 BMS_BLKMEM* blkmem /**< block memory struct */
147 )
148{
149 int i;
150 int nrows;
151 int ncols;
152 int nextendedrows;
153
154 /* solution information for exact root LP */
155 SCIP_RATIONAL** rootactivity;
156 SCIP_RATIONAL** rootprimal;
157 SCIP_Bool lperror;
158 SCIP_PROJSHIFTDATA* projshiftdata;
159
160 nrows = lpexact->nrows;
161 ncols = lpexact->ncols;
162 projshiftdata = lpexact->projshiftdata;
163
164 assert(projshiftdata != NULL);
165
166 nextendedrows = projshiftdata->nextendedrows;
167
168 /* build includedrows vector based on psfpdualcolwiseselection, this determines the matrix D */
169 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &projshiftdata->includedrows, nextendedrows) );
170 for( i = 0; i < nextendedrows; i++ )
171 projshiftdata->includedrows[i] = 0;
172 /* no selection -> include all possible dual columns */
173 if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_NO || SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE )
174 {
175 /* determine which dual variables to included in the problem
176 * (ones with finite dual objective coef. in [lhs',-rhs',lb',-ub'])
177 */
178 for( i = 0; i < nrows; i++ )
179 {
180 if( !SCIPrationalIsNegInfinity(lpexact->rows[i]->lhs) )
181 projshiftdata->includedrows[i] = 1;
182 if( !SCIPrationalIsInfinity(lpexact->rows[i]->rhs) )
183 projshiftdata->includedrows[nrows + i] = 1;
184 }
185 for( i = 0; i < ncols; i++ )
186 {
187 if( !SCIPrationalIsNegInfinity(lpexact->cols[i]->lb) )
188 projshiftdata->includedrows[2*nrows + i] = 1;
189 if( !SCIPrationalIsInfinity(lpexact->cols[i]->ub) )
190 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
191 }
192 }
193 else if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_ACTIVE_EXLP )
194 {
195 /* determine which dual variables to include in the problem (in this case we choose dual variables whose primal
196 * constraints are active at the solution of the exact LP at the root node)
197 */
198
199 SCIP_CALL( SCIPlpExactSolveAndEval(lpexact, lp, set, messagehdlr, blkmem, stat, eventqueue, prob, 100LL,
200 &lperror, FALSE) );
201
202 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &rootprimal, ncols) );
203 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &rootactivity, nrows) );
204
205 /* get the primal solution and activity */
206 SCIP_CALL( SCIPlpiExactGetSol(lpexact->lpiexact, NULL, rootprimal, NULL, rootactivity, NULL) );
207
208 /* determine which dual variables to include in the problem
209 * (primal constraints active at optimal solution found at root node)
210 */
211 for( i = 0; i < nrows; i++ )
212 {
213 if( SCIPrationalIsEQ(rootactivity[i], lpexact->rows[i]->lhs) )
214 projshiftdata->includedrows[i] = 1;
215 if( SCIPrationalIsEQ(rootactivity[i], lpexact->rows[i]->rhs) )
216 projshiftdata->includedrows[nrows + i] = 1;
217 }
218 for( i = 0; i < ncols; i++ )
219 {
220 if( SCIPrationalIsEQ(rootprimal[i], lpexact->cols[i]->lb) )
221 projshiftdata->includedrows[2*nrows + i] = 1;
222 if( SCIPrationalIsEQ(rootprimal[i], lpexact->cols[i]->ub) )
223 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
224 }
225
226 SCIPrationalFreeBufferArray(set->buffer, &rootactivity, nrows);
227 SCIPrationalFreeBufferArray(set->buffer, &rootprimal, ncols);
228 }
229 else if( set->exact_psdualcolselection == (int) PS_DUALCOSTSEL_ACTIVE_FPLP )
230 {
231 /* determine which dual variables to include in the problem (in this case we choose dual variables whose primal
232 * constraints are active at the solution of the exact LP at the root node)
233 */
234
235 assert(lp->nrows == nrows);
236 for( i = 0; i < nrows; i++ )
237 {
238 if( SCIPsetIsFeasEQ(set, SCIProwGetLPActivity(lp->rows[i], set, stat, lp), SCIProwGetLhs(lp->rows[i])) )
239 projshiftdata->includedrows[i] = 1;
240 if( SCIPsetIsFeasEQ(set, SCIProwGetLPActivity(lp->rows[i], set, stat, lp), SCIProwGetRhs(lp->rows[i])) )
241 projshiftdata->includedrows[nrows + i] = 1;
242 }
243
244 assert(ncols == lp->ncols);
245 for( i = 0; i < ncols; i++ )
246 {
248 projshiftdata->includedrows[2*nrows + i] = 1;
250 projshiftdata->includedrows[2*nrows + ncols + i] = 1;
251 }
252 }
253 else
254 {
255 SCIPerrorMessage("Invalid value for parameter psfpdualcolwiseselection \n");
256 }
257 return SCIP_OKAY;
258}
259
260/** subroutine of constructProjectShiftData(); computes the LU factorization used by the project-and-shift method */
261static
262SCIP_RETCODE projectShiftFactorizeDualSubmatrix(
263 SCIP_LPEXACT* lpexact, /**< exact LP data */
264 SCIP_SET* set, /**< scip settings */
265 BMS_BLKMEM* blkmem /**< block memory */
266 )
267{
268#if defined(SCIP_WITH_GMP) && defined(SCIP_WITH_EXACTSOLVE)
269 int i;
270 int j;
271 int pos;
272 int nrows;
273 int ncols;
274 int nextendedrows;
275 int nnonz;
276 mpq_t* projvalgmp;
277
278 /* sparse representation of the matrix used for the LU factorization */
279 int* projbeg;
280 int* projlen;
281 int* projind;
282 SCIP_RATIONAL** projval;
283 SCIP_PROJSHIFTDATA* projshiftdata;
284 int projindsize;
285
286 projshiftdata = lpexact->projshiftdata;
287
288 nrows = lpexact->nrows;
289 ncols = lpexact->ncols;
290 nextendedrows = projshiftdata->nextendedrows;
291 nnonz = getNNonz(lpexact);
292 projindsize = 2*nnonz + 2*ncols;
293
294 /* allocate memory for the projection factorization */
295 SCIP_CALL( SCIPsetAllocBufferArray(set, &projbeg, nextendedrows) );
296 SCIP_CALL( SCIPsetAllocBufferArray(set, &projlen, nextendedrows) );
297 SCIP_CALL( SCIPsetAllocBufferArray(set, &projind, projindsize) );
298 BMSclearMemoryArray(projind, projindsize);
299 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &projval, projindsize) );
300 SCIP_CALL( SCIPsetAllocBufferArray(set, &projvalgmp, projindsize) );
301
302 /* allocate memory for the basis mapping */
303 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &projshiftdata->projshiftbasis, nextendedrows) );
304
305 /* use includedrows to construct projshiftbasis, a description/mapping for D; it has length projshiftbasisdim and
306 * projshiftbasis[i] tells what column (out of the original nextendedrows) the ith column in D is
307 */
308 pos = 0;
309 for( i = 0; i < nextendedrows; i++ )
310 {
311 if( projshiftdata->includedrows[i] )
312 {
313 projshiftdata->projshiftbasis[pos] = i;
314 pos++;
315 }
316 }
317 projshiftdata->projshiftbasisdim = pos;
318
319 /* build the sparse representation of D that will be passed to the RECTLU code for factorization */
320 pos = 0;
321 for( i = 0; i < nextendedrows; i++ )
322 {
323 /* A part (lhs constraints) */
324 if( i < nrows )
325 {
326 projlen[i] = lpexact->rows[i]->len;
327 projbeg[i] = pos;
328 for( j = 0; j < projlen[i]; j++ )
329 {
330 projind[ projbeg[i] + j ] = lpexact->rows[i]->cols_index[j];
331 SCIPrationalSetRational( projval[ projbeg[i] + j], lpexact->rows[i]->vals[j]);
332 }
333 pos += projlen[i];
334 }
335 /* -A part (rhs constraints) */
336 else if( i < 2 * nrows )
337 {
338 projlen[i] = lpexact->rows[i - nrows]->len;
339 projbeg[i] = pos;
340 for(j = 0; j < projlen[i]; j++)
341 {
342 projind[ projbeg[i] + j ] = lpexact->rows[i - nrows]->cols_index[j];
343 SCIPrationalNegate( projval[ projbeg[i] + j], lpexact->rows[i - nrows]->vals[j]);
344 }
345 pos += projlen[i];
346 }
347 /* I part (lb constraints) */
348 else if( i < 2*nrows + ncols )
349 {
350 projbeg[i] = pos;
351 projlen[i] = 1;
352 projind[pos] = i - 2*nrows;
353 SCIPrationalSetFraction(projval[pos], 1LL, 1LL);
354 pos ++;
355 }
356 /* -I part (ub constraints) */
357 else
358 {
359 projbeg[i] = pos;
360 projlen[i] = 1;
361 projind[pos] = i - (2*nrows + ncols);
362 SCIPrationalSetFraction(projval[pos], -1LL, 1LL);
363 pos ++;
364 }
365 }
366
367#ifdef SCIP_DEBUG_PS_OUT
368 printf("factoring matrix: ncols=%d, projshiftbasisdim=%d\n", ncols, projshiftdata->projshiftbasisdim);
369 for( i = 0; i < nextendedrows; i++ )
370 printf(" j=%d:\t projbeg=<%d>,\t projlen=<%d>\n", i, projbeg[i], projlen[i]);
371
372 for( i = 0; i < projindsize; i++ )
373 {
374 printf(" i=%d:\t projind=<%d>,\t projval=<", i, projind[i]);
375 SCIPrationalPrint(projval[i]);
376 printf(">\n");
377 }
378#endif
379
380 /* factorize projection matrix D
381 * - projshiftbasis stores a mapping to tell us what D is, i.e. the dual columns corresponding to dual valuse that have a
382 * strictly positive value in the relative interior point
383 * - D is equal to a subset of [A',-A',I,-I] and is given to the factor code in sparse column representation
384 */
385 SCIPrationalSetGMPArray(projvalgmp, projval, projindsize);
386
387 /* if RECTLUbuildFactorization has failed, the project-and-shift method will not work and we will return failure */
388 if( RECTLUbuildFactorization(&projshiftdata->rectfactor, ncols, projshiftdata->projshiftbasisdim,
389 projshiftdata->projshiftbasis, projvalgmp, projind, projbeg, projlen) != 0 )
390 {
391 projshiftdata->projshiftdatafail = TRUE;
392 SCIPdebugMessage("factorization of matrix for project-and-shift method failed.\n");
393#ifdef SCIP_DEBUG_PS_OUT
394 printf(" matrix factorization complete: failed\n");
395#endif
396 }
397 else
398 {
399#ifdef SCIP_DEBUG_PS_OUT
400 printf(" matrix factorization complete: correct termination\n");
401#endif
402 }
403
404 SCIPrationalClearArrayGMP(projvalgmp, projindsize);
405 SCIPsetFreeBufferArray(set, &projvalgmp);
406 SCIPrationalFreeBufferArray(set->buffer, &projval, projindsize);
407 SCIPsetFreeBufferArray(set, &projind);
408 SCIPsetFreeBufferArray(set, &projlen);
409 SCIPsetFreeBufferArray(set, &projbeg);
410
411#else /* SCIP_WITH_GMP or SCIP_WITH_EXACTSOLVE not defined */
412 lpexact->projshiftdata->projshiftdatafail = TRUE;
413#ifdef SCIP_DEBUG_PS_OUT
414 printf(" matrix factorization skipped: no GMP or EXACTSOLVE\n");
415#endif
416#endif
417
418 return SCIP_OKAY;
419}
420
421/** setup the data for ps in optimal version */
422static
423SCIP_RETCODE setupProjectShiftOpt(
424 SCIP_LP* lp, /**< LP data */
425 SCIP_LPEXACT* lpexact, /**< exact LP data */
426 SCIP_SET* set, /**< scip settings */
427 SCIP_PROB* prob, /**< problem data */
428 SCIP_RATIONAL** psobj, /**< obj function */
429 SCIP_RATIONAL** psub, /**< upper bounds */
430 SCIP_RATIONAL** pslb, /**< lower bounds */
431 SCIP_RATIONAL** pslhs, /**< left hand sides */
432 SCIP_RATIONAL** psrhs, /**< right hand sides */
433 SCIP_RATIONAL** psval, /**< matrix values */
434 int* pslen, /**< lengths of rows */
435 int* psind, /**< indices of vals */
436 int* psbeg, /**< beginning of rows in vals */
437 int* dvarincidence, /**< indicates cols with bounds */
438 int* dvarmap, /**< mapping between red-sized prob and original one */
439 SCIP_RATIONAL* alpha, /**< scale obj */
440 SCIP_RATIONAL* beta, /**< scale obj */
441 SCIP_RATIONAL* tmp, /**< helper rational */
442 int psnrows, /**< numer of rows */
443 int psnnonz, /**< numer of non-zeros */
444 int psncols, /**< numer of columns */
445 int ndvarmap, /**< numer of cols with bounds in extended prob */
446 int nrows, /**< numer of rows */
447 int ncols /**< numer of cols */
448 )
449{
450 SCIP_PROJSHIFTDATA* projshiftdata;
451 int pos;
452 int i;
453 int j;
454 int indx;
455
456 projshiftdata = lpexact->projshiftdata;
457
458 /* set up the objective */
459 pos = 0;
460 for( i = 0; i < nrows; i++ )
461 {
462 if( dvarincidence[i] )
463 {
464 SCIPrationalSetRational(psobj[pos], lpexact->rows[i]->lhs);
465 pos++;
466 }
467 }
468 for( i = 0; i < nrows; i++ )
469 {
470 if( dvarincidence[nrows + i] )
471 {
472 SCIPrationalNegate(psobj[pos], lpexact->rows[i]->rhs);
473 pos++;
474 }
475 }
476 for( i = 0; i < ncols; i++ )
477 {
478 if( dvarincidence[2*nrows + i] )
479 {
480 SCIPrationalSetRational(psobj[pos], lpexact->cols[i]->lb);
481 pos++;
482 }
483 }
484 for( i = 0; i < ncols; i++ )
485 {
486 if( dvarincidence[2*nrows + ncols + i])
487 {
488 SCIPrationalNegate(psobj[pos], lpexact->cols[i]->ub);
489 pos++;
490 }
491 }
492 assert(pos == ndvarmap);
493
494 /* set alpha and beta; note that in the current implementation projshiftobjweight can only be 0 or 1 */
495 SCIPrationalSetFraction(alpha, (SCIP_Longint) projshiftdata->projshiftobjweight, 1LL);
496 SCIPrationalSetFraction(beta, 1LL, 1LL);
497
498 if( SCIPrationalIsPositive(alpha) )
499 {
500 SCIPrationalDiff(beta, beta, alpha);
501
502 /* beta = (1-alpha)*|OBJ| Where OBJ = optimal objective value of root LP, if |OBJ|<1 use 1 instead */
503 if( REALABS(SCIPlpGetObjval(lp, set, prob)) > 1 )
504 {
506 SCIPrationalMult(beta, beta, tmp);
507 }
508 /* divide through by alpha and round beta to be a power of 2 */
509 SCIPrationalDiv(beta, beta, alpha);
510 SCIPrationalSetFraction(alpha, 1LL, 1LL);
511 SCIPrationalSetReal(beta, pow(2.0, log(SCIPrationalGetReal(beta))/log(2.0)));
512 }
513
514 /* set objective to normalized value */
515 for( i = 0; i < ndvarmap; i ++ )
516 SCIPrationalMult(psobj[i], psobj[i], alpha);
517 SCIPrationalSetRational(psobj[ndvarmap], beta);
518
519 /* set variable bounds */
520 for( i = 0; i < ndvarmap; i++ )
521 {
523 SCIPrationalSetFraction(pslb[i], 0LL, 1LL);
524 }
525 SCIPrationalSetFraction(psub[ndvarmap], PSBIGM, 1LL);
526 SCIPrationalSetFraction(pslb[ndvarmap], 0LL, 1LL);
527
528 /* set up constraint bounds */
529 for( i = 0; i < ncols; i++ )
530 {
531 SCIPrationalSetRational(pslhs[i], lpexact->cols[i]->obj);
532 SCIPrationalSetRational(psrhs[i], lpexact->cols[i]->obj);
533 }
534 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
535 {
536 SCIPrationalSetFraction(pslhs[ncols + i], 0LL, 1LL);
537 SCIPrationalSetInfinity(psrhs[ncols + i]);
538 }
539
540 /* set up constraint matrix: this involves transposing the constraint matrix */
541
542 /* count the length of each constraint */
543 for( i = 0; i < psnrows; i++ )
544 pslen[i] = 0;
545 for( i = 0; i < ndvarmap; i++ )
546 {
547 indx = dvarmap[i];
548 if( indx < 2*nrows )
549 {
550 if( indx >= nrows )
551 indx -= nrows;
552 for( j = 0; j < lpexact->rows[indx]->len; j++ )
553 {
554 pslen[lpexact->rows[indx]->cols_index[j]]++;
555 }
556 }
557 else
558 {
559 if ( indx < 2*nrows + ncols )
560 indx -= 2 * nrows;
561 else
562 indx -= (2*nrows + ncols);
563 pslen[indx]++;
564 }
565 }
566 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
567 {
568 pslen[ncols + i] = 2;
569 }
570 /* set up the beg array */
571 pos = 0;
572 for( i = 0; i < psnrows; i++ )
573 {
574 psbeg[i] = pos;
575 pos += pslen[i];
576 }
577 assert(pos == psnnonz);
578
579 /* reset the length array and build it up as entries are added one by one by scanning through matrix. */
580 for( i = 0; i < ncols; i++ )
581 pslen[i] = 0;
582 for( i = 0; i < ndvarmap; i++ )
583 {
584 indx = dvarmap[i];
585 if( indx < 2*nrows )
586 {
587 if( indx >= nrows )
588 indx -= nrows;
589 for(j = 0; j < lpexact->rows[indx]->len; j++)
590 {
591 pos = psbeg[lpexact->rows[indx]->cols_index[j]] + pslen[lpexact->rows[indx]->cols_index[j]];
592 psind[pos] = i;
593 if(dvarmap[i]<nrows)
594 SCIPrationalSetRational(psval[pos], lpexact->rows[indx]->vals[j]);
595 else
596 SCIPrationalNegate(psval[pos], lpexact->rows[indx]->vals[j]);
597 pslen[lpexact->rows[indx]->cols_index[j]]++;
598 }
599 }
600 else
601 {
602 if ( indx < 2*nrows + ncols )
603 indx -= 2 * nrows;
604 else
605 indx -= (2*nrows + ncols);
606 pos = psbeg[indx] + pslen[indx];
607 psind[pos] = i;
608 if( dvarmap[i] < 2*nrows + ncols)
609 SCIPrationalSetFraction(psval[pos], 1LL, 1LL);
610 else
611 SCIPrationalSetFraction(psval[pos], -1LL, 1LL);
612 pslen[indx]++;
613 }
614 }
615 /* set up the last projshiftbasisdim rows */
616 pos = ncols;
617 for( i = 0; i < ndvarmap; i++ )
618 {
619 indx = dvarmap[i];
620 if( projshiftdata->includedrows[indx] )
621 {
622 psind[psbeg[pos]] = i;
623 SCIPrationalSetFraction(psval[psbeg[pos]], 1LL, 1LL);
624 psind[psbeg[pos] + 1] = psncols - 1;
625 SCIPrationalSetFraction(psval[psbeg[pos] + 1], -1LL, 1LL);
626 pos++;
627 }
628 }
629 assert(pos == psnrows);
630
631 return SCIP_OKAY;
632}
633
634/** subroutine to compute number of nonzeros in lp-matrix */
635static
636int computeProjectShiftNnonz(
637 SCIP_LPEXACT* lpexact, /**< the exact lp */
638 int* dvarincidence /**< the columns with existing bounds */
639 )
640{
641 int ret = 0;
642 int i;
643 int nrows = lpexact->nrows;
644 int ncols = lpexact->ncols;
645
646 for( i = 0; i < nrows; i++ )
647 {
648 if( dvarincidence[i] )
649 ret += lpexact->rows[i]->len;
650 if( dvarincidence[nrows + i] )
651 ret += lpexact->rows[i]->len;
652 }
653 for( i = 0; i < ncols; i++ )
654 {
655 if( dvarincidence[2*nrows + i] )
656 ret++;
657 if( dvarincidence[2*nrows + ncols + i] )
658 ret++;
659 }
660
661 return ret;
662}
663
664/** subroutine of constructProjectShiftData(); computes S-interior point or ray which is used to do the shifting step */
665static
666SCIP_RETCODE projectShiftComputeSintPointRay(
667 SCIP_LPEXACT* lpexact, /**< exact LP data */
668 SCIP_SET* set, /**< scip settings */
669 SCIP_STAT* stat, /**< statistics pointer */
670 BMS_BLKMEM* blkmem, /**< block memory */
671 SCIP_Bool findintpoint /**< TRUE, if we search int point, FALSE if we search for ray */
672 )
673{
674 int ncols;
675 int psncols;
676 SCIP_Real lptimelimit;
677 SCIP_RETCODE retcode;
678
679 /* lpiexact and data used for the aux. problem */
680 SCIP_LPIEXACT* pslpiexact;
681 SCIP_PROJSHIFTDATA* projshiftdata;
682
683 SCIP_RATIONAL** sol = NULL; /* either primal or dualsol */
684 SCIP_RATIONAL* objval;
685
686 /* mapping between variables used in the aux. problem and the original problem */
687 int ndvarmap;
688 int* dvarmap;
689
690 projshiftdata = lpexact->projshiftdata;
691 assert(projshiftdata != NULL);
692 pslpiexact = projshiftdata->lpiexact;
693 if( pslpiexact == NULL )
694 {
695 projshiftdata->projshiftdatafail = TRUE;
696 return SCIP_OKAY;
697 }
698
699 ncols = lpexact->ncols;
700
701 dvarmap = projshiftdata->dvarmap;
702 ndvarmap = projshiftdata->ndvarmap;
703 SCIP_CALL( SCIPlpiExactGetNCols(pslpiexact, &psncols) );
704 assert(psncols == ndvarmap + 1);
705
706 if( !findintpoint )
707 {
708 /* in this case we want to find an interior ray instead of an interior point
709 * the problem will be modified to the following problem:
710 * max: [OBJ, 0]*[y,d]'
711 * s.t.: [0] <= [ A~ | 0] [y] <= [ 0 ]
712 * [0] <= [ I* | -1] * [d] <= [\infty] <-- only for dual vars from includecons
713 * bounds: 0 <= y <= \infty
714 * 1 <= d <= \infty
715 * y is a vector of length (ndvarmap) and d is a single variable
716 * and A~ is the submatrix of [A',-A',I,-I] using columns in dvarmap
717 * and OBJ is the subvector of [lhs,-rhs,lb,-ub] using columns in dvarmap
718 *
719 * the parts that change are the objective function, the RHS/LHS of the first constraint set
720 * and the lower bound for d
721 */
722 SCIP_RATIONAL* auxval1;
723 SCIP_RATIONAL* auxval2;
724 int i;
725
726 assert(projshiftdata->projshifthasray == FALSE);
727
728 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &auxval1) );
729 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &auxval2) );
730
731 /* update the objective on d */
732 SCIPrationalSetFraction(auxval1, 0LL, 1LL);
733 SCIP_CALL( SCIPlpiExactChgObj(pslpiexact, 1, &ndvarmap, &auxval1) );
734
735 /* update the rhs/lhs */
736 for( i = 0; i < ncols; i++ )
737 {
738 SCIP_CALL( SCIPlpiExactChgSides(pslpiexact, 1, &i, &auxval1, &auxval1) );
739 }
740
741 /* update bounds on d */
742 SCIPrationalSetFraction(auxval1, 1LL, 1LL); /*lint !e850*/ /* lint exception for &i in above for loop */
744 SCIP_CALL( SCIPlpiExactChgBounds(pslpiexact, 1, &ndvarmap, &auxval1, &auxval2) );
745
746 SCIPrationalFreeBlock(blkmem, &auxval2);
747 SCIPrationalFreeBlock(blkmem, &auxval1);
748 }
749
750 /* set the display informatino */
751 SCIP_CALL( SCIPlpiExactSetIntpar(pslpiexact, SCIP_LPPAR_LPINFO, (int) set->exact_lpinfo) );
752 /* check if a time limit is set, and set time limit for LP solver accordingly */
753 lptimelimit = SCIPlpiExactInfinity(pslpiexact);
754 if( set->istimelimitfinite )
755 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
756 if( lptimelimit > 0.0 )
757 {
758 SCIP_CALL( SCIPlpiExactSetRealpar(pslpiexact, SCIP_LPPAR_LPTILIM, lptimelimit) );
759 }
760 /* solve the LP */
761 retcode = SCIPlpiExactSolveDual(pslpiexact);
762 if( retcode == SCIP_LPERROR )
763 {
764 projshiftdata->projshiftdatafail = TRUE;
765 SCIPwarningMessage(set->scip, "lperror in construction of projshift-data \n");
766 }
767
768 /* recover the optimal solution and set interior point and slack in constraint handler data */
769 if( SCIPlpiExactIsOptimal(pslpiexact) )
770 {
771 int i;
772
773 SCIPdebugMessage(" exact LP solved to optimality\n");
774
775 /* get optimal dual solution */
776 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &sol, psncols) );
777 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &objval) );
778 SCIP_CALL( SCIPlpiExactGetSol(pslpiexact, objval, sol, NULL, NULL, NULL) );
779
780 SCIPrationalSetRational(projshiftdata->commonslack, sol[psncols - 1]);
781 if( SCIPrationalIsZero(projshiftdata->commonslack) )
782 {
783 /* if commonslack == 0, point/ray is not interior */
784 SCIPdebugMessage(" --> project-and-shift failed to find interior point/ray\n");
785 }
786 else
787 {
788 /* assign interior point solution to constraint handler data */
789 for( i = 0; i < ndvarmap; i++ )
790 {
791 if( findintpoint )
792 SCIPrationalSetRational( projshiftdata->interiorpoint[dvarmap[i]], sol[i]);
793 else
794 SCIPrationalSetRational( projshiftdata->interiorray[dvarmap[i]], sol[i]);
795 }
796 if( findintpoint )
797 projshiftdata->projshifthaspoint = TRUE;
798 else
799 projshiftdata->projshifthasray = TRUE;
800 }
801
802 SCIPrationalFreeBuffer(set->buffer, &objval);
803 SCIPrationalFreeBufferArray(set->buffer, &sol, psncols);
804 }
805 else
806 projshiftdata->projshiftdatafail = TRUE;
807
808 if( findintpoint && projshiftdata->projshifthaspoint )
809 {
810 int i;
811
812 for( i = 0; i < ndvarmap; i++ )
813 SCIPrationalCanonicalize(projshiftdata->interiorpoint[i]);
814 }
815 else if( !findintpoint && projshiftdata->projshifthasray )
816 {
817 int i;
818
819 for( i = 0; i < ndvarmap; i++ )
820 SCIPrationalCanonicalize(projshiftdata->interiorray[i]);
821 }
822
823 /* free memory for exact LPI if not needed anymore */
824 assert(pslpiexact != NULL);
825 if( projshiftdata->projshiftdatafail || (projshiftdata->projshifthaspoint && projshiftdata->projshifthasray) )
826 {
827 int nlpirows;
828 int nlpicols;
829
830 SCIP_CALL( SCIPlpiExactGetNRows(pslpiexact, &nlpirows) );
831 SCIP_CALL( SCIPlpiExactDelRows(pslpiexact, 0, nlpirows - 1) );
832
833 SCIP_CALL( SCIPlpiExactGetNCols(pslpiexact, &nlpicols) );
834 SCIP_CALL( SCIPlpiExactDelCols(pslpiexact, 0, nlpicols - 1) );
835
836 SCIP_CALL( SCIPlpiExactClear(pslpiexact) );
837 SCIP_CALL( SCIPlpiExactFree(&pslpiexact) );
838
839 projshiftdata->lpiexact = NULL;
840
841 assert(projshiftdata->dvarmap != NULL);
842 BMSfreeBlockMemoryArrayNull(blkmem, &projshiftdata->dvarmap, projshiftdata->ndvarmap);
843 }
844
845 return SCIP_OKAY;
846}
847
848/** subroutine of constructProjectShiftData(); computes S-interior point or ray which is used to do the shifting step */
849static
850SCIP_RETCODE projectShiftConstructLP(
851 SCIP_LP* lp, /**< LP data */
852 SCIP_LPEXACT* lpexact, /**< exact LP data */
853 SCIP_SET* set, /**< scip settings */
854 SCIP_PROB* prob, /**< problem data */
855 BMS_BLKMEM* blkmem /**< block memory */
856 )
857{
858 /* we will find an optimized interior point for which we will try to push it interior and
859 * optimize over its objective value. To do this we will solve the following problem
860 * max \alpha * [lhs,-rhs,lb,ub] * y + \beta d
861 * s.t. [A,-A,I,-I] * y = c
862 * y_i - d >= 0 for each i \in S
863 * y >= 0
864 * M >= d >= 0
865 * M is a bound on how interior we will let the point be, S is the set of dual columns chosen earlier
866 * which could have nonzero values for the S-interior point.
867 *
868 * After solving this y will be the S-interior point and d will be the common slack.
869 * Here we actually construct the dual in row representation so it can be solved directly.
870 */
871
872 int pos;
873 int nrows;
874 int ncols;
875 int nextendedrows; /* number of extended constraints, # of cols in [A',-A',I,-I] */
876 int psncols;
877
878 /* lpiexact and data used for the aux. problem */
879 SCIP_LPIEXACT* pslpiexact;
880 SCIP_PROJSHIFTDATA* projshiftdata;
881 SCIP_ROWEXACT** lprows;
882 SCIP_COLEXACT** lpcols;
883
884 /* mapping between variables used in the aux. problem and the original problem */
885 int ndvarmap;
886 int* dvarmap;
887
888 SCIP_RATIONAL** psobj = NULL;
889 SCIP_RATIONAL** pslb = NULL;
890 SCIP_RATIONAL** psub = NULL;
891 SCIP_RATIONAL** pslhs = NULL;
892 SCIP_RATIONAL** psrhs = NULL;
893 int* psbeg;
894 int* pslen;
895 int* psind;
896 SCIP_RATIONAL** psval = NULL;
897 char ** colnames = NULL;
898 int psnrows;
899 int psnnonz;
900 int i;
901
902 SCIP_RATIONAL* tmp;
903 SCIP_RATIONAL* alpha;
904 SCIP_RATIONAL* beta;
905 int* dvarincidence;
906
907 assert(lpexact != NULL);
908
909 projshiftdata = lpexact->projshiftdata;
910 assert(projshiftdata != NULL);
911
912 if( projshiftdata->lpiexact != NULL )
913 return SCIP_OKAY;
914
915 lprows = lpexact->rows;
916 lpcols = lpexact->cols;
917 nrows = lpexact->nrows;
918 ncols = lpexact->ncols;
919
920 nextendedrows = projshiftdata->nextendedrows;
921
922 /* set up dvarmap - mapping between variables and original problem
923 * - use the rows that are used for aux. problem
924 * - dvarmap[i] is the index in the original problem of the i^th constraint in the reduced size problem
925 * (reduced from nextendedrows to ndvarmap)
926 * - dvarincidence gives the incidence vector of variables used in aux problem
927 */
928 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
929 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &alpha) );
930 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &beta) );
931 SCIP_CALL( SCIPsetAllocBufferArray(set, &dvarincidence, nextendedrows) );
932 {
933 /* if the aux. lp is not reduced then expand the selection for dvarmap to include all dual vars with finite cost */
934 for( i = 0; i < nextendedrows; i++ )
935 dvarincidence[i] = 0;
936 for( i = 0; i < nrows; i++ )
937 {
938 if( !SCIPrationalIsNegInfinity(lprows[i]->lhs) )
939 dvarincidence[i] = 1;
940 if( !SCIPrationalIsInfinity(lprows[i]->rhs) )
941 dvarincidence[nrows + i] = 1;
942 }
943 for( i = 0; i < ncols; i++ )
944 {
945 if( !SCIPrationalIsNegInfinity(lpcols[i]->lb) )
946 dvarincidence[2*nrows + i] = 1;
947 if( !SCIPrationalIsInfinity(lpcols[i]->ub) )
948 dvarincidence[2*nrows + ncols + i] = 1;
949 }
950 }
951
952 ndvarmap = 0;
953 for( i = 0; i < nextendedrows; i++ )
954 {
955 if(dvarincidence[i])
956 ndvarmap++;
957 }
958 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &dvarmap, ndvarmap) );
959 pos = 0;
960 for( i = 0; i < nextendedrows; i++ )
961 {
962 if(dvarincidence[i])
963 {
964 assert(pos < ndvarmap);
965 dvarmap[pos] = i;
966 pos++;
967 }
968 }
969 projshiftdata->dvarmap = dvarmap;
970 projshiftdata->ndvarmap = ndvarmap;
971
972 /* allocate memory for auxiliary problem */
973 psncols = ndvarmap + 1;
974 psnrows = ncols + projshiftdata->projshiftbasisdim;
975 psnnonz = computeProjectShiftNnonz(lpexact, dvarincidence);
976 psnnonz += 2*projshiftdata->projshiftbasisdim;
977
978 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psobj, psncols) );
979 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &pslb, psncols) );
980 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psub, psncols) );
981 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &pslhs, psnrows) );
982 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psrhs, psnrows) );
983 SCIP_CALL( SCIPrationalCreateBufferArray(set->buffer, &psval, psnnonz) );
984
985 SCIP_CALL( SCIPsetAllocBufferArray(set, &psbeg, psnrows) );
986 SCIP_CALL( SCIPsetAllocBufferArray(set, &pslen, psnrows) );
987 SCIP_CALL( SCIPsetAllocBufferArray(set, &psind, psnnonz) );
988
989 SCIP_CALL( SCIPsetAllocBufferArray(set, &colnames, psncols) );
990 for( i = 0; i < psncols; i++ )
991 {
992 SCIP_CALL( SCIPsetAllocBufferArray(set, &colnames[i], SCIP_MAXSTRLEN) ); /*lint !e866*/
993 (void) SCIPsnprintf( (colnames)[i] , SCIP_MAXSTRLEN, "var%d", i);
994 }
995
996 /* the representation of the problem will be:
997 * max: [\alpha*OBJ, \beta]*[y,d]'
998 * s.t.: [c] <= [ A~ | 0] [y] <= [ c ]
999 * [0] <= [ I* | -1] * [d] <= [\infty] <-- only for dual vars from includecons
1000 * bounds: 0 <= y <= \infty
1001 * 0 <= d <= M
1002 * y is a vector of length (ndvarmap) and d is a single variable
1003 * and A~ is the submatrix of [A',-A',I,-I] using columns in dvarmap
1004 * and OBJ is the subvector of [lhs,-rhs,lb,-ub] using columns in dvarmap
1005 *
1006 * alpha is set equal to the param projshiftobjweight and beta is set equal to
1007 * beta := 1-alpha
1008 */
1009 SCIP_CALL( setupProjectShiftOpt(lp, lpexact, set, prob, psobj, psub, pslb, pslhs, psrhs, psval,
1010 pslen, psind, psbeg, dvarincidence, dvarmap, alpha, beta, tmp, psnrows, psnnonz,
1011 psncols, ndvarmap, nrows, ncols) );
1012
1013 /* build aux LP using the exact LP interface and store it in the global data */
1014 SCIP_CALL( SCIPlpiExactCreate(&pslpiexact, NULL, "pslpiexact", SCIP_OBJSEN_MAXIMIZE) );
1015 projshiftdata->lpiexact = pslpiexact;
1016
1017 /* add all columns to the exact LP */
1018 SCIP_CALL( SCIPlpiExactAddCols(pslpiexact, psncols, psobj, pslb, psub, colnames, 0, NULL, NULL, NULL) );
1019
1020 /* add all constraints to the exact LP */
1021 SCIP_CALL( SCIPlpiExactAddRows(pslpiexact, psnrows, pslhs, psrhs, NULL, psnnonz, psbeg, psind, psval) );
1022
1023 /* free memory */
1024 for( i = psncols - 1; i >= 0; i-- )
1025 SCIPsetFreeBufferArray(set, &colnames[i] );
1026 SCIPsetFreeBufferArray(set, &colnames);
1027
1028 SCIPsetFreeBufferArray(set, &psind);
1029 SCIPsetFreeBufferArray(set, &pslen);
1030 SCIPsetFreeBufferArray(set, &psbeg);
1031
1032 SCIPrationalFreeBufferArray(set->buffer, &psval, psnnonz);
1033 SCIPrationalFreeBufferArray(set->buffer, &psrhs, psnrows);
1034 SCIPrationalFreeBufferArray(set->buffer, &pslhs, psnrows);
1035 SCIPrationalFreeBufferArray(set->buffer, &psub, psncols);
1036 SCIPrationalFreeBufferArray(set->buffer, &pslb, psncols);
1037 SCIPrationalFreeBufferArray(set->buffer, &psobj, psncols);
1038
1039 SCIPsetFreeBufferArray(set, &dvarincidence);
1040
1041 SCIPrationalFreeBuffer(set->buffer, &beta);
1042 SCIPrationalFreeBuffer(set->buffer, &alpha);
1043 SCIPrationalFreeBuffer(set->buffer, &tmp);
1044
1045 return SCIP_OKAY;
1046}
1047
1048/** constructs exact LP that needs to be solved to compute data for the project-and-shift method */
1049static
1050SCIP_RETCODE constructProjectShiftDataLPIExact(
1051 SCIP_LP* lp, /**< LP data */
1052 SCIP_LPEXACT* lpexact, /**< exact LP data */
1053 SCIP_SET* set, /**< scip settings */
1054 SCIP_STAT* stat, /**< statistics pointer */
1055 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1056 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1057 SCIP_PROB* prob, /**< problem data */
1058 BMS_BLKMEM* blkmem
1059 )
1060{
1061 SCIP_PROJSHIFTDATA* projshiftdata;
1062
1063 assert(lpexact != NULL);
1064 assert(lpexact->projshiftdata != NULL);
1065 assert(SCIPgetDepth(set->scip) <= 0);
1066
1067 projshiftdata = lpexact->projshiftdata;
1068
1069 /* if the LP was already constructed, exit */
1070 if( projshiftdata->lpiexact != NULL )
1071 return SCIP_OKAY;
1072
1073 SCIPdebugMessage("calling constructProjectShiftDataLPIExact()\n");
1075
1076 SCIP_CALL( SCIPrationalCreateBlock(blkmem, &projshiftdata->commonslack) );
1077
1078 /* process the bound changes */
1079 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
1080 SCIP_CALL( SCIPlpExactFlush(lp->lpexact, blkmem, set, eventqueue) );
1081
1082 projshiftdata->nextendedrows = 2*lpexact->nrows + 2*lpexact->ncols;
1083 assert(projshiftdata->nextendedrows > 1);
1084
1085 /* call function to select the set S */
1086 SCIP_CALL( projectShiftChooseDualSubmatrix(lp, lpexact, set, stat, messagehdlr, eventqueue, prob, blkmem) );
1087
1088 /* compute LU factorization of D == A|_S */
1089 SCIP_CALL( projectShiftFactorizeDualSubmatrix(lpexact, set, blkmem) );
1090
1091 SCIP_CALL( projectShiftConstructLP(lp, lpexact, set, prob, blkmem) );
1092
1094 SCIPdebugMessage("exiting constructProjectShiftDataLPIExact()\n");
1095
1096 return SCIP_OKAY;
1097}
1098
1099/** constructs data used to compute dual bounds by the project-and-shift method */
1100static
1101SCIP_RETCODE constructProjectShiftData(
1102 SCIP_LPEXACT* lpexact, /**< exact LP data */
1103 SCIP_SET* set, /**< scip settings */
1104 SCIP_STAT* stat, /**< statistics pointer */
1105 BMS_BLKMEM* blkmem
1106 )
1107{
1108 SCIP_PROJSHIFTDATA* projshiftdata;
1109
1110 assert(lpexact != NULL);
1111 assert(lpexact->projshiftdata != NULL);
1112
1113 projshiftdata = lpexact->projshiftdata;
1114
1115 /* consider the primal problem as
1116 * min c'x
1117 * lhs <= Ax <= rhs
1118 * lb <= x <= ub
1119 *
1120 * and the dual of the form
1121 * [ A', -A', I, -I] y = c
1122 * y >= 0
1123 *
1124 * A subset S of the dual columns are chosen to give a submatrix D of [A',-A',I,-I], which is then LU factorized using
1125 * rectlu code then an S-interior point is found (a dual solution that is strictly positive for each column in S).
1126 * this data is then reused throughout the tree where the LU factorization can be used to correct feasibility of
1127 * the equality constraints of the dual, and a convex combination with the S-interior point can correct any
1128 * infeasibility coming from negative variables.
1129 */
1130
1131 /* if the ps data was already constructed, exit */
1132 if( projshiftdata->projshiftdatacon )
1133 return SCIP_OKAY;
1134
1135 /* now mark that this function has been called */
1136 projshiftdata->projshiftdatacon = TRUE;
1137
1138 /* ensure that the exact LP exists that needs to be solved for obtaining the interior ray and point */
1139
1140 SCIPdebugMessage("calling constructProjectShiftData()\n");
1142
1143 /* if no fail in LU factorization, compute S-interior point and/or ray */
1144 if( !projshiftdata->projshiftdatafail )
1145 {
1146 if( projshiftdata->projshiftuseintpoint )
1147 {
1148 /* compute S-interior point if we need it */
1149 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->interiorpoint, projshiftdata->nextendedrows) );
1150 SCIP_CALL( projectShiftComputeSintPointRay(lpexact, set, stat, blkmem, TRUE) );
1151 }
1152
1153 /* always try to compute the S-interior ray (for infeasibility proofs) */
1154 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->interiorray, projshiftdata->nextendedrows) );
1155 SCIP_CALL( projectShiftComputeSintPointRay(lpexact, set, stat, blkmem, FALSE) );
1156 }
1157
1158 /* if construction of both point and ray has failed, mark projshiftdatafail as true. */
1159 if( !projshiftdata->projshifthaspoint && !projshiftdata->projshifthasray )
1160 projshiftdata->projshiftdatafail = TRUE;
1161 else
1162 projshiftdata->projshiftdatafail = FALSE;
1163
1164 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->violation, lpexact->ncols) );
1165 SCIP_CALL( SCIPrationalCreateBlockArray(blkmem, &projshiftdata->correction, projshiftdata->nextendedrows) );
1166 projshiftdata->violationsize = lpexact->ncols;
1167
1169 SCIPdebugMessage("exiting constructProjectShiftData()\n");
1170
1171 return SCIP_OKAY;
1172}
1173
1174/** computes safe dual bound by project-and-shift method or corrects dual ray for infeasibility proof */
1175static
1176SCIP_RETCODE projectShift(
1177 SCIP_LP* lp, /**< LP data */
1178 SCIP_LPEXACT* lpexact, /**< exact LP data */
1179 SCIP_SET* set, /**< scip settings */
1180 SCIP_STAT* stat, /**< statistics pointer */
1181 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
1182 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1183 SCIP_PROB* prob, /**< problem data */
1184 BMS_BLKMEM* blkmem, /**< block memory */
1185 SCIP_Bool usefarkas, /**< do we aim to prove infeasibility? */
1186 SCIP_Real* safebound /**< store the calculated safebound here */
1187 )
1188{ /*lint --e{715}*/
1189 SCIP_COL** cols;
1190 SCIP_RATIONAL** dualsol;
1191 SCIP_RATIONAL** violation;
1192 SCIP_RATIONAL** correction;
1193 SCIP_Bool useinteriorpoint;
1194 SCIP_RATIONAL* tmp;
1195 SCIP_RATIONAL* tmp2;
1196 SCIP_RATIONAL* lambda1;
1197 SCIP_RATIONAL* lambda2;
1198 SCIP_RATIONAL* maxv;
1199 SCIP_RATIONAL* dualbound;
1200 SCIP_PROJSHIFTDATA* projshiftdata;
1201 mpq_t* violationgmp = NULL;
1202 mpq_t* correctiongmp = NULL;
1203 SCIP_Real computedbound;
1204 SCIP_Bool* isupper;
1205 int i;
1206 int j;
1207 int rval;
1208 int nextendedrows;
1209 int nrows;
1210 int nrowsps; /* number of rows used for ps. this can be lower than nrows, if e.g. cuts were added */
1211 int ncols;
1212 int currentrow;
1213 int shift;
1214 SCIP_Bool isfeas;
1215
1216 assert(lp != NULL);
1217 assert(lp->solved);
1218 assert(lpexact != NULL);
1219 assert(set != NULL);
1220 assert(safebound != NULL);
1221
1222 /* project-and-shift method:
1223 * 1. projection step (to ensure that equalities are satisfied):
1224 * - compute error in equalities: r=c-Ay^
1225 * - backsolve system of equations to find correction of error: z with Dz=r
1226 * - add corretion to approximate dual solution: bold(y)=y^+[z 0]
1227 * 2. shifting step (to ensure that inequalities are satisfied):
1228 * - take convex combination of projected approximate point bold(y) with interior point y*
1229 * 3. compute dual objective value of feasible dual solution and set bound
1230 */
1231 projshiftdata = lpexact->projshiftdata;
1232
1233 /* if data has not been constructed, construct it */
1234 if( !projshiftdata->projshiftdatacon )
1235 {
1236 SCIP_CALL( constructProjectShiftData(lpexact, set, stat, blkmem) );
1237 }
1238
1239 assert(projshiftdata->projshiftdatacon);
1240
1241 /* if constructing the data failed, then exit */
1242 if( projshiftdata->projshiftdatafail || (usefarkas && !projshiftdata->projshifthasray) )
1243 {
1244 lp->hasprovedbound = FALSE;
1245 return SCIP_OKAY;
1246 }
1247
1248 /* start the timer */
1249 if( usefarkas )
1250 {
1251 stat->nprojshiftinf++;
1253 }
1254 else
1255 {
1256 stat->nprojshift++;
1258 stat->nprojshiftobjlim++;
1260 }
1261
1262 SCIPdebugMessage("calling projectShift()\n");
1263
1264 /* decide if we should use ray or point to compute bound */
1265 if( !usefarkas && projshiftdata->projshiftuseintpoint && projshiftdata->projshifthaspoint )
1266 useinteriorpoint = TRUE;
1267 else if( projshiftdata->projshifthasray )
1268 {
1269 useinteriorpoint = FALSE;
1270 }
1271 /* we either dont have a ray and want to prove infeasibility or we have neither point nor ray -> can't run */
1272 else
1273 {
1274 lp->hasprovedbound = FALSE;
1275 return SCIP_OKAY;
1276 }
1277
1278 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp) );
1279 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &tmp2) );
1280 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lambda1) );
1281 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &lambda2) );
1282 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &maxv) );
1283 SCIP_CALL( SCIPrationalCreateBuffer(set->buffer, &dualbound) );
1284
1285 /* set up the exact lpi for the current node and flush exact lp */
1286 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
1287 SCIP_CALL( SCIPlpExactFlush(lp->lpexact, blkmem, set, eventqueue) );
1288
1289 nextendedrows = projshiftdata->nextendedrows;
1290 nrows = lpexact->nrows;
1291 ncols = lpexact->ncols;
1292 nrowsps = projshiftdata->nextendedrows/2 - ncols;
1293 shift = nrows - nrowsps;
1294
1295 assert(ncols == projshiftdata->violationsize);
1296
1297 /* allocate memory for approximate dual solution, dual cost vector, violation and correction */
1298 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nrows + ncols) );
1299 violation = projshiftdata->violation;
1300 correction = projshiftdata->correction;
1301
1302 for( i = 0; i < nrows + ncols; ++i )
1303 {
1304 if( i < nrows )
1305 dualsol[i] = usefarkas ? lpexact->rows[i]->dualfarkas : lpexact->rows[i]->dualsol;
1306 else
1307 dualsol[i] = usefarkas ? lpexact->cols[i - nrows]->farkascoef : lpexact->cols[i - nrows]->redcost;
1308
1309 SCIPrationalSetFraction(dualsol[i], 0LL, 1LL);
1310 if( i < ncols )
1311 SCIPrationalSetFraction(violation[i], 0LL, 1LL);
1312 }
1313 for( i = 0; i < nextendedrows; ++i )
1314 {
1315 SCIPrationalSetFraction(correction[i], 0LL, 1LL);
1316 }
1317
1318 SCIP_CALL( SCIPsetAllocBufferArray(set, &isupper, nrows + ncols) );
1319
1320 /* recover the objective coefs and approximate solution value of dual solution;
1321 * dual vars of lhs constraints (including -inf) and rhs constraints (including +inf),
1322 * dual vars of lb constraint (including -inf) and ub constraints (including +inf)
1323 */
1324 for( i = 0; i < nrows; i++ )
1325 {
1326 if( !usefarkas )
1327 SCIPrationalSetReal(dualsol[i], SCIProwGetDualsol(lp->rows[i]));
1328 else
1329 SCIPrationalSetReal(dualsol[i], SCIProwGetDualfarkas(lp->rows[i]));
1330
1331 /* terminate in case of infinity solution */
1332 if( SCIPrationalIsAbsInfinity(dualsol[i]) )
1333 {
1334 SCIPdebugMessage(" no valid unbounded approx dual sol given\n");
1335 lp->hasprovedbound = FALSE;
1336 if( usefarkas )
1337 stat->nfailprojshiftinf++;
1338 else
1339 stat->nfailprojshift++;
1340
1341 goto TERMINATE;
1342 }
1343
1344 /* positive dual coef -> lhs, negative -> rhs */
1345 if( SCIPrationalIsPositive(dualsol[i]) )
1346 isupper[i] = FALSE;
1347 else
1348 isupper[i] = TRUE;
1349 }
1350
1351 cols = SCIPlpGetCols(lp);
1352 for( i = 0; i < ncols; i++ )
1353 {
1354 if( !usefarkas )
1355 SCIPrationalSetReal(dualsol[i+nrows], SCIPcolGetRedcost(cols[i], stat, lp));
1356 else
1357 SCIPrationalSetReal(dualsol[i+nrows], -SCIPcolGetFarkasCoef(cols[i], stat, lp));
1358
1359 /* terminate in case of infinite redcost */
1360 if( SCIPrationalIsAbsInfinity(dualsol[i + nrows]) )
1361 {
1362 SCIPdebugMessage(" no valid unbounded approx dual sol given\n");
1363 lp->hasprovedbound = FALSE;
1364 if( usefarkas )
1365 stat->nfailprojshiftinf++;
1366 else
1367 stat->nfailprojshift++;
1368
1369 goto TERMINATE;
1370 }
1371
1372 /* positive redcost -> lb, negative -> ub */
1373 if( SCIPrationalIsPositive(dualsol[i+nrows]) )
1374 isupper[i+nrows] = FALSE;
1375 else
1376 isupper[i+nrows] = TRUE;
1377 }
1378
1379 /* first, fix artificial dual variables (with infinity bound) to zero */
1380 for( i = 0; i < nrows + ncols; i++ )
1381 {
1382 SCIP_RATIONAL* val;
1383
1384 if( !isupper[i] )
1385 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
1386 else
1387 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
1388
1389 if( SCIPrationalIsAbsInfinity(val) )
1390 SCIPrationalSetFraction(dualsol[i], 0LL, 1LL);
1391 }
1392
1393#ifdef SCIP_DEBUG_PS_OUT
1394 printf("approximate dual solution:\n");
1395
1396 SCIPrationalSetFraction(dualbound, 0LL, 1LL);
1397 for( i = 0; i < nrows + ncols; i++ )
1398 {
1399 SCIP_RATIONAL* val;
1400
1401 if( !isupper[i] )
1402 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
1403 else
1404 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
1405
1406 SCIPrationalPrintf(" i=%d: %q * %q \n", i, dualsol[i], val);
1407 if( SCIPrationalIsAbsInfinity(val) )
1408 assert(SCIPrationalIsZero(dualsol[i]));
1409 else
1410 {
1411 if( i < nrows )
1412 SCIPrationalDiff(tmp, val, lpexact->rows[i]->constant);
1413 else
1414 SCIPrationalSetRational(tmp, val);
1415 SCIPrationalMult(tmp, dualsol[i], tmp);
1416 SCIPrationalAdd(dualbound, dualbound, tmp);
1417 }
1418 }
1419
1420 SCIPrationalPrintf(" objective value=%f (%q) \n", SCIPrationalGetReal(dualbound), dualbound);
1421#endif
1422
1423 /* calculate violation of equality constraints r=c-A^ty */
1424 for( i = 0; i < ncols; i++ )
1425 {
1426 /* instead of setting and then subtracting the A^ty corresponding to bound constraints, we can do this directly */
1427 if( !usefarkas )
1428 {
1429 /* set to obj - bound-redcost */
1430 SCIPrationalDiff(violation[i], lpexact->cols[i]->obj, dualsol[i + nrows]);
1431 }
1432 else
1433 {
1434 /* set to 0 - bound-redcost */
1435 SCIPrationalNegate(violation[i], dualsol[i+nrows]);
1436 }
1437 }
1438
1439 /* A^ty for y corresponding to primal constraints */
1440 for( i = 0; i < nrows; i++ )
1441 {
1442 for( j = 0; j < lpexact->rows[i]->len; j++)
1443 {
1444 currentrow = lpexact->rows[i]->cols_index[j];
1445 SCIPrationalMult(tmp, dualsol[i], lpexact->rows[i]->vals[j]);
1446 SCIPrationalDiff(violation[currentrow], violation[currentrow], tmp);
1447 }
1448 }
1449
1450 /* project solution */
1451#ifdef SCIP_DEBUG_PS_OUT
1452 printf("violation of solution:\n");
1453 for( i = 0; i < ncols; i++ )
1454 {
1455 printf(" i=%d: ", i);
1456 SCIPrationalPrint(violation[i]);
1457 printf("\n");
1458 }
1459#endif
1460
1461 /* if there is no violation of the constraints, then skip the projection */
1462 isfeas = TRUE;
1463 for( i = 0; i < ncols && isfeas; i++ )
1464 {
1465 if( !SCIPrationalIsZero(violation[i]) )
1466 isfeas = FALSE;
1467 }
1468
1469 /* isfeas is equal to one only if approximate dual solution is already feasible for the dual */
1470 if( !isfeas )
1471 {
1472 /* compute projection [z] with Dz=r (D is pre-determined submatrix of extended dual matrix [A', -A', I, -I]) */
1473 SCIP_CALL( SCIPsetAllocBufferArray(set, &violationgmp, ncols) );
1474 SCIP_CALL( SCIPsetAllocBufferArray(set, &correctiongmp, nextendedrows) );
1475 SCIPrationalSetGMPArray(violationgmp, violation, ncols);
1476
1477 for ( i = 0; i < nextendedrows; i++)
1478 {
1479 mpq_init(correctiongmp[i]);
1480 }
1481
1482#if defined SCIP_WITH_GMP && defined SCIP_WITH_EXACTSOLVE
1483 rval = RECTLUsolveSystem(projshiftdata->rectfactor, ncols, nextendedrows, violationgmp, correctiongmp);
1484#else
1485 rval = 1;
1486#endif
1487
1488 /* rval = 0 -> fail */
1489 if( rval ) /* cppcheck-suppress knownConditionTrueFalse */
1490 {
1491 lp->hasprovedbound = FALSE;
1492 if( usefarkas )
1493 stat->nfailprojshiftinf++;
1494 else
1495 stat->nfailprojshift++;
1496
1497 goto TERMINATE;
1498 }
1499
1500 SCIPrationalSetArrayGMP(correction, correctiongmp, nextendedrows);
1501
1502#ifdef SCIP_DEBUG_PS_OUT
1503 printf("correction of solution:\n");
1504 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1505 {
1506 printf(" i=%d: ", i);
1507 SCIPrationalPrint(correction[i]);
1508 printf(", position=%d\n", projshiftdata->projshiftbasis[i]);
1509 }
1510#endif
1511
1512 /* projection step: compute bold(y)=y^+[z 0];
1513 * save the corrected components in the correction vector; reset the dualsol-vector to 0
1514 */
1515 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1516 {
1517 /* map is the point in the extended space (A', -A', I, -I)-dual-matrix -> transform it back to the original space */
1518 int map = projshiftdata->projshiftbasis[i];
1519 /* [0, ..., nrows] is a lhs-row of A */
1520 if( map < nrowsps )
1521 {
1522 if( !isupper[map] )
1523 {
1524 SCIPrationalAdd(correction[i], correction[i], dualsol[map]);
1525 SCIPrationalSetFraction(dualsol[map], 0LL, 1LL);
1526 }
1527 }
1528 /* [nrows, ..., 2*nrows] is a rhs-row of A */
1529 else if( map < 2 * nrowsps )
1530 {
1531 if( isupper[map - nrowsps] )
1532 {
1533 SCIPrationalDiff(correction[i], correction[i], dualsol[map - nrowsps]);
1534 SCIPrationalSetFraction(dualsol[map - nrowsps], 0LL, 1LL);
1535 }
1536 }
1537 /* [2*nrows, ..., 2*nrows+ncols] is a lb-col */
1538 else if( map < 2 * nrowsps + ncols )
1539 {
1540 if( !isupper[map - nrowsps + shift] )
1541 {
1542 SCIPrationalAdd(correction[i], correction[i], dualsol[map - nrowsps + shift]);
1543 SCIPrationalSetFraction(dualsol[map - nrowsps + shift], 0LL, 1LL);
1544 }
1545 }
1546 /* [2*nrows+ncols, ..., 2*nrows+2*ncols] is a ub-col */
1547 else
1548 {
1549 if( isupper[map - nrowsps - ncols + shift] )
1550 {
1551 SCIPrationalDiff(correction[i], correction[i], dualsol[map - nrowsps - ncols + shift]);
1552 SCIPrationalSetFraction(dualsol[map - nrowsps - ncols + shift], 0LL, 1LL);
1553 }
1554 }
1555 }
1556
1557#ifdef SCIP_DEBUG_PS_OUT
1558 printf("updated dual solution:\n");
1559 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1560 {
1561 printf(" i=%d: ", i);
1562 SCIPrationalPrint(correction[i]);
1563 printf(", position=%d\n", projshiftdata->projshiftbasis[i]);
1564 }
1565#endif
1566
1567 if( useinteriorpoint )
1568 {
1569 assert(!usefarkas);
1570 /* shifting step (scale solution with interior point to be dual feasible):
1571 * y' = lambda1 bold(y) + lambda2 y*, where
1572 * lambda1 = MIN{( slack of int point)/ (slack of int point + max violation) = d/m+d}
1573 * lambda2 = 1 - lambda1
1574 */
1575
1576 /* compute lambda1 componentwise (set lambda1 = 1 and lower it if necessary) */
1577 SCIPrationalSetFraction(lambda1, 1LL, 1LL);
1578 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1579 {
1580 if( SCIPrationalIsNegative(correction[i]) )
1581 {
1582 int map = projshiftdata->projshiftbasis[i];
1583
1584 SCIPrationalSetRational(tmp2, projshiftdata->interiorpoint[map]);
1585 SCIPrationalDiff(tmp, projshiftdata->interiorpoint[map], correction[i]);
1586 SCIPrationalDiv(tmp2, tmp2, tmp);
1587 SCIPrationalMin(lambda1, lambda1, tmp2);
1588 }
1589 }
1590 SCIPrationalSetFraction(lambda2, 1LL, 1LL);
1591 SCIPrationalDiff(lambda2, lambda2, lambda1);
1592 }
1593 else
1594 {
1595 /* in this case we are using an interior ray that can be added freely to the solution */
1596 /* compute lambda values: compute lambda1 componentwise (set lambda1 = 1 and lower it if necessary) */
1597 SCIPrationalSetFraction(lambda1, 1LL, 1LL);
1598 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1599 {
1600 int map = projshiftdata->projshiftbasis[i];
1601 if( SCIPrationalIsNegative(correction[i]) && projshiftdata->includedrows[map] )
1602 {
1603 SCIPrationalDiv(tmp, correction[i], projshiftdata->interiorray[map]);
1604 SCIPrationalNegate(tmp, tmp);
1605 SCIPrationalMax(lambda2, lambda2, tmp);
1606 }
1607 }
1608 }
1609
1610#ifdef SCIP_DEBUG_PS_OUT
1611 printf("transformed projected dual solution:\n");
1612
1613 for( i = 0; i < nrows + ncols; i++ )
1614 {
1615 printf(" i=%d: ", i);
1616 SCIPrationalPrint(dualsol[i]);
1617 printf("\n");
1618 }
1619
1620 printf(" lambda1: ");
1621 SCIPrationalPrint(lambda1);
1622 printf(")\n");
1623#endif
1624
1625 /* tranfsorm correction back to dualsol */
1626 for( i = 0; i < projshiftdata->projshiftbasisdim; i++ )
1627 {
1628 int map = projshiftdata->projshiftbasis[i];
1629 if( map < nrowsps )
1630 SCIPrationalAdd(dualsol[map], dualsol[map], correction[i]);
1631 else if( map < 2 * nrowsps )
1632 SCIPrationalDiff(dualsol[map - nrowsps], dualsol[map - nrowsps], correction[i]);
1633 else if ( map < 2 * nrowsps + ncols )
1634 SCIPrationalAdd(dualsol[map - nrowsps + shift], dualsol[map - nrowsps + shift], correction[i]);
1635 else
1636 SCIPrationalDiff(dualsol[map - nrowsps - ncols + shift], dualsol[map - nrowsps - ncols + shift], correction[i]);
1637 }
1638
1639#ifdef SCIP_DEBUG_PS_OUT
1640 printf("transformed projected dual solution:\n");
1641
1642 for( i = 0; i < nrows + ncols; i++ )
1643 {
1644 printf(" i=%d: ", i);
1645 SCIPrationalPrint(dualsol[i]);
1646 printf("\n");
1647 }
1648
1649 printf(" lambda1: ");
1650 SCIPrationalPrint(lambda1);
1651 printf(")\n");
1652#endif
1653
1654 /* perform shift */
1655 if( !SCIPrationalIsZero(lambda2) )
1656 {
1657 for( i = 0; i < nrows + ncols; i++ )
1658 {
1659 SCIPrationalMult(dualsol[i], dualsol[i], lambda1);
1660 }
1661 for( i = 0; i < nrows + ncols; i++ )
1662 {
1663 /* explanation: when the number of lp-rows increased the number of rows in the ps-data does not.
1664 * Therefore, we have [1,...,nrows, ... extrarows ..., 1, ... ncols]
1665 * so if we map to the column part in the extended space, we have to subtract the difference */
1666 int map;
1667 if( i < nrows && i >= nrowsps )
1668 continue;
1669 map = (i < nrowsps) ? i + nrowsps : i + nrowsps + ncols - shift;
1670 SCIPrationalMult(tmp, useinteriorpoint ? projshiftdata->interiorpoint[map] : projshiftdata->interiorray[map], lambda2);
1671 SCIPrationalDiff(dualsol[i], dualsol[i], tmp);
1672 map = (i < nrowsps) ? i : i + nrowsps - shift;
1673 SCIPrationalMult(tmp, useinteriorpoint ? projshiftdata->interiorpoint[map] : projshiftdata->interiorray[map], lambda2);
1674 SCIPrationalAdd(dualsol[i], dualsol[i], tmp);
1675 }
1676 }
1677
1678#ifdef SCIP_DEBUG_PS_OUT
1679 printf("projected and shifted dual solution (should be an exact dual feasible solution)\n");
1680 for( i = 0; i < nrows+ncols; i++ )
1681 {
1682 SCIPrationalPrintf(" i=%d: %f.20 (%q) \n", i, SCIPrationalGetReal(dualsol[i]), dualsol[i]);
1683 }
1684#endif
1685 }
1686
1687#ifndef NDEBUG
1688 SCIPdebugMessage("debug test: verifying feasibility of dual solution:\n");
1689
1690 /* calculate violation of equality constraints: subtract Ax to get violation b-Ax, subtract A(dualsol) */
1691 rval = 0;
1692 for( i = 0; i < ncols; i++ )
1693 {
1694 if( !usefarkas )
1695 SCIPrationalSetRational(violation[i], lpexact->cols[i]->obj);
1696 else
1697 SCIPrationalSetFraction(violation[i], 0LL, 1LL);
1698 }
1699 for( i = 0; i < nrows; i++ )
1700 {
1701 if( !SCIPrationalIsZero(dualsol[i]) )
1702 {
1703 SCIPrationalDebugMessage("row %s has multiplier %q: ", lpexact->rows[i]->fprow->name, dualsol[i]);
1704 SCIPdebug(SCIProwExactPrint(lpexact->rows[i], messagehdlr, NULL));
1705 }
1706 for( j = 0; j < lpexact->rows[i]->len; j++ )
1707 {
1708 currentrow = lpexact->rows[i]->cols_index[j];
1709 SCIPrationalMult(tmp, dualsol[i], lpexact->rows[i]->vals[j]);
1710 SCIPrationalDiff(violation[currentrow], violation[currentrow], tmp);
1711 }
1712 }
1713 for( i = 0; i < ncols; i++ )
1714 {
1715 if( !SCIPrationalIsZero(lpexact->cols[i]->farkascoef) )
1716 {
1717 SCIPrationalDebugMessage("variable %q <= %s <= %q has farkas coefficient %q \n", lpexact->cols[i]->lb,
1718 SCIPvarGetName(lpexact->cols[i]->var), lpexact->cols[i]->ub, lpexact->cols[i]->farkascoef);
1719 }
1720 SCIPrationalDiff(violation[i], violation[i], dualsol[i + nrows]);
1721 }
1722
1723 for( i = 0; i < ncols && rval == 0; i++ )
1724 {
1725 if( !SCIPrationalIsZero(violation[i]) )
1726 {
1727 SCIPdebugMessage(" dual solution incorrect, violates equalities\n");
1728 rval = 1;
1729 }
1730 }
1731 if( !rval )
1732 SCIPdebugMessage(" dual solution verified\n");
1733 assert(!rval);
1734#endif
1735
1736 SCIPrationalSetFraction(dualbound, 0LL, 1LL);
1737 for( i = 0; i < nrows + ncols; i++ )
1738 {
1739 SCIP_RATIONAL* val;
1740 if( SCIPrationalIsPositive(dualsol[i]) )
1741 val = i < nrows ? lpexact->rows[i]->lhs : lpexact->cols[i - nrows]->lb;
1742 else
1743 val = i < nrows ? lpexact->rows[i]->rhs : lpexact->cols[i - nrows]->ub;
1744
1745 if( i < nrows )
1746 SCIPrationalDiff(tmp, val, lpexact->rows[i]->constant);
1747 else
1748 SCIPrationalSetRational(tmp, val);
1749 SCIPrationalMult(tmp, dualsol[i], tmp);
1750 SCIPrationalAdd(dualbound, dualbound, tmp);
1751 }
1752
1753 /* since we negate the farkas-coef for the project-shift representation, it has to be negated again here for saving */
1754 if( usefarkas )
1755 {
1756 for( i = nrows; i < ncols + nrows; i++ )
1757 {
1758 SCIPrationalNegate(dualsol[i], dualsol[i]);
1759 }
1760 }
1761
1762 computedbound = SCIPrationalRoundReal(dualbound, SCIP_R_ROUND_DOWNWARDS);
1763
1764 if( !usefarkas )
1765 {
1767 && computedbound < SCIPlpGetCutoffbound(lp) - SCIPlpGetLooseObjval(lp, set, prob) )
1768 {
1769 *safebound = computedbound;
1770 stat->nfailprojshift++;
1771 stat->nprojshiftobjlimfail++;
1772 assert(!lp->hasprovedbound);
1773 }
1774 else if( SCIPrationalIsGTReal(dualbound, -SCIPsetInfinity(set)) )
1775 {
1776 stat->boundingerrorps += REALABS(lp->lpobjval - computedbound);
1777 SCIPrationalSetRational(lpexact->lpobjval, dualbound);
1778 *safebound = computedbound;
1779 lp->lpobjval = *safebound;
1780 lp->hasprovedbound = TRUE;
1781 }
1782 else
1783 {
1784 lp->hasprovedbound = FALSE;
1785 stat->nfailprojshift++;
1786 }
1787 }
1788 else
1789 {
1790 /* if the objective value of the corrected ray is positive we can prune node, otherwise not */
1791 if( SCIPrationalIsPositive(dualbound) )
1792 {
1795 lp->hasprovedbound = TRUE;
1796 }
1797 else
1798 {
1799 stat->nfailprojshiftinf++;
1800 lp->hasprovedbound = FALSE;
1801 }
1802 }
1803
1804#ifdef SCIP_DEBUG_PS_OUT
1805 printf(" common slack=%.20f (", SCIPrationalGetReal(projshiftdata->commonslack));
1806 SCIPrationalPrint(projshiftdata->commonslack);
1807 printf(")\n");
1808
1809 printf(" max violation=%.20f (", SCIPrationalGetReal(maxv));
1810 SCIPrationalPrint(maxv);
1811 printf(")\n");
1812
1813 printf(" lambda (use of interior point)=%.20f (", SCIPrationalGetReal(lambda2));
1814 SCIPrationalPrint(lambda2);
1815 printf(")\n");
1816
1817 printf(" dual objective value=%.20f (", SCIPrationalGetReal(dualbound));
1818 SCIPrationalPrint(dualbound);
1819 printf(")\n");
1820#endif
1821
1822 TERMINATE:
1823 /* free memory */
1824 if( correctiongmp != NULL )
1825 {
1826 SCIPrationalClearArrayGMP(correctiongmp, nextendedrows);
1827 SCIPsetFreeBufferArray(set, &correctiongmp);
1828 }
1829 if( violationgmp != NULL )
1830 {
1831 SCIPrationalClearArrayGMP(violationgmp, ncols);
1832 SCIPsetFreeBufferArray(set, &violationgmp);
1833 }
1834
1835 SCIPsetFreeBufferArray(set, &isupper);
1836 SCIPsetFreeBufferArray(set, &dualsol);
1837
1838 SCIPrationalFreeBuffer(set->buffer, &dualbound);
1839 SCIPrationalFreeBuffer(set->buffer, &maxv);
1840 SCIPrationalFreeBuffer(set->buffer, &lambda2);
1841 SCIPrationalFreeBuffer(set->buffer, &lambda1);
1842 SCIPrationalFreeBuffer(set->buffer, &tmp2);
1843 SCIPrationalFreeBuffer(set->buffer, &tmp);
1844
1845 if( usefarkas )
1847 else
1849
1850 return SCIP_OKAY;
1851}
1852#endif
1853
1854/** chooses which bounding method to use at first attempt to provide safe bound for current lp */
1855static
1856char chooseInitialBoundingMethod(
1857 SCIP_LPEXACT* lpexact, /**< exact LP data */
1858 SCIP_SET* set, /**< global SCIP settings */
1859 SCIP_STAT* stat, /**< SCIP statistics */
1860 SCIP_PROB* prob /**< problem data */
1861 )
1862{
1863 char dualboundmethod;
1864 SCIP_Bool interleavedepth;
1865 SCIP_Bool interleavecutoff;
1866
1867 assert(lpexact != NULL);
1868 assert(set != NULL);
1869
1870 /* at the root node always call exact LP solve if allowed, i.e., after separation */
1871 if( set->scip->stat->nnodes == 1 && lpexact->allowexactsolve )
1872 dualboundmethod = 'e';
1873 /* check for other reasons to solve exactly */
1874 else if( lpexact->forceexactsolve || SCIPlpGetSolstat(lpexact->fplp) == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
1875 dualboundmethod = 'e';
1876 /* if the LP was solved to optimality and there are no fractional variables we solve exactly to generate a feasible
1877 * solution
1878 */
1879 else if( (SCIPlpGetSolstat(lpexact->fplp) == SCIP_LPSOLSTAT_OPTIMAL && fpLPisIntFeasible(lpexact->fplp, set)) && lpexact->allowexactsolve )
1880 {
1881 dualboundmethod = 'e';
1882 stat->nexlpintfeas++;
1883 }
1884 /* if we are not in automatic mode, try an iteration with the static method */
1885 else if( set->exact_safedbmethod != 'a' )
1886 {
1887 dualboundmethod = set->exact_safedbmethod;
1888 }
1889 /* select automatically which bounding method to apply */
1890 else
1891 {
1892 /* decide whether we want to interleave with exact LP call given freq: we do this if we are
1893 * a) at depth levels 2, 4, 8, 16, ..., or
1894 * b) almost at cutoffbound
1895 */
1896 interleavedepth = set->exact_interleavedbstrat >= 2 && SCIPgetDepth(set->scip) > 1 && isPowerOfTwo(SCIPgetDepth(set->scip));
1897 interleavecutoff = (set->exact_interleavedbstrat == 1 || set->exact_interleavedbstrat == 3)
1898 && SCIPsetIsGE(set, SCIPlpGetObjval(lpexact->fplp, set, prob), SCIPlpGetCutoffbound(lpexact->fplp))
1899 && SCIPlpGetObjval(lpexact->fplp, set, prob) < SCIPlpGetCutoffbound(lpexact->fplp);
1900 if( (interleavedepth || interleavecutoff) && lpexact->allowexactsolve )
1901 {
1902 if( interleavedepth )
1903 stat->nexlpinter++;
1904 else
1905 stat->nexlpboundexc++;
1906 dualboundmethod = 'e';
1907 }
1908 else
1909 {
1910 /* check if Neumaier-Shcherbina is possible */
1911 if( SCIPlpExactBoundShiftUseful(lpexact) )
1912 dualboundmethod = 'n';
1913 /* check if project and shift is possible */
1914 else if( SCIPlpExactProjectShiftPossible(lpexact) )
1915 dualboundmethod = 'p';
1916 /* otherwise solve exactly */
1917 else
1918 dualboundmethod = 'e';
1919 }
1920 }
1921
1922 assert(dualboundmethod != 'u');
1923
1924 return dualboundmethod;
1925}
1926
1927/** chooses which bounding method to use after failed attempt to provide safe bound for current lp */
1928static
1929char chooseFallbackBoundingMethod(
1930 SCIP_LPEXACT* lpexact, /**< exact LP data */
1931 SCIP_SET* set, /**< global SCIP settings */
1932 char lastboundmethod /**< last attempted dual bounding method */
1933 )
1934{
1935 char dualboundmethod;
1936
1937 assert(lpexact != NULL);
1938 assert(set != NULL);
1939
1940 switch( lastboundmethod )
1941 {
1942 case 'n':
1943 /* bound-shift -> try project shift next if possible, otherwise exactlp */
1944 dualboundmethod = SCIPlpExactProjectShiftPossible(lpexact) ? 'p' : 'e';
1945 break;
1946 case 'p':
1947 /* project-shift -> try exactlp next */
1948 dualboundmethod = 'e';
1949 break;
1950 case 'e':
1951 /* exactlp -> try bound shift next, if possible, otherwise project-shift, if possible,
1952 * otherwise try exactlp again
1953 */
1954 if( SCIPlpExactBoundShiftUseful(lpexact) )
1955 dualboundmethod = 'n';
1956 else
1957 dualboundmethod = SCIPlpExactProjectShiftPossible(lpexact) ? 'p' : 't';
1958 break;
1959 default:
1960 /* else -> return unknown */
1961 SCIPerrorMessage("unknown bounding method in chooseBoundingMethod \n");
1962 SCIPABORT();
1963 dualboundmethod = 't';
1964 break;
1965 }
1966
1967 return dualboundmethod;
1968}
1969
1970/* choose the next bounding method for safe dual bounding */
1971static
1972char chooseBoundingMethod(
1973 SCIP_LPEXACT* lpexact, /**< exact LP data */
1974 SCIP_SET* set, /**< global SCIP settings */
1975 SCIP_STAT* stat, /**< SCIP statistics */
1976 SCIP_PROB* prob, /**< problem data */
1977 char lastboundmethod /**< the last method that was chosen */
1978 )
1979{
1980 assert(!lpexact->fplp->hasprovedbound);
1981
1982 /* choose which bounding method to use */
1983 if( lastboundmethod == 'u' )
1984 return chooseInitialBoundingMethod(lpexact, set, stat, prob);
1985 else
1986 return chooseFallbackBoundingMethod(lpexact, set, lastboundmethod);
1987}
1988
1989/** calculates a valid dual bound/farkas proof if all variables have lower and upper bounds
1990 * Let (y,z) be the dual variables, y corresponding to primal rows, z to variable bounds.
1991 * An exactly feasible dual solution is computed with y' = max{0,y}, z'=max{0,(c-A^Ty')}.
1992 * The bound is then computed as b^Ty'+s^Tz', with b being the lhs/rhs and s the lb/ub depending on the
1993 * sign of the dual value.
1994 * To avoid rational computations everything is done in interval arithmetic.
1995 */
1996static
1997SCIP_RETCODE boundShift(
1998 SCIP_LP* lp, /**< LP data */
1999 SCIP_LPEXACT* lpexact, /**< exact LP data */
2000 SCIP_SET* set, /**< global SCIP settings */
2001 BMS_BLKMEM* blkmem, /**< block memory buffers */
2002 SCIP_STAT* stat, /**< problem statistics */
2003 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2004 SCIP_PROB* prob, /**< problem data */
2005 SCIP_Bool usefarkas, /**< should an infeasibility proof be computed? */
2006 SCIP_Real* safebound /**< pointer to store the computed safe bound (usually lpobj) */
2007 )
2008{
2009 SCIP_INTERVAL* rhslhsrow;
2010 SCIP_INTERVAL* ublbcol;
2011 SCIP_INTERVAL* constantinter;
2012 SCIP_INTERVAL* lpcolvals;
2013 SCIP_INTERVAL* productcoldualval;
2014 SCIP_INTERVAL* obj;
2015 SCIP_INTERVAL productsidedualval;
2016 SCIP_INTERVAL safeboundinterval;
2017 SCIP_ROW* row;
2018 SCIP_COL* col;
2019 SCIP_COLEXACT* colexact;
2020 SCIP_Real* fpdual;
2021 SCIP_Real* fpdualcolwise;
2022 SCIP_Real computedbound;
2023 int i;
2024 int j;
2025
2026 assert(lp != NULL);
2027 assert(lp->solved);
2028 assert(lpexact != NULL);
2029 assert(set != NULL);
2030 assert(safebound != NULL);
2031
2032 if( !SCIPlpExactBoundShiftUseful(lpexact) )
2033 return SCIP_OKAY;
2034
2035 /* start timing */
2036 if ( usefarkas )
2038 else
2040
2041 /* allocate temporarfpdual memory */
2042 SCIP_CALL( SCIPsetAllocBufferArray(set, &fpdual, lp->nrows) );
2043 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhslhsrow, lp->nrows) );
2044 SCIP_CALL( SCIPsetAllocBufferArray(set, &constantinter, lp->nrows) );
2045 SCIP_CALL( SCIPsetAllocBufferArray(set, &fpdualcolwise, lp->nrows) );
2046 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpcolvals, lp->nrows) );
2047 SCIP_CALL( SCIPsetAllocBufferArray(set, &productcoldualval, lp->ncols) );
2049 SCIP_CALL( SCIPsetAllocBufferArray(set, &ublbcol, lp->ncols) );
2050
2051 SCIPdebugMessage("calling proved bound for %s LP\n", usefarkas ? "infeasible" : "feasible");
2052
2053 SCIP_CALL( SCIPlpExactSyncLPs(lpexact, blkmem, set) );
2054 SCIP_CALL( SCIPlpExactLink(lpexact, blkmem, set, eventqueue) );
2055
2056 /* reset proved bound status */
2057 lp->hasprovedbound = FALSE;
2058
2059 /* calculate y^Tb */
2060 SCIPintervalSet(&productsidedualval, 0.0);
2061 SCIPdebugMessage("productsidedualval interval computation with vectors:\n");
2062
2063 /* create dual vector, sides and constant vector in interval arithmetic */
2064 for( j = 0; j < lp->nrows; ++j )
2065 {
2066 row = lp->rows[j];
2067 assert(row != NULL);
2068
2069 /* create dual vector in interval arithmetic, setting near zeros to zero */
2070 fpdual[j] = (usefarkas ? row->dualfarkas : row->dualsol);
2071
2072 if( SCIPlpiIsInfinity(lp->lpi, fpdual[j]) )
2073 fpdual[j] = SCIPsetInfinity(set);
2074
2075 if( SCIPlpiIsInfinity(lp->lpi, -fpdual[j]) )
2076 fpdual[j] = -SCIPsetInfinity(set);
2077
2078 /** @todo test whether safe dual bounding in exact solving mode can be improved by setting nonzero values of y to
2079 * zero if corresponding lhs/rhs is not finite (do such situations come up?)
2080 */
2081 /* create sides and constant vectors in interval arithmetic */
2082 if( SCIPsetIsFeasPositive(set, fpdual[j]) )
2083 {
2084 SCIPintervalSet(&rhslhsrow[j], row->lhs);
2085 SCIPintervalSet(&constantinter[j], -1.0 * row->constant);
2086 }
2087 else if( SCIPsetIsFeasNegative(set, fpdual[j]) )
2088 {
2089 SCIPintervalSet(&rhslhsrow[j], row->rhs);
2090 SCIPintervalSet(&constantinter[j], -1.0 * row->constant);
2091 }
2092 else
2093 {
2094 fpdual[j] = 0.0;
2095 SCIPintervalSet(&rhslhsrow[j], 0.0);
2096 SCIPintervalSet(&constantinter[j], 0.0);
2097 }
2098
2099 SCIPdebugMessage(" j=%d: b=[%g,%g] (lhs=%g, rhs=%g, const=%g, fpdual=%g)\n", j, rhslhsrow[j].inf, rhslhsrow[j].sup, row->lhs,
2100 row->rhs, row->constant, fpdual[j]);
2101 }
2102 /* subtract constant from sides in interval arithmetic and calculate fpdual * side */
2103 SCIPintervalAddVectors(SCIPsetInfinity(set), rhslhsrow, lp->nrows, rhslhsrow, constantinter);
2104 SCIPintervalScalprodScalars(SCIPsetInfinity(set), &productsidedualval, lp->nrows, rhslhsrow, fpdual);
2105
2106 SCIPdebugMessage(" resulting scalar product=[%g,%g]\n", SCIPintervalGetInf(productsidedualval), SCIPintervalGetSup(productsidedualval));
2107
2108 /* calculate min{(obj - dual^TMatrix)redcost} */
2109 for( j = 0; j < lp->ncols; ++j )
2110 {
2111 col = lp->cols[j];
2112 assert(col != NULL);
2113 assert(col->nunlinked == 0);
2114
2115 colexact = SCIPcolGetColExact(col);
2116
2117 assert(colexact != NULL);
2118
2119 /* create -Matrix.j vector in interval arithmetic and corresponding dual vector and compute infimum of vector -Matrix.j^Tdual */
2120 for( i = 0; i < colexact->nlprows; ++i )
2121 {
2122 SCIP_INTERVAL val;
2123 SCIP_ROWEXACT* rowexact;
2124
2125 assert(colexact->rows[i] != NULL);
2126 assert(colexact->rows[i]->lppos >= 0);
2127 assert(colexact->linkpos[i] >= 0);
2128
2129 rowexact = colexact->rows[i];
2130
2131 val = rowexact->valsinterval[colexact->linkpos[i]];
2132 assert(SCIPrationalIsGEReal(colexact->vals[i], val.inf) && SCIPrationalIsLEReal(colexact->vals[i], val.sup));
2133
2134 SCIPintervalSetBounds(&lpcolvals[i], -val.sup, -val.inf);
2135 fpdualcolwise[i] = fpdual[colexact->rows[i]->lppos];
2136 }
2137 productcoldualval[j].inf = 0.0;
2138 productcoldualval[j].sup = 0.0;
2139 SCIPintervalScalprodScalars(SCIPsetInfinity(set), &productcoldualval[j], colexact->nlprows, lpcolvals, fpdualcolwise);
2140
2141#ifndef NDEBUG
2142 for( i = colexact->nlprows; i < colexact->len; ++i )
2143 {
2144 assert(colexact->rows[i] != NULL);
2145 assert(colexact->rows[i]->lppos == -1);
2146 assert(colexact->linkpos[i] >= 0);
2147 }
2148#endif
2149 }
2150
2151 /* create objective vector and lb/ub vector in interval arithmetic and compute min{(obj^T - dual^TMatrix)lb/ub} */
2152 for( j = 0; j < lp->ncols; ++j )
2153 {
2154 col = lp->cols[j];
2155 assert(col != NULL);
2156 assert(col->nunlinked == 0);
2157
2158 if( usefarkas )
2159 SCIPintervalSet(&obj[j], 0.0);
2160 else
2161 {
2162 obj[j] = SCIPvarGetObjInterval(SCIPcolGetVar(col));
2165 }
2166
2169 SCIPintervalSetBounds(&ublbcol[j], SCIPcolGetLb(col), SCIPcolGetUb(col));
2170
2171 /* opt out if there are infinity bounds and a non-infinity value */
2173 {
2174 if( productcoldualval[j].inf + obj[j].inf != 0 || productcoldualval[j].sup + obj[j].sup != 0 )
2175 {
2176 SCIPdebugMessage("trying bound shift with unbounded column variable. Column %d, lb: %e, ub %e \n",
2177 SCIPcolGetIndex(col), SCIPcolGetLb(col) ,SCIPcolGetUb(col) );
2178 SCIPdebugMessage("Multiplied with interval: min %e, max %e \n",
2179 productcoldualval[j].inf + obj[j].inf, productcoldualval[j].sup + obj[j].sup);
2180
2181 lp->hasprovedbound = FALSE;
2182 if( usefarkas )
2183 {
2184 stat->nboundshiftinf++;
2185 stat->nfailboundshiftinf++;
2187 }
2188 else
2189 {
2190 stat->nboundshift++;
2191 stat->nfailboundshift++;
2193 }
2194 goto CLEANUP;
2195 }
2196 }
2197 }
2198
2199 SCIPintervalAddVectors(SCIPsetInfinity(set), productcoldualval, lp->ncols, productcoldualval, obj);
2200 SCIPintervalScalprod(SCIPsetInfinity(set), &safeboundinterval, lp->ncols, productcoldualval, ublbcol);
2201
2202 /* add dualsol * rhs/lhs (or farkas * rhs/lhs) */
2203 SCIPintervalAdd(SCIPsetInfinity(set), &safeboundinterval, safeboundinterval, productsidedualval);
2204
2205 computedbound = SCIPintervalGetInf(safeboundinterval);
2206 SCIPdebugMessage("safebound computed: %e, previous fp-bound: %e, difference %e \n", computedbound, lp->lpobjval, computedbound - lp->lpobjval);
2207
2208 /* stop timing and update number of calls and fails, and proved bound status */
2209 if ( usefarkas )
2210 {
2212 stat->nboundshiftinf++;
2213 *safebound = computedbound;
2214 if( computedbound <= 0.0 )
2215 {
2216 stat->nfailboundshiftinf++;
2217 assert(!lp->hasprovedbound);
2218 }
2219 else
2220 {
2222 lp->hasprovedbound = TRUE;
2223 SCIPdebugMessage("succesfully proved infeasibility \n");
2224 }
2226 }
2227 else
2228 {
2230 stat->nboundshift++;
2232 stat->nboundshiftobjlim++;
2233 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && computedbound < SCIPlpGetCutoffbound(lp) - SCIPlpGetLooseObjval(lp, set, prob) )
2234 {
2235 *safebound = computedbound;
2236 stat->nfailboundshift++;
2237 stat->nboundshiftobjlimfail++;
2238 assert(!lp->hasprovedbound);
2239 SCIPrationalSetReal(lpexact->lpobjval, SCIPintervalGetInf(safeboundinterval));
2240 }
2241 else if( !SCIPsetIsInfinity(set, -1.0 * (computedbound)) )
2242 {
2243 stat->boundingerrorbs += REALABS(lp->lpobjval - computedbound);
2244 *safebound = computedbound;
2245 lp->hasprovedbound = TRUE;
2246 SCIPrationalSetReal(lpexact->lpobjval, SCIPintervalGetInf(safeboundinterval));
2247 }
2248 else
2249 {
2250 stat->nfailboundshift++;
2251 assert(!lp->hasprovedbound);
2252 }
2253 }
2254
2255 /* if certificate is active, save the corrected dual solution into the lpexact data */
2256 if( SCIPisCertified(set->scip) && lp->hasprovedbound )
2257 {
2258 /* set up the exact lpi for the current node */
2259 for( j = 0; j < lpexact->nrows; j++ )
2260 {
2261 if( usefarkas )
2262 SCIPrationalSetReal(lpexact->rows[j]->dualfarkas, fpdual[j]);
2263 else
2264 SCIPrationalSetReal(lpexact->rows[j]->dualsol, fpdual[j]);
2265 }
2266
2267 for( j = 0; j < lpexact->ncols; j++ )
2268 {
2269 colexact = lpexact->cols[j];
2270 /* Since VIPR only detects that a constraint cTx>=b dominates some other constraint c'Tx>=b' if c==c', we
2271 * recompute the exact coefficients for the bound constraints here.
2272 */
2273 /** @todo Avoid recomputation by using weak completion in VIPR. */
2274 if( usefarkas )
2275 SCIP_CALL( SCIPcolExactCalcFarkasRedcostCoef(colexact, set, colexact->farkascoef, NULL, usefarkas) );
2276 else
2277 SCIP_CALL( SCIPcolExactCalcFarkasRedcostCoef(colexact, set, colexact->redcost, NULL, usefarkas) );
2278 }
2279 }
2280
2281CLEANUP:
2282
2283 /* if the fail percentage is higher than 20 % we do not want to waste time trying bound shift again and again */
2284 if( stat->nboundshift + stat->nboundshiftinf > 10
2285 && (1.0 * stat->nfailboundshift + stat->nfailboundshiftinf) / (stat->nboundshift + stat->nboundshiftinf) > 0.8 )
2286 {
2287 lpexact->boundshiftuseful = FALSE;
2288 }
2289 /* free buffer for storing y in interval arithmetic */
2290 SCIPsetFreeBufferArray(set, &ublbcol);
2292 SCIPsetFreeBufferArray(set, &productcoldualval);
2293 SCIPsetFreeBufferArray(set, &lpcolvals);
2294 SCIPsetFreeBufferArray(set, &fpdualcolwise);
2295 SCIPsetFreeBufferArray(set, &constantinter);
2296 SCIPsetFreeBufferArray(set, &rhslhsrow);
2297 SCIPsetFreeBufferArray(set, &fpdual);
2298
2299 return SCIP_OKAY;
2300}
2301#endif
2302
2303/** computes a safe bound for the current floating point LP */
2305 SCIP_LP* lp, /**< LP data */
2306 SCIP_LPEXACT* lpexact, /**< exact LP data */
2307 SCIP_SET* set, /**< global SCIP settings */
2308 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2309 BMS_BLKMEM* blkmem, /**< block memory buffers */
2310 SCIP_STAT* stat, /**< problem statistics */
2311 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2312 SCIP_PROB* prob, /**< problem data */
2313 SCIP_Bool* lperror, /**< pointer to store whether an unresolved LP error occurred */
2314 SCIP_Bool usefarkas, /**< should infeasibility be proven? */
2315 SCIP_Real* safebound, /**< pointer to store the calculated safe bound */
2316 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
2317 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
2318 ) /*lint --e{715}*/
2319{ /*lint --e{715}*/
2320#ifdef SCIP_WITH_BOOST
2321 char dualboundmethod;
2322 char lastboundmethod;
2323 SCIP_Bool shouldabort;
2324 int nattempts;
2325
2326 /* if we are not in exact solving mode, just return */
2327 if( !set->exact_enable )
2328 return SCIP_OKAY;
2329
2330 if( !lpexact->forcesafebound && (lp->diving || lp->probing || lp->strongbranchprobing) )
2331 return SCIP_OKAY;
2332
2333 lastboundmethod = 'u';
2334 shouldabort = FALSE;
2335 nattempts = 0;
2336
2337 assert(set->exact_enable);
2338 assert(!lp->hasprovedbound);
2339
2340 /* we need to construct projshiftdata at the root node */
2341 if( SCIPgetDepth(set->scip) <= 0 && lpexact->projshiftdata->lpiexact == NULL
2342 && !lpexact->projshiftdata->projshiftdatacon && !lpexact->projshiftdata->projshiftdatafail )
2343 {
2344#ifdef SCIP_WITH_GMP
2345 SCIP_CALL( constructProjectShiftDataLPIExact(lp, lpexact, set, stat, messagehdlr, eventqueue, prob,
2346 blkmem) );
2347#endif
2348 }
2349
2350 while( (!lp->hasprovedbound && !shouldabort) || lpexact->allowexactsolve )
2351 {
2352 dualboundmethod = chooseBoundingMethod(lpexact, set, stat, prob, lastboundmethod);
2353 SCIPdebugMessage("Computing safe bound for LP with status %d using bounding method %c\n",
2354 SCIPlpGetSolstat(lp), dualboundmethod);
2355
2356 /* reset the allow exact solve status */
2358 nattempts++;
2359
2360 /*
2361 * For the methods used please refer to
2362 * "Valid Linear Programming Bounds for Exact Mixed-Integer Programming" from Steffy and Wolter (2011)
2363 */
2364 switch( dualboundmethod )
2365 {
2366 case 'n':
2367 /* Safe Bounding introduced by Neumaier and Shcherbina (Chapter 2)*/
2368 *lperror = FALSE;
2369 SCIP_CALL( boundShift(lp, lpexact, set, blkmem, stat, eventqueue,
2370 prob, usefarkas, safebound) );
2371 break;
2372 #ifdef SCIP_WITH_GMP
2373 case 'p':
2374 /* Project-and-Shift (Chapter 3)*/
2375 *lperror = FALSE;
2376 SCIP_CALL( projectShift(lp, lpexact, set, stat, messagehdlr, eventqueue,
2377 prob, blkmem, usefarkas, safebound) );
2378 break;
2379 #endif
2380 case 'e':
2381 /* exact LP */
2382 SCIP_CALL( SCIPlpExactSolveAndEval(lpexact, lp, set, messagehdlr, blkmem, stat, eventqueue,
2383 prob, set->lp_iterlim, lperror, usefarkas) );
2384 if( *lperror )
2385 {
2386 if( !usefarkas )
2387 stat->nfailexlp++;
2388 else
2389 stat->nfailexlpinf++;
2390 }
2391 *primalfeasible = lpexact->primalfeasible;
2392 *dualfeasible = lpexact->dualfeasible;
2393 break;
2394 case 't':
2395 /* terminate */
2396 SCIPdebugMessage("could not find suitable bounding method \n");
2397 break;
2398 default:
2399 SCIPerrorMessage("bounding method %c not implemented yet \n", dualboundmethod);
2400 SCIPABORT();
2401 break;
2402 }
2403
2404 lastboundmethod = dualboundmethod;
2405
2406 /* we fail if we tried all available methods, or if we had to solve the lp exactly but could not */
2407 if( (lpexact->forceexactsolve && (*lperror)) || (nattempts >= 3 && !lp->hasprovedbound) || (lastboundmethod == 't') )
2408 {
2409 SCIPdebugMessage("failed safe bounding call after %d attempts to compute safe bound\n", nattempts);
2410 shouldabort = TRUE;
2411 *lperror = TRUE;
2412 }
2413 if( lpexact->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT )
2414 shouldabort = TRUE;
2415 }
2416#endif
2417 if( *lperror && lp->lpsolstat != SCIP_LPSOLSTAT_TIMELIMIT && lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT )
2418 {
2419 lp->solved = FALSE;
2421 }
2422
2423 /* reset the forceexactsolve flag */
2424 lpexact->forceexactsolve = FALSE;
2425 lpexact->wasforcedsafebound = lpexact->forcesafebound;
2426 lpexact->forcesafebound = FALSE;
2427 if( lp->hasprovedbound )
2428 *dualfeasible = TRUE;
2429
2430 return SCIP_OKAY;
2431}
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:438
internal methods for clocks and timing issues
#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 SCIP_ALLOC(x)
Definition: def.h:366
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIPABORT()
Definition: def.h:327
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPlpiExactSetRealpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, SCIP_Real dval)
SCIP_RETCODE SCIPlpiExactSolveDual(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactSetIntpar(SCIP_LPIEXACT *lpi, SCIP_LPPARAM type, int ival)
SCIP_Real SCIPlpiExactInfinity(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactAddRows(SCIP_LPIEXACT *lpi, int nrows, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs, char **rownames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPlpiExactCreate(SCIP_LPIEXACT **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
SCIP_Bool SCIPlpiExactIsOptimal(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactAddCols(SCIP_LPIEXACT *lpi, int ncols, SCIP_RATIONAL **obj, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub, char **colnames, int nnonz, int *beg, int *ind, SCIP_RATIONAL **val)
SCIP_RETCODE SCIPlpiExactDelCols(SCIP_LPIEXACT *lpi, int firstcol, int lastcol)
SCIP_RETCODE SCIPlpiExactChgObj(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **obj)
SCIP_RETCODE SCIPlpiExactClear(SCIP_LPIEXACT *lpi)
SCIP_RETCODE SCIPlpiExactFree(SCIP_LPIEXACT **lpi)
SCIP_RETCODE SCIPlpiExactGetNCols(SCIP_LPIEXACT *lpi, int *ncols)
SCIP_RETCODE SCIPlpiExactChgSides(SCIP_LPIEXACT *lpi, int nrows, int *ind, SCIP_RATIONAL **lhs, SCIP_RATIONAL **rhs)
SCIP_RETCODE SCIPlpiExactDelRows(SCIP_LPIEXACT *lpi, int firstrow, int lastrow)
SCIP_RETCODE SCIPlpiExactGetNRows(SCIP_LPIEXACT *lpi, int *nrows)
SCIP_RETCODE SCIPlpiExactChgBounds(SCIP_LPIEXACT *lpi, int ncols, int *ind, SCIP_RATIONAL **lb, SCIP_RATIONAL **ub)
SCIP_RETCODE SCIPlpiExactGetSol(SCIP_LPIEXACT *lpi, SCIP_RATIONAL *objval, SCIP_RATIONAL **primsol, SCIP_RATIONAL **dualsol, SCIP_RATIONAL **activity, SCIP_RATIONAL **redcost)
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_clp.cpp:3959
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:120
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17425
int SCIPcolGetIndex(SCIP_COL *col)
Definition: lp.c:17435
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:17346
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:17379
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:17356
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
void SCIPintervalScalprodScalars(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_Real *operand2)
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
void SCIPintervalAddVectors(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_INTERVAL *operand2)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalScalprod(SCIP_Real infinity, SCIP_INTERVAL *resultant, int length, SCIP_INTERVAL *operand1, SCIP_INTERVAL *operand2)
void SCIPrationalMin(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1342
SCIP_RETCODE SCIPrationalCreateBlock(BMS_BLKMEM *blkmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:108
void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1066
void SCIPrationalPrint(SCIP_RATIONAL *rational)
Definition: rational.cpp:1831
void SCIPrationalSetInfinity(SCIP_RATIONAL *res)
Definition: rational.cpp:618
void SCIPrationalAdd(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:935
SCIP_Real SCIPrationalGetReal(SCIP_RATIONAL *rational)
Definition: rational.cpp:2085
void SCIPrationalFreeBlock(BMS_BLKMEM *mem, SCIP_RATIONAL **rational)
Definition: rational.cpp:461
SCIP_RETCODE SCIPrationalCreateBlockArray(BMS_BLKMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:196
#define SCIPrationalDebugMessage
Definition: rational.h:641
void SCIPrationalDiv(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1132
SCIP_Bool SCIPrationalIsAbsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1680
void SCIPrationalSetReal(SCIP_RATIONAL *res, SCIP_Real real)
Definition: rational.cpp:603
void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:473
void SCIPrationalDiff(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:983
SCIP_Bool SCIPrationalIsLEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1615
SCIP_Bool SCIPrationalIsPositive(SCIP_RATIONAL *rational)
Definition: rational.cpp:1640
SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
Definition: rational.cpp:123
SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
Definition: rational.cpp:1624
void SCIPrationalSetRational(SCIP_RATIONAL *res, SCIP_RATIONAL *src)
Definition: rational.cpp:569
SCIP_Bool SCIPrationalIsGEReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1606
void SCIPrationalMax(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
Definition: rational.cpp:1373
void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
Definition: rational.cpp:538
void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
Definition: rational.cpp:582
void SCIPrationalNegate(SCIP_RATIONAL *res, SCIP_RATIONAL *op)
Definition: rational.cpp:1297
SCIP_Bool SCIPrationalIsNegative(SCIP_RATIONAL *rational)
Definition: rational.cpp:1650
SCIP_Bool SCIPrationalIsInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1660
SCIP_Real SCIPrationalRoundReal(SCIP_RATIONAL *rational, SCIP_ROUNDMODE_RAT roundmode)
Definition: rational.cpp:2110
SCIP_RETCODE SCIPrationalCreateBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***rational, int size)
Definition: rational.cpp:214
SCIP_Bool SCIPrationalIsNegInfinity(SCIP_RATIONAL *rational)
Definition: rational.cpp:1670
SCIP_Bool SCIPrationalIsGTReal(SCIP_RATIONAL *rat, SCIP_Real real)
Definition: rational.cpp:1546
SCIP_Bool SCIPrationalIsEQ(SCIP_RATIONAL *rat1, SCIP_RATIONAL *rat2)
Definition: rational.cpp:1404
void SCIPrationalPrintf(const char *formatstr,...)
Definition: rational.cpp:1923
void SCIPrationalFreeBufferArray(BMS_BUFMEM *mem, SCIP_RATIONAL ***ratbufarray, int size)
Definition: rational.cpp:518
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17686
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17696
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17719
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17706
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:23453
SCIP_INTERVAL SCIPvarGetObjInterval(SCIP_VAR *var)
Definition: var.c:23921
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_RATIONAL * SCIPvarGetUbLocalExact(SCIP_VAR *var)
Definition: var.c:24278
SCIP_RATIONAL * SCIPvarGetLbLocalExact(SCIP_VAR *var)
Definition: var.c:24244
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13475
SCIP_Real SCIProwGetLPActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6454
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13420
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13436
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4147
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:18211
SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4330
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:17969
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition: lp.c:10441
internal methods for LP management
SCIP_Bool SCIPlpExactProjectShiftPossible(SCIP_LPEXACT *lpexact)
Definition: lpexact.c:3909
SCIP_RETCODE SCIPlpExactLink(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lpexact.c:3711
SCIP_RETCODE SCIPlpExactSolveAndEval(SCIP_LPEXACT *lpexact, SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool *lperror, SCIP_Bool usefarkas)
Definition: lpexact.c:4477
void SCIProwExactPrint(SCIP_ROWEXACT *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lpexact.c:4953
SCIP_RETCODE SCIPlpExactSyncLPs(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: lpexact.c:8474
SCIP_COLEXACT * SCIPcolGetColExact(SCIP_COL *col)
Definition: lpexact.c:5099
SCIP_RETCODE SCIPcolExactCalcFarkasRedcostCoef(SCIP_COLEXACT *col, SCIP_SET *set, SCIP_RATIONAL *result, SCIP_RATIONAL **dual, SCIP_Bool usefarkas)
Definition: lpexact.c:5111
SCIP_Bool SCIPlpExactBoundShiftUseful(SCIP_LPEXACT *lpexact)
Definition: lpexact.c:3899
void SCIPlpExactAllowExactSolve(SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_Bool allowexact)
Definition: lpexact.c:7630
SCIP_RATIONAL * SCIPcolExactGetObj(SCIP_COLEXACT *col)
Definition: lpexact.c:5996
SCIP_RETCODE SCIPlpExactFlush(SCIP_LPEXACT *lpexact, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lpexact.c:3651
internal methods for exact LP management
SCIP_RETCODE SCIPlpExactComputeSafeBound(SCIP_LP *lp, SCIP_LPEXACT *lpexact, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_Bool *lperror, SCIP_Bool usefarkas, SCIP_Real *safebound, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
safe exact rational bounding methods
interface methods for specific LP solvers
interface methods for specific exact LP solvers
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
internal methods for collecting primal CIP solutions and primal informations
internal methods for storing and manipulating the main problem
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
#define SCIPdebugMessage
Definition: pub_message.h:96
public data structures and miscellaneous methods
public methods for problem variables
wrapper for rational number arithmetic
wrapper for rational number arithmetic that interacts with GMP
public methods for certified solving
public methods for message handling
public methods for global and local (sub)problems
public methods for the branch-and-bound tree
internal methods for storing separated exact cuts
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7076
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6617
SCIP_Bool SCIPsetIsFeasFracIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7110
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7087
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6945
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6380
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6515
SCIP_Real SCIPsetFeasFrac(SCIP_SET *set, SCIP_Real val)
Definition: set.c:7160
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1782
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1775
internal methods for problem statistics
SCIP_RATIONAL * farkascoef
SCIP_ROWEXACT ** rows
SCIP_RATIONAL * obj
SCIP_RATIONAL ** vals
SCIP_RATIONAL * ub
SCIP_RATIONAL * redcost
SCIP_VAR * var
SCIP_RATIONAL * lb
int nunlinked
Definition: struct_lp.h:173
SCIP_VAR * var
Definition: struct_lp.h:162
SCIP_Real sup
Definition: intervalarith.h:57
SCIP_Real inf
Definition: intervalarith.h:56
SCIP_Bool primalfeasible
SCIP_PROJSHIFTDATA * projshiftdata
SCIP_Bool wasforcedsafebound
SCIP_COLEXACT ** cols
SCIP_LPIEXACT * lpiexact
SCIP_LPSOLSTAT lpsolstat
SCIP_ROWEXACT ** rows
SCIP_Bool boundshiftuseful
SCIP_LP * fplp
SCIP_Bool forcesafebound
SCIP_Bool dualfeasible
SCIP_Bool allowexactsolve
SCIP_RATIONAL * lpobjval
SCIP_Bool forceexactsolve
SCIP_ROW ** rows
Definition: struct_lp.h:308
SCIP_Bool probing
Definition: struct_lp.h:384
SCIP_COL ** cols
Definition: struct_lp.h:306
int ncols
Definition: struct_lp.h:334
SCIP_Bool strongbranchprobing
Definition: struct_lp.h:385
SCIP_LPEXACT * lpexact
Definition: struct_lp.h:309
int nrows
Definition: struct_lp.h:340
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:359
SCIP_Real lpobjval
Definition: struct_lp.h:276
SCIP_Bool solved
Definition: struct_lp.h:373
SCIP_Bool diving
Definition: struct_lp.h:386
SCIP_Bool hasprovedbound
Definition: struct_lp.h:409
SCIP_LPI * lpi
Definition: struct_lp.h:301
SCIP_ROW * fprow
SCIP_RATIONAL ** vals
SCIP_RATIONAL * dualfarkas
SCIP_RATIONAL * lhs
SCIP_RATIONAL * rhs
SCIP_RATIONAL * dualsol
SCIP_INTERVAL * valsinterval
SCIP_RATIONAL * constant
SCIP_Real rhs
Definition: struct_lp.h:208
SCIP_Real dualfarkas
Definition: struct_lp.h:218
char * name
Definition: struct_lp.h:229
SCIP_Real lhs
Definition: struct_lp.h:207
SCIP_Real constant
Definition: struct_lp.h:206
SCIP_Real dualsol
Definition: struct_lp.h:216
SCIP_Longint nexlpinter
Definition: struct_stat.h:232
SCIP_Longint nfailboundshiftinf
Definition: struct_stat.h:239
SCIP_Longint nboundshiftinf
Definition: struct_stat.h:238
SCIP_Longint nprojshiftinf
Definition: struct_stat.h:244
SCIP_Real boundingerrorps
Definition: struct_stat.h:164
SCIP_Longint nboundshift
Definition: struct_stat.h:236
SCIP_Longint nfailprojshiftinf
Definition: struct_stat.h:245
SCIP_Longint nboundshiftobjlimfail
Definition: struct_stat.h:241
SCIP_CLOCK * provedinfeaspstime
Definition: struct_stat.h:185
SCIP_Longint nprojshiftobjlimfail
Definition: struct_stat.h:247
SCIP_Longint nprojshiftobjlim
Definition: struct_stat.h:246
SCIP_CLOCK * provedinfeasbstime
Definition: struct_stat.h:183
SCIP_Longint nexlpintfeas
Definition: struct_stat.h:233
SCIP_Real boundingerrorbs
Definition: struct_stat.h:163
SCIP_Longint nprojshift
Definition: struct_stat.h:242
SCIP_Longint nboundshiftobjlim
Definition: struct_stat.h:240
SCIP_CLOCK * provedfeaspstime
Definition: struct_stat.h:184
SCIP_Longint nfailexlp
Definition: struct_stat.h:235
SCIP_Longint nfailboundshift
Definition: struct_stat.h:237
SCIP_Longint nexlpboundexc
Definition: struct_stat.h:234
SCIP_Longint nfailexlpinf
Definition: struct_stat.h:230
SCIP_Longint nfailprojshift
Definition: struct_stat.h:243
SCIP_CLOCK * provedfeasbstime
Definition: struct_stat.h:182
SCIP_CLOCK * solvingtime
Definition: struct_stat.h:168
data structures for exact LP management
SCIP main data structure.
datastructures for global SCIP settings
Definition: heur_padm.c:135
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:43
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_TIMELIMIT
Definition: type_lp.h:49
@ SCIP_LPSOLSTAT_UNBOUNDEDRAY
Definition: type_lp.h:46
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:45
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:47
@ SCIP_LPSOLSTAT_ITERLIMIT
Definition: type_lp.h:48
@ PS_DUALCOSTSEL_ACTIVE_EXLP
Definition: type_lpexact.h:70
@ PS_DUALCOSTSEL_NO
Definition: type_lpexact.h:68
@ PS_DUALCOSTSEL_ACTIVE_FPLP
Definition: type_lpexact.h:69
struct SCIP_ProjShiftData SCIP_PROJSHIFTDATA
Definition: type_lpexact.h:58
@ SCIP_LPPAR_LPINFO
Definition: type_lpi.h:55
@ SCIP_LPPAR_LPTILIM
Definition: type_lpi.h:61
@ SCIP_OBJSEN_MAXIMIZE
Definition: type_lpi.h:42
@ SCIP_R_ROUND_UPWARDS
Definition: type_rational.h:58
@ SCIP_R_ROUND_DOWNWARDS
Definition: type_rational.h:57
@ SCIP_LPERROR
Definition: type_retcode.h:49
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71