Scippy

SCIP

Solving Constraint Integer Programs

lp.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-2024 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 lp.c
26 * @ingroup OTHER_CFILES
27 * @brief LP management methods and data structures
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Marc Pfetsch
31 * @author Kati Wolter
32 * @author Gerald Gamrath
33 *
34 * In LP management, we have to differ between the current LP and the SCIP_LP
35 * stored in the LP solver. All LP methods affect the current LP only.
36 * Before solving the current LP with the LP solver or setting an LP state,
37 * the LP solvers data has to be updated to the current LP with a call to
38 * lpFlush().
39 */
40
41/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42
43
44#include "lpi/lpi.h"
45#include "scip/clock.h"
46#include "scip/cons.h"
47#include "scip/event.h"
48#include "scip/intervalarith.h"
49#include "scip/lp.h"
50#include "scip/misc.h"
51#include "scip/prob.h"
52#include "scip/pub_lp.h"
53#include "scip/pub_message.h"
54#include "scip/pub_misc.h"
55#include "scip/pub_misc_sort.h"
56#include "scip/pub_var.h"
57#include "scip/set.h"
58#include "scip/sol.h"
59#include "scip/solve.h"
60#include "scip/stat.h"
61#include "scip/struct_event.h"
62#include "scip/struct_lp.h"
63#include "scip/struct_prob.h"
64#include "scip/struct_set.h"
65#include "scip/struct_stat.h"
66#include "scip/struct_var.h"
67#include "scip/var.h"
68#include <string.h>
69
70
71/* activate this to use the row activities as given by the LPI instead of recalculating
72 * using the LP solver activity is potentially faster, but may not be consistent with the SCIP_ROW calculations
73 * see also #2594 for more details on possible trouble
74 */
75/* #define SCIP_USE_LPSOLVER_ACTIVITY */
76
77/*
78 * debug messages
79 */
80
81#ifdef SCIP_DEBUG
82/** method is to print in row in case SCIP_DEBUG is defined */
83static
84void debugRowPrint(
85 SCIP_SET* set, /**< global SCIP settings */
86 SCIP_ROW* row /**< LP row */
87 )
88{
89 int i;
90
91 assert(row != NULL);
92
93 /* print row name */
94 if( row->name != NULL && row->name[0] != '\0' )
95 {
96 SCIPsetDebugMsgPrint(set, "%s: ", row->name);
97 }
98
99 /* print left hand side */
100 SCIPsetDebugMsgPrint(set, "%.15g <= ", row->lhs);
101
102 /* print coefficients */
103 if( row->len == 0 )
104 {
106 }
107 for( i = 0; i < row->len; ++i )
108 {
109 assert(row->cols[i] != NULL);
110 assert(row->cols[i]->var != NULL);
111 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
112 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
113 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
114 }
115
116 /* print constant */
118 {
119 SCIPsetDebugMsgPrint(set, "%+.15g ", row->constant);
120 }
121
122 /* print right hand side */
123 SCIPsetDebugMsgPrint(set, "<= %.15g\n", row->rhs);
124}
125#else
126#define debugRowPrint(x,y) /**/
127#endif
128
129#ifdef SCIP_DEBUG
130/** method to output column if SCIP_DEBUG is define */
131static
132void debugColPrint(
133 SCIP_SET* set, /**< global SCIP settings */
134 SCIP_COL* col /**< LP column */
135 )
136{
137 int r;
138
139 assert(col != NULL);
140 assert(col->var != NULL);
141
142 /* print bounds */
143 SCIPsetDebugMsgPrint(set, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
144
145 /* print coefficients */
146 if( col->len == 0 )
147 {
148 SCIPsetDebugMsgPrint(set, "<empty>");
149 }
150 for( r = 0; r < col->len; ++r )
151 {
152 assert(col->rows[r] != NULL);
153 assert(col->rows[r]->name != NULL);
154 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
155 }
157}
158#else
159#define debugColPrint(x,y) /**/
160#endif
161
162/*
163 * memory growing methods for dynamically allocated arrays
164 */
165
166/** ensures, that chgcols array can store at least num entries */
167static
169 SCIP_LP* lp, /**< current LP data */
170 SCIP_SET* set, /**< global SCIP settings */
171 int num /**< minimum number of entries to store */
172 )
173{
174 assert(lp->nchgcols <= lp->chgcolssize);
175
176 if( num > lp->chgcolssize )
177 {
178 int newsize;
179
180 newsize = SCIPsetCalcMemGrowSize(set, num);
181 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
182 lp->chgcolssize = newsize;
183 }
184 assert(num <= lp->chgcolssize);
185
186 return SCIP_OKAY;
187}
188
189/** ensures, that chgrows array can store at least num entries */
190static
192 SCIP_LP* lp, /**< current LP data */
193 SCIP_SET* set, /**< global SCIP settings */
194 int num /**< minimum number of entries to store */
195 )
196{
197 assert(lp->nchgrows <= lp->chgrowssize);
198
199 if( num > lp->chgrowssize )
200 {
201 int newsize;
202
203 newsize = SCIPsetCalcMemGrowSize(set, num);
204 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
205 lp->chgrowssize = newsize;
206 }
207 assert(num <= lp->chgrowssize);
208
209 return SCIP_OKAY;
210}
211
212/** ensures, that lpicols array can store at least num entries */
213static
215 SCIP_LP* lp, /**< current LP data */
216 SCIP_SET* set, /**< global SCIP settings */
217 int num /**< minimum number of entries to store */
218 )
219{
220 assert(lp->nlpicols <= lp->lpicolssize);
221
222 if( num > lp->lpicolssize )
223 {
224 int newsize;
225
226 newsize = SCIPsetCalcMemGrowSize(set, num);
227 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
228 lp->lpicolssize = newsize;
229 }
230 assert(num <= lp->lpicolssize);
231
232 return SCIP_OKAY;
233}
234
235/** ensures, that lpirows array can store at least num entries */
236static
238 SCIP_LP* lp, /**< current LP data */
239 SCIP_SET* set, /**< global SCIP settings */
240 int num /**< minimum number of entries to store */
241 )
242{
243 assert(lp->nlpirows <= lp->lpirowssize);
244
245 if( num > lp->lpirowssize )
246 {
247 int newsize;
248
249 newsize = SCIPsetCalcMemGrowSize(set, num);
250 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
251 lp->lpirowssize = newsize;
252 }
253 assert(num <= lp->lpirowssize);
254
255 return SCIP_OKAY;
256}
257
258/** ensures, that cols array can store at least num entries */
259static
261 SCIP_LP* lp, /**< current LP data */
262 SCIP_SET* set, /**< global SCIP settings */
263 int num /**< minimum number of entries to store */
264 )
265{
266 assert(lp->ncols <= lp->colssize);
267
268 if( num > lp->colssize )
269 {
270 int newsize;
271
272 newsize = SCIPsetCalcMemGrowSize(set, num);
273 SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
274 lp->colssize = newsize;
275 }
276 assert(num <= lp->colssize);
277
278 return SCIP_OKAY;
279}
280
281/** ensures, that soldirection array can store at least num entries */
282static
284 SCIP_LP* lp, /**< current LP data */
285 int num /**< minimum number of entries to store */
286 )
287{
288 if( num > lp->soldirectionsize )
289 {
292
293 lp->soldirectionsize = num;
294 }
295
296 assert(num <= lp->soldirectionsize);
297
298 return SCIP_OKAY;
299}
300
301/** ensures, that lazy cols array can store at least num entries */
302static
304 SCIP_LP* lp, /**< current LP data */
305 SCIP_SET* set, /**< global SCIP settings */
306 int num /**< minimum number of entries to store */
307 )
308{
309 assert(lp->nlazycols <= lp->lazycolssize);
310
311 if( num > lp->lazycolssize )
312 {
313 int newsize;
314
315 newsize = SCIPsetCalcMemGrowSize(set, num);
316 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
317 lp->lazycolssize = newsize;
318 }
319 assert(num <= lp->lazycolssize);
320
321 return SCIP_OKAY;
322}
323
324/** ensures, that rows array can store at least num entries */
325static
327 SCIP_LP* lp, /**< current LP data */
328 SCIP_SET* set, /**< global SCIP settings */
329 int num /**< minimum number of entries to store */
330 )
331{
332 assert(lp->nrows <= lp->rowssize);
333
334 if( num > lp->rowssize )
335 {
336 int newsize;
337
338 newsize = SCIPsetCalcMemGrowSize(set, num);
339 SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
340 lp->rowssize = newsize;
341 }
342 assert(num <= lp->rowssize);
343
344 return SCIP_OKAY;
345}
346
347/** ensures, that row array of column can store at least num entries */
348static
350 SCIP_COL* col, /**< LP column */
351 BMS_BLKMEM* blkmem, /**< block memory */
352 SCIP_SET* set, /**< global SCIP settings */
353 int num /**< minimum number of entries to store */
354 )
355{
356 assert(col != NULL);
357 assert(col->len <= col->size);
358
359 if( num > col->size )
360 {
361 int newsize;
362
363 newsize = SCIPsetCalcMemGrowSize(set, num);
364 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
365 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
366 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
367 col->size = newsize;
368 }
369 assert(num <= col->size);
370
371 return SCIP_OKAY;
372}
373
374/** save current LP values dependent on the solution */
375static
377 SCIP_LP* lp, /**< LP data */
378 SCIP_STAT* stat, /**< problem statistics */
379 BMS_BLKMEM* blkmem /**< block memory */
380 )
381{
382 SCIP_LPSOLVALS* storedsolvals;
383
384 assert(lp != NULL);
385 assert(stat != NULL);
386 assert(blkmem != NULL);
387
388 /* allocate memory for storage */
389 if( lp->storedsolvals == NULL )
390 {
392 }
393 storedsolvals = lp->storedsolvals;
394
395 /* store values */
396 storedsolvals->lpsolstat = lp->lpsolstat;
397 storedsolvals->lpobjval = lp->lpobjval;
398 storedsolvals->primalfeasible = lp->primalfeasible;
399 storedsolvals->primalchecked = lp->primalchecked;
400 storedsolvals->dualfeasible = lp->dualfeasible;
401 storedsolvals->dualchecked = lp->dualchecked;
402 storedsolvals->solisbasic = lp->solisbasic;
403 storedsolvals->lpissolved = lp->solved;
404
405 return SCIP_OKAY;
406}
407
408/** restore LP solution values in column */
409static
411 SCIP_LP* lp, /**< LP data */
412 BMS_BLKMEM* blkmem, /**< block memory */
413 SCIP_Longint validlp /**< number of lp for which restored values are valid */
414 )
415{
416 SCIP_LPSOLVALS* storedsolvals;
417
418 assert(lp != NULL);
419 assert(blkmem != NULL);
420
421 /* if stored values are available, restore them */
422 storedsolvals = lp->storedsolvals;
423 if( storedsolvals != NULL )
424 {
425 lp->solved = storedsolvals->lpissolved;
426 lp->validsollp = validlp;
427
428 lp->lpsolstat = storedsolvals->lpsolstat;
429 lp->lpobjval = storedsolvals->lpobjval;
430 lp->primalfeasible = storedsolvals->primalfeasible;
431 lp->primalchecked = storedsolvals->primalchecked;
432 lp->dualfeasible = storedsolvals->dualfeasible;
433 lp->dualchecked = storedsolvals->dualchecked;
434 lp->solisbasic = storedsolvals->solisbasic;
435
436 /* solution values are stored only for LPs solved to optimality or unboundedness */
437 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
443 lp->validsollp == -1);
444 }
445 /* no values available, mark LP as unsolved */
446 else
447 {
448 lp->solved = FALSE;
449 lp->validsollp = -1;
450
453 lp->primalfeasible = FALSE;
454 lp->primalchecked = FALSE;
455 lp->dualfeasible = FALSE;
456 lp->dualchecked = FALSE;
457 lp->solisbasic = FALSE;
458 lp->validfarkaslp = -1;
459 }
460
461 lp->validdegeneracylp = -1;
462
463 /* intentionally keep storage space allocated */
464
465 return SCIP_OKAY;
466}
467
468/** save current LP solution values stored in each column */
469static
471 SCIP_COL* col, /**< LP column */
472 BMS_BLKMEM* blkmem /**< block memory */
473 )
474{
475 SCIP_COLSOLVALS* storedsolvals;
476
477 assert(col != NULL);
478 assert(blkmem != NULL);
479
480 /* allocate memory for storage */
481 if( col->storedsolvals == NULL )
482 {
484 }
485 storedsolvals = col->storedsolvals;
486
487 /* store values */
488 storedsolvals->primsol = col->primsol;
489 storedsolvals->redcost = col->redcost;
490 storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
491
492 return SCIP_OKAY;
493}
494
495/** restore LP solution values in column */
496static
498 SCIP_COL* col, /**< LP column */
499 BMS_BLKMEM* blkmem, /**< block memory */
500 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
501 SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */
502 )
503{
504 SCIP_COLSOLVALS* storedsolvals;
505
506 assert(col != NULL);
507 assert(blkmem != NULL);
508
509 /* if stored values are available, restore them */
510 storedsolvals = col->storedsolvals;
511 if( storedsolvals != NULL )
512 {
513 col->primsol = storedsolvals->primsol;
514 col->redcost = storedsolvals->redcost;
515 col->validredcostlp = validlp;
516 col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
517
518 /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
519 col->validfarkaslp = -1;
520 }
521 /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
522 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
523 */
524 else
525 {
526 col->primsol = 0.0;
527 col->validredcostlp = -1;
528 col->validfarkaslp = -1;
529 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
530 }
531
532 /* free memory */
533 if( freebuffer )
534 {
536 assert(col->storedsolvals == NULL);
537 }
538
539 return SCIP_OKAY;
540}
541
542/** save current LP solution values stored in each column */
543static
545 SCIP_ROW* row, /**< LP row */
546 BMS_BLKMEM* blkmem, /**< block memory */
547 SCIP_Bool infeasible /**< is the solution infeasible? */
548 )
549{
550 SCIP_ROWSOLVALS* storedsolvals;
551
552 assert(row != NULL);
553 assert(blkmem != NULL);
554
555 /* allocate memory for storage */
556 if( row->storedsolvals == NULL )
557 {
559 }
560 storedsolvals = row->storedsolvals;
561
562 /* store values */
563 if ( infeasible )
564 {
565 storedsolvals->dualsol = row->dualfarkas;
566 storedsolvals->activity = SCIP_INVALID;
567 storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
568 }
569 else
570 {
571 storedsolvals->dualsol = row->dualsol;
572 storedsolvals->activity = row->activity;
573 storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
574 }
575
576 return SCIP_OKAY;
577}
578
579/** restore LP solution values in row */
580static
582 SCIP_ROW* row, /**< LP column */
583 BMS_BLKMEM* blkmem, /**< block memory */
584 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
585 SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */
586 SCIP_Bool infeasible /**< is the solution infeasible? */
587 )
588{
589 SCIP_ROWSOLVALS* storedsolvals;
590
591 assert(row != NULL);
592 assert(blkmem != NULL);
593
594 /* if stored values are available, restore them */
595 storedsolvals = row->storedsolvals;
596 if( storedsolvals != NULL )
597 {
598 if ( infeasible )
599 row->dualfarkas = storedsolvals->dualsol;
600 else
601 row->dualsol = storedsolvals->dualsol;
602 row->activity = storedsolvals->activity;
603 row->validactivitylp = validlp;
604 row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
605 }
606 /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
607 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
608 */
609 else
610 {
611 row->dualsol = 0.0;
612 row->dualfarkas = 0.0;
613 row->activity = SCIP_INVALID;
614 row->validactivitylp = -1;
615 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
616 }
617
618 /* free memory */
619 if( freebuffer )
620 {
622 assert(row->storedsolvals == NULL);
623 }
624
625 return SCIP_OKAY;
626}
627
628/** ensures, that column array of row can store at least num entries */
630 SCIP_ROW* row, /**< LP row */
631 BMS_BLKMEM* blkmem, /**< block memory */
632 SCIP_SET* set, /**< global SCIP settings */
633 int num /**< minimum number of entries to store */
634 )
635{
636 assert(row != NULL);
637 assert(row->len <= row->size);
638
639 if( num > row->size )
640 {
641 int newsize;
642
643 newsize = SCIPsetCalcMemGrowSize(set, num);
644 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
645 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
646 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
647 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
648 row->size = newsize;
649 }
650 assert(num <= row->size);
651
652 return SCIP_OKAY;
653}
654
655
656#ifdef SCIP_MORE_DEBUG /* enable this to check the sortings within rows (for debugging, very slow!) */
657static SCIP_Bool msgdisp_checkrow = FALSE;
658
659static
660void checkRow(
661 SCIP_ROW* row
662 )
663{
664 int i;
665
666 if( !msgdisp_checkrow )
667 {
668 printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
669 msgdisp_checkrow = TRUE;
670 }
671
672 /* validate sorting of LP part of row */
673 if( row->lpcolssorted && row->nlpcols > 0)
674 {
675 assert(row->cols_index[0] == row->cols[0]->index);
676 for( i = 1; i < row->nlpcols; ++i )
677 {
678 assert(row->cols_index[i] == row->cols[i]->index);
679 assert(row->cols_index[i] >= row->cols_index[i-1]);
680 }
681 }
682
683 /* validate sorting of non-LP part of row */
684 if( row->nonlpcolssorted && row->len > row->nlpcols )
685 {
686 assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
687 for( i = row->nlpcols + 1; i < row->len; ++i )
688 {
689 assert(row->cols_index[i] == row->cols[i]->index);
690 assert(row->cols_index[i] >= row->cols_index[i-1]);
691 }
692 }
693}
694#else
695#define checkRow(row) /**/
696#endif
697
698#ifdef SCIP_MORE_DEBUG /* enable this to check norms of rows (for debugging, very slow!) */
699static
700void checkRowSqrnorm(
701 SCIP_ROW* row
702 )
703{
704 SCIP_COL** cols;
705 SCIP_Real sqrnorm;
706 int c;
707
708 cols = row->cols;
709 assert(cols != NULL || row->len == 0);
710
711 sqrnorm = 0.0;
712
713 for( c = row->len - 1; c >= 0; --c )
714 {
715 if( cols[c]->lppos >= 0 )
716 sqrnorm += SQR(row->vals[c]);
717 }
718
719 assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
720}
721
722static
723void checkRowSumnorm(
724 SCIP_ROW* row
725 )
726{
727 SCIP_COL** cols;
728 SCIP_Real sumnorm;
729 int c;
730
731 cols = row->cols;
732 assert(cols != NULL || row->len == 0);
733
734 sumnorm = 0.0;
735
736 for( c = row->len - 1; c >= 0; --c )
737 {
738 if( cols[c]->lppos >= 0 )
739 sumnorm += REALABS(row->vals[c]);
740 }
741
742 assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
743}
744
745static
746void checkRowObjprod(
747 SCIP_ROW* row
748 )
749{
750 SCIP_COL** cols;
751 SCIP_Real objprod;
752 int c;
753
754 cols = row->cols;
755 assert(cols != NULL || row->len == 0);
756
757 objprod = 0.0;
758
759 for( c = row->len - 1; c >= 0; --c )
760 {
761 if( cols[c]->lppos >= 0 )
762 objprod += row->vals[c] * cols[c]->unchangedobj;
763 }
764
765 assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
766}
767#else
768#define checkRowSqrnorm(row) /**/
769#define checkRowSumnorm(row) /**/
770#define checkRowObjprod(row) /**/
771#endif
772
773/*
774 * Local methods for pseudo and loose objective values
775 */
776
777/* recompute the loose objective value from scratch, if it was marked to be unreliable before */
778static
780 SCIP_LP* lp, /**< current LP data */
781 SCIP_SET* set, /**< global SCIP settings */
782 SCIP_PROB* prob /**< problem data */
783 )
784{
785 SCIP_VAR** vars;
786 SCIP_Real obj;
787 int nvars;
788 int v;
789
790 assert(lp != NULL);
791 assert(set != NULL);
792 assert(prob != NULL);
793 assert(!lp->looseobjvalid);
794
795 vars = prob->vars;
796 nvars = prob->nvars;
797 lp->looseobjval = 0.0;
798
799 /* iterate over all variables in the problem */
800 for( v = 0; v < nvars; ++v )
801 {
802 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
803 {
804 obj = SCIPvarGetObj(vars[v]);
805
806 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
808 lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
809 else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
810 lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
811 }
812 }
813
814 /* the recomputed value is reliable */
815 lp->rellooseobjval = lp->looseobjval;
816 lp->looseobjvalid = TRUE;
817}
818
819/* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
820static
822 SCIP_LP* lp, /**< current LP data */
823 SCIP_SET* set, /**< global SCIP settings */
824 SCIP_PROB* prob /**< problem data */
825 )
826{
827 SCIP_VAR** vars;
828 int nvars;
829 int v;
830
831 assert(lp != NULL);
832 assert(set != NULL);
833 assert(prob != NULL);
834 assert(!lp->pseudoobjvalid);
835
836 vars = prob->vars;
837 nvars = prob->nvars;
838 lp->pseudoobjval = 0.0;
839
840 /* iterate over all variables in the problem */
841 for( v = 0; v < nvars; ++v )
842 {
843 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
844 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
846 {
847 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
848 }
849 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
851 {
852 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
853 }
854 }
855
856 /* the recomputed value is reliable */
858 lp->pseudoobjvalid = TRUE;
859}
860
861/* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
862static
864 SCIP_LP* lp, /**< current LP data */
865 SCIP_SET* set, /**< global SCIP settings */
866 SCIP_PROB* prob /**< problem data */
867 )
868{
869 SCIP_VAR** vars;
870 int nvars;
871 int v;
872
873 assert(lp != NULL);
874 assert(set != NULL);
875 assert(prob != NULL);
876 assert(!lp->glbpseudoobjvalid);
877
878 vars = prob->vars;
879 nvars = prob->nvars;
880 lp->glbpseudoobjval = 0.0;
881
882 /* iterate over all variables in the problem */
883 for( v = 0; v < nvars; ++v )
884 {
885 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
886 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
888 {
889 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
890 }
891 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
893 {
894 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
895 }
896 }
897
898 /* the recomputed value is reliable */
901}
902
903/** gets finite part of objective value of current LP that results from LOOSE variables only */
904static
906 SCIP_LP* lp, /**< current LP data */
907 SCIP_SET* set, /**< global SCIP settings */
908 SCIP_PROB* prob /**< problem data */
909 )
910{
911 assert(lp != NULL);
912 assert(set != NULL);
913 assert(prob != NULL);
914 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
915 assert(lp->flushed);
916 assert(lp->looseobjvalinf == 0);
917
918 /* recalculate the loose objective value, if needed */
919 if( !lp->looseobjvalid )
921
922 return lp->looseobjval;
923}
924
925/** gets finite part of pseudo objective value of current LP */
926static
928 SCIP_LP* lp, /**< current LP data */
929 SCIP_SET* set, /**< global SCIP settings */
930 SCIP_PROB* prob /**< problem data */
931 )
932{
933 assert(lp != NULL);
934 assert(set != NULL);
935 assert(prob != NULL);
936
937 /* recalculate the pseudo objective value, if needed */
938 if( !lp->pseudoobjvalid )
940
941 return lp->pseudoobjval;
942}
943
944/*
945 * Sorting and searching rows and columns
946 */
947
948
949/** comparison method for sorting rows by non-decreasing index */
951{
952 assert(elem1 != NULL);
953 assert(elem2 != NULL);
954
955 if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
956 return -1;
957 else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
958 return +1;
959 else
960 {
961 assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
962 return 0;
963 }
964}
965
966
967/** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
968static
970 SCIP_COL* col /**< column to be sorted */
971 )
972{
973 int i;
974
975 assert(col != NULL);
976
977 /* check, if column is already sorted in the LP part */
978 if( col->lprowssorted )
979 return;
980
981 /* sort coefficients */
982 SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
983
984 /* update links */
985 for( i = 0; i < col->nlprows; ++i )
986 {
987 if( col->linkpos[i] >= 0 )
988 {
989 assert(col->rows[i]->cols[col->linkpos[i]] == col);
990 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
991 col->rows[i]->linkpos[col->linkpos[i]] = i;
992 }
993 }
994
995 col->lprowssorted = TRUE;
996}
997
998/** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
999 * ones
1000 */
1001static
1003 SCIP_COL* col /**< column to be sorted */
1004 )
1005{
1006 int i;
1007
1008 assert(col != NULL);
1009
1010 /* check, if column is already sorted in the non-LP part */
1011 if( col->nonlprowssorted )
1012 return;
1013
1014 /* sort coefficients */
1015 SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
1016
1017 /* update links */
1018 for( i = col->nlprows; i < col->len; ++i )
1019 {
1020 if( col->linkpos[i] >= 0 )
1021 {
1022 assert(col->rows[i]->cols[col->linkpos[i]] == col);
1023 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
1024 col->rows[i]->linkpos[col->linkpos[i]] = i;
1025 }
1026 }
1027
1028 col->nonlprowssorted = TRUE;
1029}
1030
1031/** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
1032static
1034 SCIP_ROW* row /**< row to be sorted */
1035 )
1036{
1037 int i;
1038
1039 assert(row != NULL);
1040
1041 /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
1042 if( row->lpcolssorted || row->delaysort )
1043 return;
1044
1045 /* sort coefficients */
1046 SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
1047
1048 /* update links */
1049 for( i = 0; i < row->nlpcols; ++i )
1050 {
1051 if( row->linkpos[i] >= 0 )
1052 {
1053 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1054 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1055 row->cols[i]->linkpos[row->linkpos[i]] = i;
1056 }
1057 }
1058
1059 row->lpcolssorted = TRUE;
1060}
1061
1062/** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1063 * higher ones
1064 */
1065static
1067 SCIP_ROW* row /**< row to be sorted */
1068 )
1069{
1070 int i;
1071
1072 assert(row != NULL);
1073
1074 checkRow(row);
1075
1076 /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1077 if( row->nonlpcolssorted || row->delaysort )
1078 return;
1079
1080 /* sort coefficients */
1081 SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1082
1083 /* update links */
1084 for( i = row->nlpcols; i < row->len; ++i )
1085 {
1086 if( row->linkpos[i] >= 0 )
1087 {
1088 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1089 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1090 row->cols[i]->linkpos[row->linkpos[i]] = i;
1091 }
1092 }
1093
1094 checkRow(row);
1095
1096 row->nonlpcolssorted = TRUE;
1097}
1098
1099/** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1100static
1102 SCIP_COL* col, /**< column to be searched in */
1103 const SCIP_ROW* row, /**< coefficient to be searched for */
1104 int minpos, /**< first position of search range */
1105 int maxpos /**< last position of search range */
1106 )
1107{
1108 int pos;
1109 int idx;
1110 int searchidx;
1111
1112 assert(col != NULL);
1113 assert(row != NULL);
1114
1115 /* binary search */
1116 searchidx = row->index;
1117 while(minpos <= maxpos)
1118 {
1119 pos = (minpos + maxpos)/2;
1120 assert(0 <= pos && pos < col->len);
1121 assert(col->rows[pos] != NULL);
1122 assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1123 idx = col->rows[pos]->index;
1124 if( searchidx == idx )
1125 return pos;
1126 else if( searchidx < idx )
1127 maxpos = pos-1;
1128 else
1129 minpos = pos+1;
1130 }
1131
1132 return -1;
1133}
1134
1135/** searches coefficient in column, returns position in col vector or -1 if not found */
1136static
1138 SCIP_COL* col, /**< column to be searched in */
1139 const SCIP_ROW* row /**< coefficient to be searched for */
1140 )
1141{
1142 int pos;
1143
1144 assert(col != NULL);
1145 assert(row != NULL);
1146
1147 pos = -1;
1148
1149 /* search in the linked LP rows */
1150 if( row->lppos >= 0 )
1151 {
1152 /* column has to be sorted, such that binary search works */
1153 colSortLP(col);
1154 assert(col->lprowssorted);
1155
1156 pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1157 if( pos >= 0 )
1158 return pos;
1159 }
1160
1161 /* search in the non-LP/unlinked rows */
1162 if( row->lppos == -1 || col->nunlinked > 0 )
1163 {
1164 /* column has to be sorted, such that binary search works */
1165 colSortNonLP(col);
1166 assert(col->nonlprowssorted);
1167
1168 pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1169 }
1170
1171 return pos;
1172}
1173
1174/** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1175static
1177 SCIP_ROW* row, /**< row to be searched in */
1178 const SCIP_COL* col, /**< coefficient to be searched for */
1179 int minpos, /**< first position of search range */
1180 int maxpos /**< last position of search range */
1181 )
1182{
1183 int pos;
1184 int idx;
1185 int searchidx;
1186
1187 assert(row != NULL);
1188 assert(col != NULL);
1189
1190 /* binary search */
1191 searchidx = col->index;
1192 while(minpos <= maxpos)
1193 {
1194 pos = (minpos + maxpos)/2;
1195 assert(0 <= pos && pos < row->len);
1196 assert(row->cols[pos] != NULL);
1197 assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1198 assert(row->cols_index[pos] == row->cols[pos]->index);
1199 idx = row->cols_index[pos];
1200 if( searchidx == idx )
1201 return pos;
1202 else if( searchidx < idx )
1203 maxpos = pos-1;
1204 else
1205 minpos = pos+1;
1206 }
1207
1208 return -1;
1209}
1210
1211/** searches coefficient in row, returns position in row vector or -1 if not found;
1212 * if the sorting of the row is delayed, returns -1
1213 */
1214static
1216 SCIP_ROW* row, /**< row to be searched in */
1217 const SCIP_COL* col /**< coefficient to be searched for */
1218 )
1219{
1220 int pos;
1221
1222 assert(row != NULL);
1223 assert(col != NULL);
1224
1225 if( row->delaysort )
1226 return -1;
1227
1228 pos = -1;
1229
1230 /* search in the linked LP columns */
1231 if( col->lppos >= 0 )
1232 {
1233 /* row has to be sorted, such that binary search works */
1234 rowSortLP(row);
1235 assert(row->lpcolssorted);
1236
1237 pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1238 }
1239
1240 /* search in the non-LP/unlinked columns */
1241 if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1242 {
1243 /* row has to be sorted, such that binary search works */
1244 rowSortNonLP(row);
1245 assert(row->nonlpcolssorted);
1246
1247 pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1248 }
1249
1250#ifndef NDEBUG
1251 /* validate result */
1252 assert(-1 <= pos && pos < row->len);
1253 if( pos >= 0 )
1254 assert(row->cols[pos] == col);
1255 else
1256 {
1257 int i;
1258 for( i = 0; i < row->len; ++i )
1259 assert(row->cols[i] != col);
1260 }
1261#endif
1262
1263 return pos;
1264}
1265
1266/** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1267static
1269 SCIP_COL* col, /**< LP column */
1270 int oldpos, /**< old position of coefficient */
1271 int newpos /**< new position of coefficient */
1272 )
1273{
1274 assert(col != NULL);
1275 assert(0 <= oldpos && oldpos < col->len);
1276 assert(0 <= newpos && newpos < col->len);
1277 assert(col->rows[oldpos] != NULL);
1278
1279 if( oldpos == newpos )
1280 return;
1281
1282 col->rows[newpos] = col->rows[oldpos];
1283 col->vals[newpos] = col->vals[oldpos];
1284 col->linkpos[newpos] = col->linkpos[oldpos];
1285
1286 /* update link position in row */
1287 if( col->linkpos[newpos] >= 0 )
1288 {
1289 assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1290 assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1291
1292 col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1293 }
1294
1295 /* update sorted flags */
1296 if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1297 col->lprowssorted = FALSE;
1298 else
1299 col->nonlprowssorted = FALSE;
1300}
1301
1302/** swaps two coefficients in a column, and updates all corresponding data structures */
1303static
1305 SCIP_COL* col, /**< LP column */
1306 int pos1, /**< position of first coefficient */
1307 int pos2 /**< position of second coefficient */
1308 )
1309{
1310 SCIP_ROW* tmprow;
1311 SCIP_Real tmpval;
1312 int tmplinkpos;
1313
1314 assert(col != NULL);
1315 assert(0 <= pos1 && pos1 < col->len);
1316 assert(0 <= pos2 && pos2 < col->len);
1317 assert(col->rows[pos1] != NULL);
1318
1319 if( pos1 == pos2 )
1320 return;
1321
1322 /* swap coefficients */
1323 tmprow = col->rows[pos2];
1324 tmpval = col->vals[pos2];
1325 tmplinkpos = col->linkpos[pos2];
1326
1327 col->rows[pos2] = col->rows[pos1];
1328 col->vals[pos2] = col->vals[pos1];
1329 col->linkpos[pos2] = col->linkpos[pos1];
1330
1331 col->rows[pos1] = tmprow;
1332 col->vals[pos1] = tmpval;
1333 col->linkpos[pos1] = tmplinkpos;
1334
1335 /* update link position in rows */
1336 if( col->linkpos[pos1] >= 0 )
1337 {
1338 assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1339 assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1340
1341 col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1342 }
1343 if( col->linkpos[pos2] >= 0 )
1344 {
1345 assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1346 assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1347
1348 col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1349 }
1350
1351 /* update sorted flags */
1352 if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1353 col->lprowssorted = FALSE;
1354 else
1355 col->nonlprowssorted = FALSE;
1356 if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1357 col->lprowssorted = FALSE;
1358 else
1359 col->nonlprowssorted = FALSE;
1360}
1361
1362/** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1363static
1365 SCIP_ROW* row, /**< LP row */
1366 int oldpos, /**< old position of coefficient */
1367 int newpos /**< new position of coefficient */
1368 )
1369{
1370 assert(row != NULL);
1371 assert(0 <= oldpos && oldpos < row->len);
1372 assert(0 <= newpos && newpos < row->len);
1373 assert(row->cols[oldpos] != NULL);
1374
1375 if( oldpos == newpos )
1376 return;
1377
1378 row->cols[newpos] = row->cols[oldpos];
1379 row->cols_index[newpos] = row->cols_index[oldpos];
1380 row->vals[newpos] = row->vals[oldpos];
1381 row->linkpos[newpos] = row->linkpos[oldpos];
1382
1383 /* update link position in column */
1384 if( row->linkpos[newpos] >= 0 )
1385 {
1386 assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1387 assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1388
1389 row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1390 }
1391
1392 /* update sorted flags */
1393 if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1394 row->lpcolssorted = FALSE;
1395 else
1396 row->nonlpcolssorted = FALSE;
1397}
1398
1399/** swaps two coefficients in a row, and updates all corresponding data structures */
1400static
1402 SCIP_ROW* row, /**< LP row */
1403 int pos1, /**< position of first coefficient */
1404 int pos2 /**< position of second coefficient */
1405 )
1406{
1407 SCIP_COL* tmpcol;
1408 SCIP_Real tmpval;
1409 int tmpindex;
1410 int tmplinkpos;
1411
1412 assert(row != NULL);
1413 assert(0 <= pos1 && pos1 < row->len);
1414 assert(0 <= pos2 && pos2 < row->len);
1415 assert(row->cols[pos1] != NULL);
1416 assert(row->cols[pos1]->index == row->cols_index[pos1]);
1417
1418 if( pos1 == pos2 )
1419 return;
1420
1421 /* swap coefficients */
1422 tmpcol = row->cols[pos2];
1423 tmpindex = row->cols_index[pos2];
1424 tmpval = row->vals[pos2];
1425 tmplinkpos = row->linkpos[pos2];
1426
1427 row->cols[pos2] = row->cols[pos1];
1428 row->cols_index[pos2] = row->cols_index[pos1];
1429 row->vals[pos2] = row->vals[pos1];
1430 row->linkpos[pos2] = row->linkpos[pos1];
1431
1432 row->cols[pos1] = tmpcol;
1433 row->cols_index[pos1] = tmpindex;
1434 row->vals[pos1] = tmpval;
1435 row->linkpos[pos1] = tmplinkpos;
1436
1437 /* update link position in columns */
1438 if( row->linkpos[pos1] >= 0 )
1439 {
1440 assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1441 assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1442
1443 row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1444 }
1445 if( row->linkpos[pos2] >= 0 )
1446 {
1447 assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1448 assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1449
1450 row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1451 }
1452
1453 /* update sorted flags */
1454 if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1455 row->lpcolssorted = FALSE;
1456 else
1457 row->nonlpcolssorted = FALSE;
1458 if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1459 row->lpcolssorted = FALSE;
1460 else
1461 row->nonlpcolssorted = FALSE;
1462}
1463
1464/** issues a ROWCOEFCHANGED event on the given row */
1465static
1467 SCIP_ROW* row, /**< row which coefficient has changed */
1468 BMS_BLKMEM* blkmem, /**< block memory */
1469 SCIP_SET* set, /**< global SCIP settings */
1470 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1471 SCIP_COL* col, /**< the column which coefficient has changed */
1472 SCIP_Real oldval, /**< old value of the coefficient */
1473 SCIP_Real newval /**< new value of the coefficient */
1474 )
1475{
1476 assert(row != NULL);
1477 assert(row->eventfilter != NULL);
1478 assert(col != NULL);
1479
1480 /* check, if the row is being tracked for coefficient changes
1481 * if so, issue ROWCOEFCHANGED event
1482 */
1483 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1484 {
1485 SCIP_EVENT* event;
1486
1487 SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1488 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1489 }
1490
1491 return SCIP_OKAY;
1492}
1493
1494/** issues a ROWCONSTCHANGED event on the given row */
1495static
1497 SCIP_ROW* row, /**< row which coefficient has changed */
1498 BMS_BLKMEM* blkmem, /**< block memory */
1499 SCIP_SET* set, /**< global SCIP settings */
1500 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1501 SCIP_Real oldval, /**< old value of the constant */
1502 SCIP_Real newval /**< new value of the constant */
1503 )
1504{
1505 assert(row != NULL);
1506 assert(row->eventfilter != NULL);
1507
1508 /* check, if the row is being tracked for coefficient changes
1509 * if so, issue ROWCONSTCHANGED event
1510 */
1512 {
1513 SCIP_EVENT* event;
1514
1515 SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1516 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1517 }
1518
1519 return SCIP_OKAY;
1520}
1521
1522/** issues a ROWSIDECHANGED event on the given row */
1523static
1525 SCIP_ROW* row, /**< row which coefficient has changed */
1526 BMS_BLKMEM* blkmem, /**< block memory */
1527 SCIP_SET* set, /**< global SCIP settings */
1528 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1529 SCIP_SIDETYPE side, /**< the side that has changed */
1530 SCIP_Real oldval, /**< old value of side */
1531 SCIP_Real newval /**< new value of side */
1532 )
1533{
1534 assert(row != NULL);
1535 assert(row->eventfilter != NULL);
1536
1537 /* check, if the row is being tracked for coefficient changes
1538 * if so, issue ROWSIDECHANGED event
1539 */
1540 if( (row->eventfilter->len > 0 && !(row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED)) )
1541 {
1542 SCIP_EVENT* event;
1543
1544 SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1545 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1546 }
1547
1548 return SCIP_OKAY;
1549}
1550
1551#ifdef SCIP_MORE_DEBUG /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */
1552
1553#ifdef NDEBUG
1554#define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1555#else
1556#define ASSERT(x) assert(x)
1557#endif
1558
1559static SCIP_Bool msgdisp_checklinks = FALSE;
1560
1561
1562static
1563void checkLinks(
1564 SCIP_LP* lp /**< current LP data */
1565 )
1566{
1567 SCIP_COL* col;
1568 SCIP_ROW* row;
1569 int i;
1570 int j;
1571
1572 ASSERT(lp != NULL);
1573
1574 if( !msgdisp_checklinks )
1575 {
1576 printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1577 msgdisp_checklinks = TRUE;
1578 }
1579
1580 for( i = 0; i < lp->ncols; ++i )
1581 {
1582 col = lp->cols[i];
1583 ASSERT(col != NULL);
1584 ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1585 ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1586 ASSERT(col->nlprows <= col->len);
1587 ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1588
1589 for( j = 0; j < col->len; ++j )
1590 {
1591 row = col->rows[j];
1592 ASSERT(row != NULL);
1593 ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1594 ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1595 ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1596 ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1597 }
1598 }
1599
1600 for( i = 0; i < lp->nrows; ++i )
1601 {
1602 row = lp->rows[i];
1603 ASSERT(row != NULL);
1604 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1605 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1606 ASSERT(row->nlpcols <= row->len);
1607 ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1608
1609 for( j = 0; j < row->len; ++j )
1610 {
1611 col = row->cols[j];
1612 ASSERT(col != NULL);
1613 ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1614 ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1615 ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1616 ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1617 }
1618 }
1619}
1620
1621#undef ASSERT
1622
1623#else
1624#define checkLinks(lp) /**/
1625#endif
1626
1627/*
1628 * Changing announcements
1629 */
1630
1631/** announces, that the given coefficient in the constraint matrix changed */
1632static
1634 SCIP_ROW* row, /**< LP row */
1635 SCIP_COL* col, /**< LP col */
1636 SCIP_LP* lp /**< current LP data */
1637 )
1638{
1639 assert(row != NULL);
1640 assert(col != NULL);
1641 assert(lp != NULL);
1642
1643 if( row->lpipos >= 0 && col->lpipos >= 0 )
1644 {
1645 assert(row->lpipos < lp->nlpirows);
1646 assert(col->lpipos < lp->nlpicols);
1647
1648 /* we have to remember the change only in the row or in the column,
1649 * because the readdition of one vector would change the other automatically.
1650 */
1651 if( row->lpipos >= lp->lpifirstchgrow )
1652 row->coefchanged = TRUE;
1653 else if( col->lpipos >= lp->lpifirstchgcol )
1654 col->coefchanged = TRUE;
1655 else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1656 {
1657 row->coefchanged = TRUE;
1658 lp->lpifirstchgrow = row->lpipos;
1659 }
1660 else
1661 {
1662 col->coefchanged = TRUE;
1663 lp->lpifirstchgcol = col->lpipos;
1664 }
1665
1666 /* mark the current LP unflushed */
1667 lp->flushed = FALSE;
1668 }
1669
1673 row->validpsactivitydomchg = -1;
1674 row->validactivitybdsdomchg = -1;
1675}
1676
1677
1678
1679/*
1680 * local column changing methods
1681 */
1682
1683/* forward declaration for colAddCoef() */
1684static
1686 SCIP_ROW* row, /**< LP row */
1687 BMS_BLKMEM* blkmem, /**< block memory */
1688 SCIP_SET* set, /**< global SCIP settings */
1689 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1690 SCIP_LP* lp, /**< current LP data */
1691 SCIP_COL* col, /**< LP column */
1692 SCIP_Real val, /**< value of coefficient */
1693 int linkpos /**< position of row in the column's row array, or -1 */
1694 );
1695
1696/** adds a previously non existing coefficient to an LP column */
1697static
1699 SCIP_COL* col, /**< LP column */
1700 BMS_BLKMEM* blkmem, /**< block memory */
1701 SCIP_SET* set, /**< global SCIP settings */
1702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1703 SCIP_LP* lp, /**< current LP data */
1704 SCIP_ROW* row, /**< LP row */
1705 SCIP_Real val, /**< value of coefficient */
1706 int linkpos /**< position of column in the row's col array, or -1 */
1707 )
1708{
1709 int pos;
1710
1711 assert(blkmem != NULL);
1712 assert(col != NULL);
1713 assert(col->nlprows <= col->len);
1714 assert(col->var != NULL);
1715 assert(row != NULL);
1716 assert(!SCIPsetIsZero(set, val));
1717 /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1718
1719 SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1720 assert(col->rows != NULL);
1721 assert(col->vals != NULL);
1722 assert(col->linkpos != NULL);
1723
1724 pos = col->len;
1725 col->len++;
1726
1727 /* if the row is in current LP and is linked to the column, we have to insert it at the end of the linked LP rows
1728 * part of the column's arrays
1729 */
1730 if( row->lppos >= 0 && linkpos >= 0 )
1731 {
1732 /* move the first non-LP/not linked row to the end */
1733 if( col->nlprows < pos )
1734 {
1735 colMoveCoef(col, col->nlprows, pos);
1736 pos = col->nlprows;
1737 }
1738 col->nlprows++;
1739 }
1740
1741 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1742 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1743
1744 /* insert the row at the correct position and update the links */
1745 col->rows[pos] = row;
1746 col->vals[pos] = val;
1747 col->linkpos[pos] = linkpos;
1748 if( linkpos == -1 )
1749 {
1750 col->nunlinked++;
1751
1752 /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1753 * of the row is not complete
1754 */
1755 if( col->lppos >= 0 )
1756 {
1757 /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1758 * has to be updated
1759 */
1760 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1761 if( row->lppos >= 0 )
1762 pos = col->nlprows-1;
1763 linkpos = col->linkpos[pos];
1764
1765 assert(0 <= linkpos && linkpos < row->len);
1766 assert(row->cols[linkpos] == col);
1767 assert(col->rows[pos] == row);
1768 assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1769 assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1770 }
1771 }
1772 else
1773 {
1774 assert(row->linkpos[linkpos] == -1);
1775 assert(row->nunlinked > 0);
1776 row->linkpos[linkpos] = pos;
1777 row->nunlinked--;
1778
1779 /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1780 * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1781 */
1782 if( col->lppos >= 0 )
1783 {
1784 row->nlpcols++;
1785 rowSwapCoefs(row, linkpos, row->nlpcols-1);
1786
1787 /* if no swap was necessary, mark nonlpcols to be unsorted */
1788 if( linkpos == row->nlpcols-1 )
1789 row->lpcolssorted = FALSE;
1790 }
1791 }
1792
1793 /* update the sorted flags */
1794 if( row->lppos >= 0 && linkpos >= 0 )
1795 {
1796 assert(col->nlprows >= 1);
1797 assert(col->rows[col->nlprows-1] == row);
1798 if( col->nlprows > 1 )
1799 col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1800 }
1801 else
1802 {
1803 assert(col->len - col->nlprows >= 1);
1804 assert(col->rows[col->len-1] == row);
1805 if( col->len - col->nlprows > 1 )
1806 col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1807 }
1808
1809 coefChanged(row, col, lp);
1810
1811 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1812 val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1813
1814 return SCIP_OKAY;
1815}
1816
1817/** deletes coefficient at given position from column */
1818static
1820 SCIP_COL* col, /**< column to be changed */
1821 SCIP_SET* set, /**< global SCIP settings */
1822 SCIP_LP* lp, /**< current LP data */
1823 int pos /**< position in column vector to delete */
1824 )
1825{
1826 SCIP_ROW* row;
1827
1828 assert(col != NULL);
1829 assert(col->var != NULL);
1830 assert(set != NULL);
1831 assert(0 <= pos && pos < col->len);
1832 assert(col->rows[pos] != NULL);
1833 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1834 assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1835
1836 row = col->rows[pos];
1837 assert((row->lppos >= 0) == (pos < col->nlprows));
1838
1839 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from column <%s>\n",
1840 col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1841
1842 if( col->linkpos[pos] == -1 )
1843 col->nunlinked--;
1844
1845 /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1846 if( pos < col->nlprows )
1847 {
1848 colMoveCoef(col, col->nlprows-1, pos);
1849 col->nlprows--;
1850 pos = col->nlprows;
1851 }
1852
1853 /* move last coefficient to position of empty slot */
1854 colMoveCoef(col, col->len-1, pos);
1855 col->len--;
1856
1857 coefChanged(row, col, lp);
1858
1859 return SCIP_OKAY;
1860}
1861
1862/** changes a coefficient at given position of an LP column */
1863static
1865 SCIP_COL* col, /**< LP column */
1866 SCIP_SET* set, /**< global SCIP settings */
1867 SCIP_LP* lp, /**< current LP data */
1868 int pos, /**< position in column vector to change */
1869 SCIP_Real val /**< value of coefficient */
1870 )
1871{
1872 assert(col != NULL);
1873 assert(col->var != NULL);
1874 assert(0 <= pos && pos < col->len);
1875 assert(col->rows[pos] != NULL);
1876 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1877
1878 /*debugMsg(scip, "changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1879 col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1880
1881 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1882 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1883
1884 if( SCIPsetIsZero(set, val) )
1885 {
1886 /* delete existing coefficient */
1887 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1888 }
1889 else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1890 {
1891 /* change existing coefficient */
1892 col->vals[pos] = val;
1893 coefChanged(col->rows[pos], col, lp);
1894 }
1895
1896 return SCIP_OKAY;
1897}
1898
1899
1900
1901
1902/*
1903 * local row changing methods
1904 */
1905
1906/** update row norms after addition of coefficient */
1907static
1909 SCIP_ROW* row, /**< LP row */
1910 SCIP_SET* set, /**< global SCIP settings */
1911 SCIP_COL* col, /**< column of added coefficient */
1912 SCIP_Real val, /**< value of added coefficient */
1913 SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */
1914 )
1915{
1916 SCIP_Real absval;
1917
1918 assert(row != NULL);
1919 assert(row->nummaxval >= 0);
1920 assert(row->numminval >= 0);
1921 assert(set != NULL);
1922 assert(col != NULL);
1923
1924 absval = REALABS(val);
1925 assert(!SCIPsetIsZero(set, absval));
1926
1927 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
1928 if( col->lppos >= 0 )
1929 {
1930 /* update squared Euclidean norm and sum norm */
1931 row->sqrnorm += SQR(absval);
1932 row->sumnorm += absval;
1933
1934 /* update objective function scalar product */
1935 row->objprod += val * col->unchangedobj;
1936 }
1937
1938 if( updateidxvals )
1939 {
1940 /* update min/maxidx */
1941 row->minidx = MIN(row->minidx, col->index);
1942 row->maxidx = MAX(row->maxidx, col->index);
1943
1944 /* update maximal and minimal non-zero value */
1945 if( row->nummaxval > 0 )
1946 {
1947 if( SCIPsetIsGT(set, absval, row->maxval) )
1948 {
1949 row->maxval = absval;
1950 row->nummaxval = 1;
1951 }
1952 else if( SCIPsetIsGE(set, absval, row->maxval) )
1953 {
1954 /* make sure the maxval is always exactly the same */
1955 row->maxval = MAX(absval, row->maxval);
1956 row->nummaxval++;
1957 }
1958 }
1959 if( row->numminval > 0 )
1960 {
1961 if( SCIPsetIsLT(set, absval, row->minval) )
1962 {
1963 row->minval = absval;
1964 row->numminval = 1;
1965 }
1966 else if( SCIPsetIsLE(set, absval, row->minval) )
1967 {
1968 /* make sure the minval is always exactly the same */
1969 row->minval = MIN(absval, row->minval);
1970 row->numminval++;
1971 }
1972 }
1973 }
1974 else
1975 {
1976 assert(row->minidx <= col->index);
1977 assert(row->maxidx >= col->index);
1978 assert(row->numminval <= 0 || absval >= row->minval);
1979 assert(row->nummaxval <= 0 || absval <= row->maxval);
1980 }
1981}
1982
1983/** update row norms after deletion of coefficient */
1984static
1986 SCIP_ROW* row, /**< LP row */
1987 SCIP_SET* set, /**< global SCIP settings */
1988 SCIP_COL* col, /**< column of deleted coefficient */
1989 SCIP_Real val, /**< value of deleted coefficient */
1990 SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */
1991 SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */
1992 SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */
1993 )
1994{
1995 SCIP_Real absval;
1996
1997 assert(row != NULL);
1998 assert(row->nummaxval >= 0);
1999 assert(row->numminval >= 0);
2000 assert(set != NULL);
2001 assert(col != NULL);
2002
2003 absval = REALABS(val);
2004 assert(!SCIPsetIsZero(set, absval));
2005 assert(row->nummaxval == 0 || row->maxval >= absval);
2006 assert(row->numminval == 0 || row->minval <= absval);
2007
2008 /* update min/maxidx validity */
2009 if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
2010 row->validminmaxidx = FALSE;
2011
2012 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
2013 if( forcenormupdate || col->lppos >= 0 )
2014 {
2015 /* update squared Euclidean norm and sum norm */
2016 row->sqrnorm -= SQR(absval);
2017 row->sqrnorm = MAX(row->sqrnorm, 0.0);
2018 row->sumnorm -= absval;
2019 row->sumnorm = MAX(row->sumnorm, 0.0);
2020
2021 /* update objective function scalar product */
2022 row->objprod -= val * col->unchangedobj;
2023 }
2024
2025 if( updateval )
2026 {
2027 /* update maximal and minimal non-zero value */
2028 if( row->nummaxval > 0 )
2029 {
2030 if( SCIPsetIsGE(set, absval, row->maxval) )
2031 row->nummaxval--;
2032 }
2033 if( row->numminval > 0 )
2034 {
2035 if( SCIPsetIsLE(set, absval, row->minval) )
2036 row->numminval--;
2037 }
2038 }
2039}
2040
2041/** adds a previously non existing coefficient to an LP row */
2042static
2044 SCIP_ROW* row, /**< LP row */
2045 BMS_BLKMEM* blkmem, /**< block memory */
2046 SCIP_SET* set, /**< global SCIP settings */
2047 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2048 SCIP_LP* lp, /**< current LP data */
2049 SCIP_COL* col, /**< LP column */
2050 SCIP_Real val, /**< value of coefficient */
2051 int linkpos /**< position of row in the column's row array, or -1 */
2052 )
2053{
2054 int pos;
2055
2056 assert(row != NULL);
2057 assert(row->nlpcols <= row->len);
2058 assert(blkmem != NULL);
2059 assert(col != NULL);
2060 assert(col->var != NULL);
2061 assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2062 assert(!SCIPsetIsZero(set, val));
2063 /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2064
2065 if( row->nlocks > 0 )
2066 {
2067 SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2068 return SCIP_INVALIDDATA;
2069 }
2070
2071 SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2072 assert(row->cols != NULL);
2073 assert(row->vals != NULL);
2074
2075 pos = row->len;
2076 row->len++;
2077
2078 /* if the column is in current LP and is linked to the row, we have to insert it at the end of the linked LP columns
2079 * part of the row's arrays
2080 */
2081 if( col->lppos >= 0 && linkpos >= 0 )
2082 {
2083 /* move the first non-LP/not linked column to the end */
2084 if( row->nlpcols < pos )
2085 {
2086 rowMoveCoef(row, row->nlpcols, pos);
2087 pos = row->nlpcols;
2088 }
2089 row->nlpcols++;
2090 }
2091
2092 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2093 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2094
2095 /* insert the column at the correct position and update the links */
2096 row->cols[pos] = col;
2097 row->cols_index[pos] = col->index;
2098 row->vals[pos] = val;
2099 row->linkpos[pos] = linkpos;
2100 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2101 if( linkpos == -1 )
2102 {
2103 row->nunlinked++;
2104
2105 /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2106 * of the column is not complete
2107 */
2108 if( row->lppos >= 0 )
2109 {
2110 /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2111 * has to be updated
2112 */
2113 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2114 if( col->lppos >= 0 )
2115 pos = row->nlpcols-1;
2116 linkpos = row->linkpos[pos];
2117
2118 assert(0 <= linkpos && linkpos < col->len);
2119 assert(col->rows[linkpos] == row);
2120 assert(row->cols[pos] == col);
2121 assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2122 assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2123 }
2124 }
2125 else
2126 {
2127 assert(col->linkpos[linkpos] == -1);
2128 assert(col->nunlinked > 0);
2129 col->linkpos[linkpos] = pos;
2130 col->nunlinked--;
2131
2132 /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2133 * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2134 */
2135 if( row->lppos >= 0 )
2136 {
2137 col->nlprows++;
2138 colSwapCoefs(col, linkpos, col->nlprows-1);
2139
2140 /* if no swap was necessary, mark lprows to be unsorted */
2141 if( linkpos == col->nlprows-1 )
2142 col->lprowssorted = FALSE;
2143 }
2144 }
2145
2146 /* update the sorted flags */
2147 if( col->lppos >= 0 && linkpos >= 0 )
2148 {
2149 assert(row->nlpcols >= 1);
2150 assert(row->cols[row->nlpcols-1] == col);
2151 if( row->nlpcols > 1 )
2152 {
2153 assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2154 row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2155 }
2156 }
2157 else
2158 {
2159 assert(row->len - row->nlpcols >= 1);
2160 assert(row->cols[row->len-1] == col);
2161 if( row->len - row->nlpcols > 1 )
2162 {
2163 assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2164 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2165 }
2166 }
2167
2168 /* update row norm */
2169 rowAddNorms(row, set, col, val, TRUE);
2170
2171 coefChanged(row, col, lp);
2172
2173 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2174 val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2175
2176 /* issue row coefficient changed event */
2177 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2178
2179 return SCIP_OKAY;
2180}
2181
2182/** deletes coefficient at given position from row */
2183static
2185 SCIP_ROW* row, /**< row to be changed */
2186 BMS_BLKMEM* blkmem, /**< block memory */
2187 SCIP_SET* set, /**< global SCIP settings */
2188 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2189 SCIP_LP* lp, /**< current LP data */
2190 int pos /**< position in row vector to delete */
2191 )
2192{
2193 SCIP_COL* col;
2194 SCIP_Real val;
2195
2196 assert(row != NULL);
2197 assert(set != NULL);
2198 assert(0 <= pos && pos < row->len);
2199 assert(row->cols[pos] != NULL);
2200 assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2201
2202 col = row->cols[pos];
2203 val = row->vals[pos];
2204 assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2205
2206 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from row <%s>\n",
2207 val, SCIPvarGetName(col->var), pos, row->name);*/
2208
2209 if( row->nlocks > 0 )
2210 {
2211 SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2212 return SCIP_INVALIDDATA;
2213 }
2214
2215 if( row->linkpos[pos] == -1 )
2216 row->nunlinked--;
2217
2218 /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2219 if( pos < row->nlpcols )
2220 {
2221 rowMoveCoef(row, row->nlpcols-1, pos);
2222 assert(!row->lpcolssorted);
2223 row->nlpcols--;
2224 pos = row->nlpcols;
2225 }
2226
2227 /* move last coefficient to position of empty slot */
2228 rowMoveCoef(row, row->len-1, pos);
2229 row->len--;
2230
2231 /* update norms */
2232 rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2233
2234 coefChanged(row, col, lp);
2235
2236 /* issue row coefficient changed event */
2237 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2238
2239 return SCIP_OKAY;
2240}
2241
2242/** changes a coefficient at given position of an LP row */
2243static
2245 SCIP_ROW* row, /**< LP row */
2246 BMS_BLKMEM* blkmem, /**< block memory */
2247 SCIP_SET* set, /**< global SCIP settings */
2248 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2249 SCIP_LP* lp, /**< current LP data */
2250 int pos, /**< position in row vector to change */
2251 SCIP_Real val /**< value of coefficient */
2252 )
2253{
2254 SCIP_COL* col;
2255
2256 assert(row != NULL);
2257 assert(0 <= pos && pos < row->len);
2258
2259 /*SCIPsetDebugMsg(set, "changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2260 row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2261
2262 if( row->nlocks > 0 )
2263 {
2264 SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2265 return SCIP_INVALIDDATA;
2266 }
2267
2268 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2269 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2270 col = row->cols[pos];
2271 assert(row->cols[pos] != NULL);
2272
2273 if( SCIPsetIsZero(set, val) )
2274 {
2275 /* delete existing coefficient */
2276 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2277 }
2278 else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2279 {
2280 SCIP_Real oldval;
2281
2282 oldval = row->vals[pos];
2283
2284 /* change existing coefficient */
2285 rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2286 row->vals[pos] = val;
2287 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2288 rowAddNorms(row, set, col, row->vals[pos], TRUE);
2289 coefChanged(row, col, lp);
2290
2291 /* issue row coefficient changed event */
2292 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2293 }
2294
2295 return SCIP_OKAY;
2296}
2297
2298/** notifies LP row, that its sides were changed */
2299static
2301 SCIP_ROW* row, /**< LP row */
2302 SCIP_SET* set, /**< global SCIP settings */
2303 SCIP_LP* lp, /**< current LP data */
2304 SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */
2305 )
2306{
2307 assert(row != NULL);
2308 assert(lp != NULL);
2309
2310 if( row->lpipos >= 0 )
2311 {
2312 /* insert row in the chgrows list (if not already there) */
2313 if( !row->lhschanged && !row->rhschanged )
2314 {
2315 SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2316 lp->chgrows[lp->nchgrows] = row;
2317 lp->nchgrows++;
2318 }
2319
2320 /* mark side change in the row */
2321 switch( sidetype )
2322 {
2323 case SCIP_SIDETYPE_LEFT:
2324 row->lhschanged = TRUE;
2325 break;
2327 row->rhschanged = TRUE;
2328 break;
2329 default:
2330 SCIPerrorMessage("unknown row side type\n");
2331 SCIPABORT();
2332 return SCIP_INVALIDDATA; /*lint !e527*/
2333 }
2334
2335 /* mark the current LP unflushed */
2336 lp->flushed = FALSE;
2337
2338 assert(lp->nchgrows > 0);
2339 }
2340
2341 return SCIP_OKAY;
2342}
2343
2344
2345
2346
2347/*
2348 * double linked coefficient matrix methods
2349 */
2350
2351/** insert column coefficients in corresponding rows */
2353 SCIP_COL* col, /**< column data */
2354 BMS_BLKMEM* blkmem, /**< block memory */
2355 SCIP_SET* set, /**< global SCIP settings */
2356 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2357 SCIP_LP* lp /**< current LP data */
2358 )
2359{
2360 int i;
2361
2362 assert(col != NULL);
2363 assert(col->var != NULL);
2364 assert(blkmem != NULL);
2365 assert(set != NULL);
2366 assert(lp != NULL);
2367
2368 if( col->nunlinked > 0 )
2369 {
2370 SCIPsetDebugMsg(set, "linking column <%s>\n", SCIPvarGetName(col->var));
2371
2372 /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2373 for( i = col->nlprows; i < col->len; ++i )
2374 {
2375 assert(!SCIPsetIsZero(set, col->vals[i]));
2376 if( col->linkpos[i] == -1 )
2377 {
2378 /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2379 SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2380 }
2381 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2382 assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2383 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2384 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2385 }
2386 }
2387 assert(col->nunlinked == 0);
2388
2389 checkLinks(lp);
2390
2391 return SCIP_OKAY;
2392}
2393
2394/** removes column coefficients from corresponding rows */
2396 SCIP_COL* col, /**< column data */
2397 BMS_BLKMEM* blkmem, /**< block memory */
2398 SCIP_SET* set, /**< global SCIP settings */
2399 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2400 SCIP_LP* lp /**< current LP data */
2401 )
2402{
2403 int i;
2404
2405 assert(col != NULL);
2406 assert(col->var != NULL);
2407 assert(blkmem != NULL);
2408 assert(set != NULL);
2409 assert(lp != NULL);
2410
2411 if( col->nunlinked < col->len )
2412 {
2413 SCIPsetDebugMsg(set, "unlinking column <%s>\n", SCIPvarGetName(col->var));
2414 for( i = 0; i < col->len; ++i )
2415 {
2416 if( col->linkpos[i] >= 0 )
2417 {
2418 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2419 SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2420 col->linkpos[i] = -1;
2421 col->nunlinked++;
2422 }
2423 }
2424 }
2425 assert(col->nunlinked == col->len);
2426
2427 checkLinks(lp);
2428
2429 return SCIP_OKAY;
2430}
2431
2432/** insert row coefficients in corresponding columns */
2434 SCIP_ROW* row, /**< row data */
2435 BMS_BLKMEM* blkmem, /**< block memory */
2436 SCIP_SET* set, /**< global SCIP settings */
2437 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2438 SCIP_LP* lp /**< current LP data */
2439 )
2440{
2441 int i;
2442
2443 assert(row != NULL);
2444 assert(blkmem != NULL);
2445 assert(set != NULL);
2446 assert(lp != NULL);
2447
2448 if( row->nunlinked > 0 )
2449 {
2450 SCIPsetDebugMsg(set, "linking row <%s>\n", row->name);
2451
2452 /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2453 for( i = row->nlpcols; i < row->len; ++i )
2454 {
2455 assert(!SCIPsetIsZero(set, row->vals[i]));
2456 if( row->linkpos[i] == -1 )
2457 {
2458 /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2459 SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2460 }
2461 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2462 assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2463 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2464 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2465 }
2466 }
2467 assert(row->nunlinked == 0);
2468
2469 checkLinks(lp);
2470
2471 return SCIP_OKAY;
2472}
2473
2474/** removes row coefficients from corresponding columns */
2476 SCIP_ROW* row, /**< row data */
2477 SCIP_SET* set, /**< global SCIP settings */
2478 SCIP_LP* lp /**< current LP data */
2479 )
2480{
2481 int i;
2482
2483 assert(row != NULL);
2484 assert(set != NULL);
2485 assert(lp != NULL);
2486
2487 if( row->nunlinked < row->len )
2488 {
2489 SCIPsetDebugMsg(set, "unlinking row <%s>\n", row->name);
2490 for( i = 0; i < row->len; ++i )
2491 {
2492 if( row->linkpos[i] >= 0 )
2493 {
2494 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2495 SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2496 row->nunlinked++;
2497 }
2498 }
2499 }
2500 assert(row->nunlinked == row->len);
2501
2502 return SCIP_OKAY;
2503}
2504
2505
2506
2507
2508/*
2509 * local LP parameter methods
2510 */
2511
2512/** sets parameter of type int in LP solver, ignoring unknown parameters */
2513static
2515 SCIP_LP* lp, /**< current LP data */
2516 SCIP_LPPARAM lpparam, /**< LP parameter */
2517 int value, /**< value to set parameter to */
2518 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2519 )
2520{
2521 SCIP_RETCODE retcode;
2522
2523 assert(lp != NULL);
2524 assert(success != NULL);
2525
2526 retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2527
2528 /* check, if parameter is unknown */
2529 if( retcode == SCIP_PARAMETERUNKNOWN )
2530 {
2531 *success = FALSE;
2532 return SCIP_OKAY;
2533 }
2534 *success = TRUE;
2535
2536 return retcode;
2537}
2538
2539/** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2540static
2542 SCIP_LP* lp, /**< current LP data */
2543 SCIP_LPPARAM lpparam, /**< LP parameter */
2544 SCIP_Bool value, /**< value to set parameter to */
2545 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2546 )
2547{
2548 return lpSetIntpar(lp, lpparam, (int)value, success);
2549}
2550
2551/** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2552static
2554 SCIP_LP* lp, /**< current LP data */
2555 SCIP_LPPARAM lpparam, /**< LP parameter */
2556 SCIP_Real value, /**< value to set parameter to */
2557 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2558 )
2559{
2560 SCIP_RETCODE retcode;
2561
2562 assert(lp != NULL);
2563 assert(success != NULL);
2564
2565 retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2566
2567 /* check, if parameter is unknown */
2568 if( retcode == SCIP_PARAMETERUNKNOWN )
2569 {
2570 *success = FALSE;
2571 return SCIP_OKAY;
2572 }
2573 *success = TRUE;
2574
2575 return retcode;
2576}
2577
2578#ifndef NDEBUG
2579/** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2580static
2582 SCIP_LP* lp, /**< current LP data */
2583 SCIP_LPPARAM lpparam, /**< LP parameter */
2584 int value /**< value parameter should have */
2585 )
2586{
2587 SCIP_RETCODE retcode;
2588 int lpivalue;
2589
2590 assert(lp != NULL);
2591
2592 retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2593
2594 /* ignore unknown parameter error */
2595 if( retcode == SCIP_PARAMETERUNKNOWN )
2596 return SCIP_OKAY;
2597
2598 /* check value */
2599 assert(lpivalue == value);
2600
2601 return retcode;
2602}
2603
2604/** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2605static
2607 SCIP_LP* lp, /**< current LP data */
2608 SCIP_LPPARAM lpparam, /**< LP parameter */
2609 SCIP_Bool value /**< value parameter should have */
2610 )
2611{
2612 return lpCheckIntpar(lp, lpparam, (int)value);
2613}
2614
2615/** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2616static
2618 SCIP_LP* lp, /**< current LP data */
2619 SCIP_LPPARAM lpparam, /**< LP parameter */
2620 SCIP_Real value /**< value parameter should have */
2621 )
2622{
2623 SCIP_RETCODE retcode;
2624 SCIP_Real lpivalue;
2625
2626 assert(lp != NULL);
2627
2628 retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2629
2630 /* ignore unknown parameter error */
2631 if( retcode == SCIP_PARAMETERUNKNOWN )
2632 return SCIP_OKAY;
2633
2634 /* check value */
2635 assert(lpivalue == value); /*lint !e777*/
2636
2637 return retcode;
2638}
2639#else
2640#define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2641#define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2642#define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2643#endif
2644
2645/** should the objective limit of the LP solver be disabled */
2646#define lpCutoffDisabled(set,prob) (set->lp_disablecutoff == 1 || ((set->nactivepricers > 0 || !SCIPprobAllColsInLP(prob, set, lp)) && set->lp_disablecutoff == 2))
2647
2648/** sets the objective limit of the LP solver
2649 *
2650 * Note that we are always minimizing.
2651 */
2652static
2654 SCIP_LP* lp, /**< current LP data */
2655 SCIP_SET* set, /**< global SCIP settings */
2656 SCIP_PROB* prob, /**< problem data */
2657 SCIP_Real objlim, /**< new objective limit */
2658 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2659 )
2660{
2661 assert(lp != NULL);
2662 assert(set != NULL);
2663 assert(success != NULL);
2664
2665 *success = FALSE;
2666
2667 /* We disabled the objective limit in the LP solver or we want so solve exactly and thus cannot rely on the LP
2668 * solver's objective limit handling, so we make sure that the objective limit is inactive (infinity). */
2669 if( lpCutoffDisabled(set, prob) || set->misc_exactsolve )
2670 objlim = SCIPlpiInfinity(lp->lpi);
2671
2672 /* convert SCIP infinity value to lp-solver infinity value if necessary */
2673 if( SCIPsetIsInfinity(set, objlim) )
2674 objlim = SCIPlpiInfinity(lp->lpi);
2675
2677
2678 if( objlim != lp->lpiobjlim ) /*lint !e777*/
2679 {
2680 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) );
2681 if( *success )
2682 {
2683 SCIP_Real actualobjlim;
2684
2685 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2686 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) );
2687 if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/
2688 {
2689 /* mark the current solution invalid */
2690 lp->solved = FALSE;
2691 lp->primalfeasible = FALSE;
2692 lp->primalchecked = FALSE;
2693 lp->lpobjval = SCIP_INVALID;
2695 }
2696 lp->lpiobjlim = actualobjlim;
2697 }
2698 }
2699
2700 return SCIP_OKAY;
2701}
2702
2703/** sets the feasibility tolerance of the LP solver */
2704static
2706 SCIP_LP* lp, /**< current LP data */
2707 SCIP_Real feastol, /**< new feasibility tolerance */
2708 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2709 )
2710{
2711 assert(lp != NULL);
2712 assert(feastol >= 0.0);
2713 assert(success != NULL);
2714
2716
2717 if( feastol != lp->lpifeastol ) /*lint !e777*/
2718 {
2719 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2720 if( *success )
2721 {
2722 SCIP_Real actualfeastol;
2723
2724 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2725 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) );
2726 if( lp->nrows > 0 && actualfeastol < lp->lpifeastol )
2727 {
2728 /* mark the current solution invalid */
2729 lp->solved = FALSE;
2730 lp->primalfeasible = FALSE;
2731 lp->primalchecked = FALSE;
2732 lp->lpobjval = SCIP_INVALID;
2734 }
2735 else
2736 *success = FALSE;
2737 lp->lpifeastol = actualfeastol;
2738 }
2739 }
2740 else
2741 *success = FALSE;
2742
2743 return SCIP_OKAY;
2744}
2745
2746/** sets the reduced costs feasibility tolerance of the LP solver */
2747static
2749 SCIP_LP* lp, /**< current LP data */
2750 SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2751 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2752 )
2753{
2754 assert(lp != NULL);
2755 assert(dualfeastol >= 0.0);
2756 assert(success != NULL);
2757
2759
2760 if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2761 {
2762 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2763 if( *success )
2764 {
2765 SCIP_Real actualdualfeastol;
2766
2767 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2768 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) );
2769 if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol )
2770 {
2771 /* mark the current solution invalid */
2772 lp->solved = FALSE;
2773 lp->dualfeasible = FALSE;
2774 lp->dualchecked = FALSE;
2775 lp->lpobjval = SCIP_INVALID;
2777 }
2778 else
2779 *success = FALSE;
2780 lp->lpidualfeastol = actualdualfeastol;
2781 }
2782 }
2783 else
2784 *success = FALSE;
2785
2786 return SCIP_OKAY;
2787}
2788
2789/** sets the convergence tolerance used in barrier algorithm of the LP solver */
2790static
2792 SCIP_LP* lp, /**< current LP data */
2793 SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2794 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2795 )
2796{
2797 assert(lp != NULL);
2798 assert(barrierconvtol >= 0.0);
2799 assert(success != NULL);
2800
2802
2803 if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2804 {
2805 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2806 if( *success )
2807 {
2808 SCIP_Real actualbarrierconvtol;
2809
2810 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2811 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) );
2812 if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol
2814 {
2815 /* mark the current solution invalid */
2816 lp->solved = FALSE;
2817 lp->dualfeasible = FALSE;
2818 lp->dualchecked = FALSE;
2819 lp->lpobjval = SCIP_INVALID;
2821 }
2822 else
2823 *success = FALSE;
2824 lp->lpibarrierconvtol = actualbarrierconvtol;
2825 }
2826 }
2827 else
2828 *success = FALSE;
2829
2830 return SCIP_OKAY;
2831}
2832
2833/** sets the FROMSCRATCH setting of the LP solver */
2834static
2836 SCIP_LP* lp, /**< current LP data */
2837 SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2838 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2839 )
2840{
2841 assert(lp != NULL);
2842 assert(success != NULL);
2843
2845
2846 if( fromscratch != lp->lpifromscratch )
2847 {
2848 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2849 if( *success )
2850 lp->lpifromscratch = fromscratch;
2851 }
2852 else
2853 *success = FALSE;
2854
2855 return SCIP_OKAY;
2856}
2857
2858/** sets the FASTMIP setting of the LP solver */
2859static
2861 SCIP_LP* lp, /**< current LP data */
2862 int fastmip, /**< new FASTMIP setting */
2863 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2864 )
2865{
2866 assert(lp != NULL);
2867 assert(success != NULL);
2868 assert(0 <= fastmip && fastmip <= 1);
2869
2871
2872 if( fastmip != lp->lpifastmip )
2873 {
2874 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2875 if( *success )
2876 {
2877 lp->lpifastmip = fastmip;
2878 lp->solved = FALSE;
2879 /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more
2880 * demanding setting; however, in the current code, this should have not effect. */
2881 }
2882 }
2883 else
2884 *success = FALSE;
2885
2886 return SCIP_OKAY;
2887}
2888
2889/** sets the SCALING setting of the LP solver */
2890static
2892 SCIP_LP* lp, /**< current LP data */
2893 int scaling, /**< new SCALING setting */
2894 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2895 )
2896{
2897 assert(lp != NULL);
2898 assert(success != NULL);
2899
2901
2902 if( scaling != lp->lpiscaling )
2903 {
2904 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2905 if( *success )
2906 lp->lpiscaling = scaling;
2907 }
2908 else
2909 *success = FALSE;
2910
2911 return SCIP_OKAY;
2912}
2913
2914/** sets the number of THREADS of the LP solver */
2915static
2917 SCIP_LP* lp, /**< current LP data */
2918 int threads, /**< new number of threads used to solve the LP */
2919 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2920 )
2921{
2922 assert(lp != NULL);
2923 assert(success != NULL);
2924
2926
2927 if( threads != lp->lpithreads )
2928 {
2929 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2930 if( *success )
2931 lp->lpithreads = threads;
2932 }
2933 else
2934 *success = FALSE;
2935
2936 return SCIP_OKAY;
2937}
2938
2939/** sets the PRESOLVING setting of the LP solver */
2940static
2942 SCIP_LP* lp, /**< current LP data */
2943 SCIP_Bool presolving, /**< new PRESOLVING setting */
2944 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2945 )
2946{
2947 assert(lp != NULL);
2948 assert(success != NULL);
2949
2951
2952 if( presolving != lp->lpipresolving )
2953 {
2954 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2955 if( *success )
2956 lp->lpipresolving = presolving;
2957 }
2958 else
2959 *success = FALSE;
2960
2961 return SCIP_OKAY;
2962}
2963
2964/** sets the ROWREPSWITCH setting of the LP solver */
2965static
2967 SCIP_LP* lp, /**< current LP data */
2968 SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2969 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2970 )
2971{
2972 assert(lp != NULL);
2973 assert(success != NULL);
2974
2976
2977 if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2978 {
2979 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2980 if( *success )
2981 lp->lpirowrepswitch = rowrepswitch;
2982 }
2983 else
2984 *success = FALSE;
2985
2986 return SCIP_OKAY;
2987}
2988
2989/** sets the iteration limit of the LP solver */
2990static
2992 SCIP_LP* lp, /**< current LP data */
2993 int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2994 )
2995{
2996 SCIP_Bool success;
2997
2998 assert(lp != NULL);
2999 assert(itlim >= -1);
3000
3001 if( itlim == -1 )
3002 itlim = INT_MAX;
3003
3005
3006 if( itlim != lp->lpiitlim )
3007 {
3008 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
3009 if( success )
3010 {
3011 if( itlim > lp->lpiitlim )
3012 {
3013 /* mark the current solution invalid */
3014 lp->solved = FALSE;
3015 lp->lpobjval = SCIP_INVALID;
3017 }
3018 lp->lpiitlim = itlim;
3019 }
3020 }
3021
3022 return SCIP_OKAY;
3023}
3024
3025/** sets the pricing strategy of the LP solver */
3026static
3028 SCIP_LP* lp, /**< current LP data */
3029 SCIP_PRICING pricing /**< pricing strategy */
3030 )
3031{
3032 SCIP_Bool success;
3033
3034 assert(lp != NULL);
3035
3037
3038 if( pricing != lp->lpipricing )
3039 {
3040 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
3041 if( success )
3042 lp->lpipricing = pricing;
3043 }
3044
3045 return SCIP_OKAY;
3046}
3047
3048/** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
3049static
3051 SCIP_LP* lp, /**< current LP data */
3052 char pricingchar /**< character representing the pricing strategy */
3053 )
3054{
3055 SCIP_PRICING pricing;
3056
3057 switch( pricingchar )
3058 {
3059 case 'l':
3060 pricing = SCIP_PRICING_LPIDEFAULT;
3061 break;
3062 case 'a':
3063 pricing = SCIP_PRICING_AUTO;
3064 break;
3065 case 'f':
3066 pricing = SCIP_PRICING_FULL;
3067 break;
3068 case 'p':
3069 pricing = SCIP_PRICING_PARTIAL;
3070 break;
3071 case 's':
3072 pricing = SCIP_PRICING_STEEP;
3073 break;
3074 case 'q':
3075 pricing = SCIP_PRICING_STEEPQSTART;
3076 break;
3077 case 'd':
3078 pricing = SCIP_PRICING_DEVEX;
3079 break;
3080 default:
3081 SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
3082 return SCIP_INVALIDDATA;
3083 }
3084
3085 SCIP_CALL( lpSetPricing(lp, pricing) );
3086
3087 return SCIP_OKAY;
3088}
3089
3090/** sets the verbosity of the LP solver */
3091static
3093 SCIP_LP* lp, /**< current LP data */
3094 SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3095 )
3096{
3097 SCIP_Bool success;
3098
3099 assert(lp != NULL);
3100
3102
3103 if( lpinfo != lp->lpilpinfo )
3104 {
3105 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3106 if( success )
3107 lp->lpilpinfo = lpinfo;
3108 }
3109
3110 return SCIP_OKAY;
3111}
3112
3113/** sets the CONDITIONLIMIT setting of the LP solver */
3114static
3116 SCIP_LP* lp, /**< current LP data */
3117 SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3118 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3119 )
3120{
3121 assert(lp != NULL);
3122 assert(success != NULL);
3123
3125
3126 if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3127 {
3128 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3129 if( *success )
3130 lp->lpiconditionlimit = condlimit;
3131 }
3132 else
3133 *success = FALSE;
3134
3135 return SCIP_OKAY;
3136}
3137
3138/** sets the MARKOWITZ setting of the LP solver */
3139static
3141 SCIP_LP* lp, /**< current LP data */
3142 SCIP_Real threshhold, /**< new MARKOWITZ value */
3143 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3144 )
3145{
3146 assert(lp != NULL);
3147 assert(success != NULL);
3148
3150
3151 if( threshhold != lp->lpimarkowitz ) /*lint !e777*/
3152 {
3153 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) );
3154 if( *success )
3155 lp->lpimarkowitz = threshhold;
3156 }
3157 else
3158 *success = FALSE;
3159
3160 return SCIP_OKAY;
3161}
3162
3163/** sets the type of timer of the LP solver */
3164static
3166 SCIP_LP* lp, /**< current LP data */
3167 SCIP_CLOCKTYPE timing, /**< new timing value */
3168 SCIP_Bool enabled, /**< is timing enabled? */
3169 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3170 )
3171{
3172 int lptiming;
3173
3174 assert(lp != NULL);
3175 assert(success != NULL);
3176 assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/
3177
3179
3180 if( !enabled )
3181 lptiming = 0;
3182 else
3183 lptiming = (int) timing;
3184
3185 if( lptiming != lp->lpitiming ) /*lint !e777*/
3186 {
3187 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3188 if( *success )
3189 lp->lpitiming = lptiming;
3190 }
3191 else
3192 *success = FALSE;
3193
3194 return SCIP_OKAY;
3195}
3196
3197/** sets the initial random seed of the LP solver */
3198static
3200 SCIP_LP* lp, /**< current LP data */
3201 int randomseed, /**< new initial random seed */
3202 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3203 )
3204{
3205 assert(lp != NULL);
3206 assert(success != NULL);
3207
3208 /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */
3209
3210 if( randomseed == 0 )
3211 {
3212 lp->lpirandomseed = randomseed;
3213 *success = TRUE;
3214 }
3215 else if( randomseed != lp->lpirandomseed ) /*lint !e777*/
3216 {
3217 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) );
3218 if( *success )
3219 lp->lpirandomseed = randomseed;
3220 }
3221 else
3222 *success = FALSE;
3223
3224 return SCIP_OKAY;
3225}
3226
3227/** sets the LP solution polishing method */
3228static
3230 SCIP_LP* lp, /**< current LP data */
3231 SCIP_Bool polishing, /**< LP solution polishing activated (0: disabled, 1: enabled) */
3232 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3233 )
3234{
3235 assert(lp != NULL);
3236 assert(success != NULL);
3237
3238 if( polishing != lp->lpisolutionpolishing )
3239 {
3240 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) );
3241 if( *success )
3242 lp->lpisolutionpolishing = polishing;
3243 }
3244 else
3245 *success = FALSE;
3246
3247 return SCIP_OKAY;
3248}
3249
3250/** sets the LP refactorization interval */
3251static
3253 SCIP_LP* lp, /**< current LP data */
3254 int refactor, /**< LP refactorization interval (0: automatic) */
3255 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3256 )
3257{
3258 assert(lp != NULL);
3259 assert(success != NULL);
3260
3261 if( refactor != lp->lpirefactorinterval )
3262 {
3263 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) );
3264 if( *success )
3265 lp->lpirefactorinterval = refactor;
3266 }
3267 else
3268 *success = FALSE;
3269
3270 return SCIP_OKAY;
3271}
3272
3273
3274/*
3275 * Column methods
3276 */
3277
3278/** creates an LP column */
3280 SCIP_COL** col, /**< pointer to column data */
3281 BMS_BLKMEM* blkmem, /**< block memory */
3282 SCIP_SET* set, /**< global SCIP settings */
3283 SCIP_STAT* stat, /**< problem statistics */
3284 SCIP_VAR* var, /**< variable, this column represents */
3285 int len, /**< number of nonzeros in the column */
3286 SCIP_ROW** rows, /**< array with rows of column entries */
3287 SCIP_Real* vals, /**< array with coefficients of column entries */
3288 SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3289 )
3290{
3291 int i;
3292
3293 assert(col != NULL);
3294 assert(blkmem != NULL);
3295 assert(set != NULL);
3296 assert(stat != NULL);
3297 assert(var != NULL);
3298 assert(len >= 0);
3299 assert(len == 0 || (rows != NULL && vals != NULL));
3300
3301 SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3302
3303 if( len > 0 )
3304 {
3305 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3306 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3307 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3308
3309 for( i = 0; i < len; ++i )
3310 {
3311 assert(rows[i] != NULL);
3312 assert(!SCIPsetIsZero(set, vals[i]));
3313 (*col)->linkpos[i] = -1;
3314 }
3315 }
3316 else
3317 {
3318 (*col)->rows = NULL;
3319 (*col)->vals = NULL;
3320 (*col)->linkpos = NULL;
3321 }
3322
3323 (*col)->var = var;
3324 (*col)->obj = SCIPvarGetObj(var);
3325 (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3326 (*col)->lb = SCIPvarGetLbLocal(var);
3327 (*col)->ub = SCIPvarGetUbLocal(var);
3328 (*col)->flushedobj = 0.0;
3329 (*col)->flushedlb = 0.0;
3330 (*col)->flushedub = 0.0;
3331 (*col)->index = stat->ncolidx;
3332 SCIPstatIncrement(stat, set, ncolidx);
3333 (*col)->size = len;
3334 (*col)->len = len;
3335 (*col)->nlprows = 0;
3336 (*col)->nunlinked = len;
3337 (*col)->lppos = -1;
3338 (*col)->lpipos = -1;
3339 (*col)->lpdepth = -1;
3340 (*col)->primsol = 0.0;
3341 (*col)->redcost = SCIP_INVALID;
3342 (*col)->farkascoef = SCIP_INVALID;
3343 (*col)->minprimsol = (*col)->ub;
3344 (*col)->maxprimsol = (*col)->lb;
3345 (*col)->sbdown = SCIP_INVALID;
3346 (*col)->sbup = SCIP_INVALID;
3347 (*col)->sbsolval = SCIP_INVALID;
3348 (*col)->sblpobjval = SCIP_INVALID;
3349 (*col)->sbnode = -1;
3350 (*col)->validredcostlp = -1;
3351 (*col)->validfarkaslp = -1;
3352 (*col)->validsblp = -1;
3353 (*col)->sbitlim = -1;
3354 (*col)->nsbcalls = 0;
3355 (*col)->age = 0;
3356 (*col)->obsoletenode = -1;
3357 (*col)->var_probindex = SCIPvarGetProbindex(var);
3358 (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3359 (*col)->lprowssorted = TRUE;
3360 (*col)->nonlprowssorted = (len <= 1);
3361 (*col)->objchanged = FALSE;
3362 (*col)->lbchanged = FALSE;
3363 (*col)->ubchanged = FALSE;
3364 (*col)->coefchanged = FALSE;
3365 (*col)->integral = SCIPvarIsIntegral(var);
3366 (*col)->removable = removable;
3367 (*col)->sbdownvalid = FALSE;
3368 (*col)->sbupvalid = FALSE;
3369 (*col)->lazylb = SCIPvarGetLbLazy(var);
3370 (*col)->lazyub = SCIPvarGetUbLazy(var);
3371 (*col)->storedsolvals = NULL;
3372
3373 return SCIP_OKAY;
3374}
3375
3376/** frees an LP column */
3378 SCIP_COL** col, /**< pointer to LP column */
3379 BMS_BLKMEM* blkmem, /**< block memory */
3380 SCIP_SET* set, /**< global SCIP settings */
3381 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3382 SCIP_LP* lp /**< current LP data */
3383 )
3384{
3385 assert(blkmem != NULL);
3386 assert(col != NULL);
3387 assert(*col != NULL);
3388 assert((*col)->var != NULL);
3389 assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3390 assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3391 assert((*col)->lppos == -1);
3392 assert((*col)->lpipos == -1);
3393
3394 /* remove column indices from corresponding rows */
3395 SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3396
3397 BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3398 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3399 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3400 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3401 BMSfreeBlockMemory(blkmem, col);
3402
3403 return SCIP_OKAY;
3404}
3405
3406/** output column to file stream */
3408 SCIP_COL* col, /**< LP column */
3409 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3410 FILE* file /**< output file (or NULL for standard output) */
3411 )
3412{
3413 int r;
3414
3415 assert(col != NULL);
3416 assert(col->var != NULL);
3417
3418 /* print bounds */
3419 SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3420
3421 /* print coefficients */
3422 if( col->len == 0 )
3423 SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3424 for( r = 0; r < col->len; ++r )
3425 {
3426 assert(col->rows[r] != NULL);
3427 assert(col->rows[r]->name != NULL);
3428 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3429 }
3430 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3431}
3432
3433/** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3434 */
3436 SCIP_COL* col /**< column to be sorted */
3437 )
3438{
3439 /* sort LP rows */
3440 colSortLP(col);
3441
3442 /* sort non-LP rows */
3443 colSortNonLP(col);
3444}
3445
3446/** adds a previously non existing coefficient to an LP column */
3448 SCIP_COL* col, /**< LP column */
3449 BMS_BLKMEM* blkmem, /**< block memory */
3450 SCIP_SET* set, /**< global SCIP settings */
3451 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3452 SCIP_LP* lp, /**< current LP data */
3453 SCIP_ROW* row, /**< LP row */
3454 SCIP_Real val /**< value of coefficient */
3455 )
3456{
3457 assert(lp != NULL);
3458 assert(!lp->diving);
3459
3460 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3461
3462 checkLinks(lp);
3463
3464 return SCIP_OKAY;
3465}
3466
3467/** deletes existing coefficient from column */
3469 SCIP_COL* col, /**< column to be changed */
3470 BMS_BLKMEM* blkmem, /**< block memory */
3471 SCIP_SET* set, /**< global SCIP settings */
3472 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3473 SCIP_LP* lp, /**< current LP data */
3474 SCIP_ROW* row /**< coefficient to be deleted */
3475 )
3476{
3477 int pos;
3478
3479 assert(col != NULL);
3480 assert(col->var != NULL);
3481 assert(lp != NULL);
3482 assert(!lp->diving);
3483 assert(row != NULL);
3484
3485 /* search the position of the row in the column's row vector */
3486 pos = colSearchCoef(col, row);
3487 if( pos == -1 )
3488 {
3489 SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3490 return SCIP_INVALIDDATA;
3491 }
3492 assert(0 <= pos && pos < col->len);
3493 assert(col->rows[pos] == row);
3494
3495 /* if row knows of the column, remove the column from the row's col vector */
3496 if( col->linkpos[pos] >= 0 )
3497 {
3498 assert(row->cols[col->linkpos[pos]] == col);
3499 assert(row->cols_index[col->linkpos[pos]] == col->index);
3500 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3501 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3502 }
3503
3504 /* delete the row from the column's row vector */
3505 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3506
3507 checkLinks(lp);
3508
3509 return SCIP_OKAY;
3510}
3511
3512/** changes or adds a coefficient to an LP column */
3514 SCIP_COL* col, /**< LP column */
3515 BMS_BLKMEM* blkmem, /**< block memory */
3516 SCIP_SET* set, /**< global SCIP settings */
3517 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3518 SCIP_LP* lp, /**< current LP data */
3519 SCIP_ROW* row, /**< LP row */
3520 SCIP_Real val /**< value of coefficient */
3521 )
3522{
3523 int pos;
3524
3525 assert(col != NULL);
3526 assert(lp != NULL);
3527 assert(!lp->diving);
3528 assert(row != NULL);
3529
3530 /* search the position of the row in the column's row vector */
3531 pos = colSearchCoef(col, row);
3532
3533 /* check, if row already exists in the column's row vector */
3534 if( pos == -1 )
3535 {
3536 /* add previously not existing coefficient */
3537 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3538 }
3539 else
3540 {
3541 /* modify already existing coefficient */
3542 assert(0 <= pos && pos < col->len);
3543 assert(col->rows[pos] == row);
3544
3545 /* if row knows of the column, change the corresponding coefficient in the row */
3546 if( col->linkpos[pos] >= 0 )
3547 {
3548 assert(row->cols[col->linkpos[pos]] == col);
3549 assert(row->cols_index[col->linkpos[pos]] == col->index);
3550 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3551 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3552 }
3553
3554 /* change the coefficient in the column */
3555 SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3556 }
3557
3558 checkLinks(lp);
3559
3560 return SCIP_OKAY;
3561}
3562
3563/** increases value of an existing or non-existing coefficient in an LP column */
3565 SCIP_COL* col, /**< LP column */
3566 BMS_BLKMEM* blkmem, /**< block memory */
3567 SCIP_SET* set, /**< global SCIP settings */
3568 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3569 SCIP_LP* lp, /**< current LP data */
3570 SCIP_ROW* row, /**< LP row */
3571 SCIP_Real incval /**< value to add to the coefficient */
3572 )
3573{
3574 int pos;
3575
3576 assert(col != NULL);
3577 assert(lp != NULL);
3578 assert(!lp->diving);
3579 assert(row != NULL);
3580
3581 if( SCIPsetIsZero(set, incval) )
3582 return SCIP_OKAY;
3583
3584 /* search the position of the row in the column's row vector */
3585 pos = colSearchCoef(col, row);
3586
3587 /* check, if row already exists in the column's row vector */
3588 if( pos == -1 )
3589 {
3590 /* add previously not existing coefficient */
3591 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3592 }
3593 else
3594 {
3595 /* modify already existing coefficient */
3596 assert(0 <= pos && pos < col->len);
3597 assert(col->rows[pos] == row);
3598
3599 /* if row knows of the column, change the corresponding coefficient in the row */
3600 if( col->linkpos[pos] >= 0 )
3601 {
3602 assert(row->cols[col->linkpos[pos]] == col);
3603 assert(row->cols_index[col->linkpos[pos]] == col->index);
3604 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3605 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3606 }
3607
3608 /* change the coefficient in the column */
3609 SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3610 }
3611
3612 checkLinks(lp);
3613
3614 return SCIP_OKAY;
3615}
3616
3617/** insert column in the chgcols list (if not already there) */
3618static
3620 SCIP_COL* col, /**< LP column to change */
3621 SCIP_SET* set, /**< global SCIP settings */
3622 SCIP_LP* lp /**< current LP data */
3623 )
3624{
3625 if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3626 {
3627 SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3628 lp->chgcols[lp->nchgcols] = col;
3629 lp->nchgcols++;
3630 }
3631
3632 /* mark the current LP unflushed */
3633 lp->flushed = FALSE;
3634
3635 return SCIP_OKAY;
3636}
3637
3638/** Is the new value reliable or may we have cancellation?
3639 *
3640 * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3641 * cancellations which can occur during increasing the oldvalue to the newvalue
3642 */
3643static
3645 SCIP_SET* set, /**< global SCIP settings */
3646 SCIP_Real newvalue, /**< new value */
3647 SCIP_Real oldvalue /**< old reliable value */
3648 )
3649{
3650 SCIP_Real quotient;
3651
3652 assert(set != NULL);
3653 assert(oldvalue != SCIP_INVALID); /*lint !e777*/
3654
3655 quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3656
3657 return SCIPsetIsZero(set, quotient);
3658}
3659
3660/** update norms of objective function vector */
3661static
3663 SCIP_LP* lp, /**< current LP data */
3664 SCIP_SET* set, /**< global SCIP settings */
3665 SCIP_Real oldobj, /**< old objective value of variable */
3666 SCIP_Real newobj /**< new objective value of variable */
3667 )
3668{
3669 if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
3670 {
3671 if( !lp->objsqrnormunreliable )
3672 {
3673 SCIP_Real oldvalue;
3674
3675 oldvalue = lp->objsqrnorm;
3676 lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3677
3678 /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3679 if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3681 else
3682 {
3683 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3684
3685 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3686 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3687
3688 assert(lp->objsqrnorm >= 0.0);
3689 }
3690 }
3691
3692 lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3693 lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3694 }
3695}
3696
3697/** changes objective value of column */
3699 SCIP_COL* col, /**< LP column to change */
3700 SCIP_SET* set, /**< global SCIP settings */
3701 SCIP_LP* lp, /**< current LP data */
3702 SCIP_Real newobj /**< new objective value */
3703 )
3704{
3705 assert(col != NULL);
3706 assert(col->var != NULL);
3708 assert(SCIPvarGetCol(col->var) == col);
3709 assert(lp != NULL);
3710
3711 SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3712
3713 /* only add actual changes */
3714 if( !SCIPsetIsEQ(set, col->obj, newobj) )
3715 {
3716 /* only variables with a real position in the LPI can be inserted */
3717 if( col->lpipos >= 0 )
3718 {
3719 /* insert column in the chgcols list (if not already there) */
3720 SCIP_CALL( insertColChgcols(col, set, lp) );
3721
3722 /* mark objective value change in the column */
3723 col->objchanged = TRUE;
3724
3725 assert(lp->nchgcols > 0);
3726 }
3727 /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3728 * LP and the LP has to be flushed
3729 */
3730 else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3731 || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3732 {
3733 /* mark the LP unflushed */
3734 lp->flushed = FALSE;
3735 }
3736 }
3737
3738 /* store new objective function value */
3739 col->obj = newobj;
3740
3741 /* update original objective value, as long as we are not in diving or probing and changed objective values */
3742 if( !lp->divingobjchg )
3743 {
3744 SCIP_Real oldobj = col->unchangedobj;
3745
3746 assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3747 col->unchangedobj = newobj;
3748
3749 /* update the objective function vector norms */
3750 lpUpdateObjNorms(lp, set, oldobj, newobj);
3751 }
3752
3753 return SCIP_OKAY;
3754}
3755
3756/** changes lower bound of column */
3758 SCIP_COL* col, /**< LP column to change */
3759 SCIP_SET* set, /**< global SCIP settings */
3760 SCIP_LP* lp, /**< current LP data */
3761 SCIP_Real newlb /**< new lower bound value */
3762 )
3763{
3764 assert(col != NULL);
3765 assert(col->var != NULL);
3767 assert(SCIPvarGetCol(col->var) == col);
3768 assert(lp != NULL);
3769
3770 SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3771
3772 /* only add actual changes */
3773 if( !SCIPsetIsEQ(set, col->lb, newlb) )
3774 {
3775 /* only variables with a real position in the LPI can be inserted */
3776 if( col->lpipos >= 0 )
3777 {
3778 /* insert column in the chgcols list (if not already there) */
3779 SCIP_CALL( insertColChgcols(col, set, lp) );
3780
3781 /* mark bound change in the column */
3782 col->lbchanged = TRUE;
3783
3784 assert(lp->nchgcols > 0);
3785 }
3786 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3787 * flushed
3788 */
3789 else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3790 {
3791 /* mark the LP unflushed */
3792 lp->flushed = FALSE;
3793 }
3794 }
3795
3796 col->lb = newlb;
3797
3798 return SCIP_OKAY;
3799}
3800
3801/** changes upper bound of column */
3803 SCIP_COL* col, /**< LP column to change */
3804 SCIP_SET* set, /**< global SCIP settings */
3805 SCIP_LP* lp, /**< current LP data */
3806 SCIP_Real newub /**< new upper bound value */
3807 )
3808{
3809 assert(col != NULL);
3810 assert(col->var != NULL);
3812 assert(SCIPvarGetCol(col->var) == col);
3813 assert(lp != NULL);
3814
3815 SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3816
3817 /* only add actual changes */
3818 if( !SCIPsetIsEQ(set, col->ub, newub) )
3819 {
3820 /* only variables with a real position in the LPI can be inserted */
3821 if( col->lpipos >= 0 )
3822 {
3823 /* insert column in the chgcols list (if not already there) */
3824 SCIP_CALL( insertColChgcols(col, set, lp) );
3825
3826 /* mark bound change in the column */
3827 col->ubchanged = TRUE;
3828
3829 assert(lp->nchgcols > 0);
3830 }
3831 /* in any case, when the best bound is zero and gets changed, the variable has to enter the LP and the LP has to be
3832 * flushed
3833 */
3834 else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3835 {
3836 /* mark the LP unflushed */
3837 lp->flushed = FALSE;
3838 }
3839 }
3840
3841 col->ub = newub;
3842
3843 return SCIP_OKAY;
3844}
3845
3846/** calculates the reduced costs of a column using the given dual solution vector */
3848 SCIP_COL* col, /**< LP column */
3849 SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3850 )
3851{
3852 SCIP_ROW* row;
3853 SCIP_Real redcost;
3854 int i;
3855
3856 assert(col != NULL);
3858 assert(SCIPvarGetCol(col->var) == col);
3859 assert(dualsol != NULL);
3860
3861 redcost = col->obj;
3862 for( i = 0; i < col->nlprows; ++i )
3863 {
3864 row = col->rows[i];
3865 assert(row != NULL);
3866 assert(row->lppos >= 0);
3867 redcost -= col->vals[i] * dualsol[row->lppos];
3868 }
3869
3870 if( col->nunlinked > 0 )
3871 {
3872 for( i = col->nlprows; i < col->len; ++i )
3873 {
3874 row = col->rows[i];
3875 assert(row != NULL);
3876 assert(row->lppos == -1 || col->linkpos[i] == -1);
3877 if( row->lppos >= 0 )
3878 redcost -= col->vals[i] * dualsol[row->lppos];
3879 }
3880 }
3881#ifndef NDEBUG
3882 else
3883 {
3884 for( i = col->nlprows; i < col->len; ++i )
3885 {
3886 row = col->rows[i];
3887 assert(row != NULL);
3888 assert(row->lppos == -1);
3889 assert(col->linkpos[i] >= 0);
3890 }
3891 }
3892#endif
3893
3894 return redcost;
3895}
3896
3897/** calculates the reduced costs of a column using the dual solution stored in the rows */
3898static
3900 SCIP_COL* col /**< LP column */
3901 )
3902{
3903 SCIP_ROW* row;
3904 SCIP_Real redcost;
3905 int i;
3906
3907 assert(col != NULL);
3909 assert(SCIPvarGetCol(col->var) == col);
3910
3911 redcost = col->obj;
3912 for( i = 0; i < col->nlprows; ++i )
3913 {
3914 row = col->rows[i];
3915 assert(row != NULL);
3916 assert(row->dualsol != SCIP_INVALID); /*lint !e777*/
3917 assert(row->lppos >= 0);
3918 assert(col->linkpos[i] >= 0);
3919 redcost -= col->vals[i] * row->dualsol;
3920 }
3921
3922 if( col->nunlinked > 0 )
3923 {
3924 for( i = col->nlprows; i < col->len; ++i )
3925 {
3926 row = col->rows[i];
3927 assert(row != NULL);
3928 assert(row->lppos >= 0 || row->dualsol == 0.0);
3929 assert(row->lppos == -1 || col->linkpos[i] == -1);
3930 if( row->lppos >= 0 )
3931 redcost -= col->vals[i] * row->dualsol;
3932 }
3933 }
3934#ifndef NDEBUG
3935 else
3936 {
3937 for( i = col->nlprows; i < col->len; ++i )
3938 {
3939 row = col->rows[i];
3940 assert(row != NULL);
3941 assert(row->dualsol == 0.0);
3942 assert(row->lppos == -1);
3943 assert(col->linkpos[i] >= 0);
3944 }
3945 }
3946#endif
3947
3948 return redcost;
3949}
3950
3951/** gets the reduced costs of a column in last LP or after recalculation */
3953 SCIP_COL* col, /**< LP column */
3954 SCIP_STAT* stat, /**< problem statistics */
3955 SCIP_LP* lp /**< current LP data */
3956 )
3957{
3958 assert(col != NULL);
3959 assert(stat != NULL);
3960 assert(lp != NULL);
3961 assert(col->validredcostlp <= stat->lpcount);
3962 assert(lp->validsollp == stat->lpcount);
3963
3964 if( col->validredcostlp < stat->lpcount )
3965 {
3966 col->redcost = colCalcInternalRedcost(col);
3967 col->validredcostlp = stat->lpcount;
3968 }
3969 assert(col->validredcostlp == stat->lpcount);
3970 assert(col->redcost != SCIP_INVALID); /*lint !e777*/
3971
3972 return col->redcost;
3973}
3974
3975/** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3977 SCIP_COL* col, /**< LP column */
3978 SCIP_SET* set, /**< global SCIP settings */
3979 SCIP_STAT* stat, /**< problem statistics */
3980 SCIP_LP* lp /**< current LP data */
3981 )
3982{
3983 assert(col != NULL);
3984 assert(set != NULL);
3985 assert(stat != NULL);
3986 assert(lp != NULL);
3987 assert(lp->validsollp == stat->lpcount);
3988
3989 /* A column's reduced cost is defined as
3990 * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3991 * The activity is equal to the activity of the corresponding row in the dual LP.
3992 * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3993 * The sides of the dual row depend on the bounds of the column:
3994 * - lb == ub : dual row is a free row with infinite sides
3995 * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3996 * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3997 * - lb < ub <= 0: obj <= activity => redcost <= 0
3998 */
3999 if( SCIPsetIsEQ(set, col->lb, col->ub) )
4000 {
4001 /* dual row is free */
4002 return SCIPsetInfinity(set);
4003 }
4004 else
4005 {
4006 SCIP_Real redcost;
4007
4008 /* calculate reduced costs */
4009 redcost = SCIPcolGetRedcost(col, stat, lp);
4010
4011 if( !SCIPsetIsNegative(set, col->lb) )
4012 {
4013 /* dual row is activity <= obj <=> redcost >= 0 */
4014 return redcost;
4015 }
4016 else if( SCIPsetIsPositive(set, col->ub) )
4017 {
4018 /* dual row is activity == obj <=> redcost == 0 */
4019 return -REALABS(redcost);
4020 }
4021 else
4022 {
4023 /* dual row is activity >= obj <=> redcost <= 0 */
4024 return -redcost;
4025 }
4026 }
4027}
4028
4029/** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
4031 SCIP_COL* col, /**< LP column */
4032 SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
4033 )
4034{
4035 SCIP_ROW* row;
4036 SCIP_Real farkas;
4037 int i;
4038
4039 assert(col != NULL);
4041 assert(SCIPvarGetCol(col->var) == col);
4042 assert(dualfarkas != NULL);
4043
4044 farkas = 0.0;
4045 for( i = 0; i < col->nlprows; ++i )
4046 {
4047 row = col->rows[i];
4048 assert(row != NULL);
4049 assert(row->lppos >= 0);
4050 farkas += col->vals[i] * dualfarkas[row->lppos];
4051 }
4052
4053 if( col->nunlinked > 0 )
4054 {
4055 for( i = col->nlprows; i < col->len; ++i )
4056 {
4057 row = col->rows[i];
4058 assert(row != NULL);
4059 assert(row->lppos == -1 || col->linkpos[i] == -1);
4060 if( row->lppos >= 0 )
4061 farkas += col->vals[i] * dualfarkas[row->lppos];
4062 }
4063 }
4064#ifndef NDEBUG
4065 else
4066 {
4067 for( i = col->nlprows; i < col->len; ++i )
4068 {
4069 row = col->rows[i];
4070 assert(row != NULL);
4071 assert(row->lppos == -1);
4072 assert(col->linkpos[i] >= 0);
4073 }
4074 }
4075#endif
4076
4077 return farkas;
4078}
4079
4080/** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
4081static
4083 SCIP_COL* col /**< LP column */
4084 )
4085{
4086 SCIP_ROW* row;
4087 SCIP_Real farkas;
4088 int i;
4089
4090 assert(col != NULL);
4092 assert(SCIPvarGetCol(col->var) == col);
4093
4094 farkas = 0.0;
4095 for( i = 0; i < col->nlprows; ++i )
4096 {
4097 row = col->rows[i];
4098 assert(row != NULL);
4099 assert(row->dualfarkas != SCIP_INVALID); /*lint !e777*/
4100 assert(row->lppos >= 0);
4101 assert(col->linkpos[i] >= 0);
4102 farkas += col->vals[i] * row->dualfarkas;
4103 }
4104
4105 if( col->nunlinked > 0 )
4106 {
4107 for( i = col->nlprows; i < col->len; ++i )
4108 {
4109 row = col->rows[i];
4110 assert(row != NULL);
4111 assert(row->lppos >= 0 || row->dualfarkas == 0.0);
4112 assert(row->lppos == -1 || col->linkpos[i] == -1);
4113 if( row->lppos >= 0 )
4114 farkas += col->vals[i] * row->dualfarkas;
4115 }
4116 }
4117#ifndef NDEBUG
4118 else
4119 {
4120 for( i = col->nlprows; i < col->len; ++i )
4121 {
4122 row = col->rows[i];
4123 assert(row != NULL);
4124 assert(row->dualfarkas == 0.0);
4125 assert(row->lppos == -1);
4126 assert(col->linkpos[i] >= 0);
4127 }
4128 }
4129#endif
4130
4131 return farkas;
4132}
4133
4134/** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
4136 SCIP_COL* col, /**< LP column */
4137 SCIP_STAT* stat, /**< problem statistics */
4138 SCIP_LP* lp /**< current LP data */
4139 )
4140{
4141 assert(col != NULL);
4142 assert(stat != NULL);
4143 assert(lp != NULL);
4144 assert(col->validfarkaslp <= stat->lpcount);
4145 assert(lp->validfarkaslp == stat->lpcount);
4146
4147 if( col->validfarkaslp < stat->lpcount )
4148 {
4150 col->validfarkaslp = stat->lpcount;
4151 }
4152 assert(col->validfarkaslp == stat->lpcount);
4153 assert(col->farkascoef != SCIP_INVALID); /*lint !e777*/
4154
4155 return col->farkascoef;
4156}
4157
4158/** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
4159 * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
4160 */
4162 SCIP_COL* col, /**< LP column */
4163 SCIP_STAT* stat, /**< problem statistics */
4164 SCIP_LP* lp /**< current LP data */
4165 )
4166{
4167 SCIP_Real farkascoef;
4168
4169 assert(col != NULL);
4170
4171 farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
4172
4173 if( farkascoef > 0.0 )
4174 return col->ub * farkascoef;
4175 else
4176 return col->lb * farkascoef;
4177}
4178
4179/** start strong branching - call before any strong branching */
4181 SCIP_LP* lp /**< LP data */
4182 )
4183{
4184 assert(lp != NULL);
4185 assert(!lp->strongbranching);
4186
4187 lp->strongbranching = TRUE;
4188 SCIPdebugMessage("starting strong branching ...\n");
4190
4191 return SCIP_OKAY;
4192}
4193
4194/** end strong branching - call after any strong branching */
4196 SCIP_LP* lp /**< LP data */
4197 )
4198{
4199 assert(lp != NULL);
4200 assert(lp->strongbranching);
4201
4202 lp->strongbranching = FALSE;
4203 SCIPdebugMessage("ending strong branching ...\n");
4205
4206 return SCIP_OKAY;
4207}
4208
4209/** sets strong branching information for a column variable */
4211 SCIP_COL* col, /**< LP column */
4212 SCIP_SET* set, /**< global SCIP settings */
4213 SCIP_STAT* stat, /**< dynamic problem statistics */
4214 SCIP_LP* lp, /**< LP data */
4215 SCIP_Real lpobjval, /**< objective value of the current LP */
4216 SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4217 SCIP_Real sbdown, /**< dual bound after branching column down */
4218 SCIP_Real sbup, /**< dual bound after branching column up */
4219 SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
4220 SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
4221 SCIP_Longint iter, /**< total number of strong branching iterations */
4222 int itlim /**< iteration limit applied to the strong branching call */
4223 )
4224{
4225 assert(col != NULL);
4226 assert(col->var != NULL);
4227 assert(SCIPcolIsIntegral(col));
4228 assert(SCIPvarIsIntegral(col->var));
4230 assert(SCIPvarGetCol(col->var) == col);
4231 assert(col->lpipos >= 0);
4232 assert(col->lppos >= 0);
4233 assert(set != NULL);
4234 assert(stat != NULL);
4235 assert(lp != NULL);
4236 assert(lp->strongbranchprobing);
4237 assert(col->lppos < lp->ncols);
4238 assert(lp->cols[col->lppos] == col);
4239 assert(itlim >= 1);
4240
4241 col->sblpobjval = lpobjval;
4242 col->sbsolval = primsol;
4243 col->validsblp = stat->nlps;
4244 col->sbnode = stat->nnodes;
4245
4246 col->sbitlim = itlim;
4247 col->nsbcalls++;
4248
4249 col->sbdown = MIN(sbdown, lp->cutoffbound);
4250 col->sbup = MIN(sbup, lp->cutoffbound);
4251 col->sbdownvalid = sbdownvalid;
4252 col->sbupvalid = sbupvalid;
4253
4254 SCIPstatIncrement(stat, set, nstrongbranchs);
4255 SCIPstatAdd(stat, set, nsblpiterations, iter);
4256 if( stat->nnodes == 1 )
4257 {
4258 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4259 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4260 }
4261}
4262
4263/** invalidates strong branching information for a column variable */
4265 SCIP_COL* col, /**< LP column */
4266 SCIP_SET* set, /**< global SCIP settings */
4267 SCIP_STAT* stat, /**< dynamic problem statistics */
4268 SCIP_LP* lp /**< LP data */
4269 )
4270{
4271 assert(col != NULL);
4272 assert(col->var != NULL);
4273 assert(SCIPcolIsIntegral(col));
4274 assert(SCIPvarIsIntegral(col->var));
4276 assert(SCIPvarGetCol(col->var) == col);
4277 assert(col->lpipos >= 0);
4278 assert(col->lppos >= 0);
4279 assert(set != NULL);
4280 assert(stat != NULL);
4281 assert(lp != NULL);
4282 assert(lp->strongbranchprobing);
4283 assert(col->lppos < lp->ncols);
4284 assert(lp->cols[col->lppos] == col);
4285
4286 col->sbdown = SCIP_INVALID;
4287 col->sbup = SCIP_INVALID;
4288 col->sbdownvalid = FALSE;
4289 col->sbupvalid = FALSE;
4290 col->validsblp = -1;
4291 col->sbsolval = SCIP_INVALID;
4292 col->sblpobjval = SCIP_INVALID;
4293 col->sbnode = -1;
4294 col->sbitlim = -1;
4295}
4296
4297
4298/** gets strong branching information on a column variable */
4300 SCIP_COL* col, /**< LP column */
4301 SCIP_Bool integral, /**< should integral strong branching be performed? */
4302 SCIP_SET* set, /**< global SCIP settings */
4303 SCIP_STAT* stat, /**< dynamic problem statistics */
4304 SCIP_PROB* prob, /**< problem data */
4305 SCIP_LP* lp, /**< LP data */
4306 int itlim, /**< iteration limit for strong branchings */
4307 SCIP_Bool updatecol, /**< should col be updated, or should it stay in its current state ? */
4308 SCIP_Bool updatestat, /**< should stat be updated, or should it stay in its current state ? */
4309 SCIP_Real* down, /**< stores dual bound after branching column down */
4310 SCIP_Real* up, /**< stores dual bound after branching column up */
4311 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4312 * otherwise, it can only be used as an estimate value */
4313 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4314 * otherwise, it can only be used as an estimate value */
4315 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4316 )
4317{
4318 SCIP_Real sbdown;
4319 SCIP_Real sbup;
4320 SCIP_Bool sbdownvalid;
4321 SCIP_Bool sbupvalid;
4322 SCIP_Longint validsblp;
4323 SCIP_Real sbsolval;
4324 SCIP_Real sblpobjval;
4325 SCIP_Longint sbnode;
4326 int sbitlim;
4327 int nsbcalls;
4328
4329 assert(col != NULL);
4330 assert(col->var != NULL);
4331 assert(SCIPcolIsIntegral(col));
4332 assert(SCIPvarIsIntegral(col->var));
4334 assert(SCIPvarGetCol(col->var) == col);
4335 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4336 assert(col->lpipos >= 0);
4337 assert(col->lppos >= 0);
4338 assert(set != NULL);
4339 assert(stat != NULL);
4340 assert(lp != NULL);
4341 assert(lp->flushed);
4342 assert(lp->solved);
4343 assert(lp->strongbranching);
4344 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4345 assert(lp->validsollp == stat->lpcount);
4346 assert(col->lppos < lp->ncols);
4347 assert(lp->cols[col->lppos] == col);
4348 assert(itlim >= 1);
4349 /* assert(down != NULL);
4350 * assert(up != NULL); temporary hack for cloud branching
4351 */
4352 assert(lperror != NULL);
4353
4354 *lperror = FALSE;
4355
4356 sbdown = col->sbdown;
4357 sbup = col->sbup;
4358 sbdownvalid = col->sbdownvalid;
4359 sbupvalid = col->sbupvalid;
4360 sbitlim = col->sbitlim;
4361 nsbcalls = col->nsbcalls;
4362
4363 validsblp = stat->nlps;
4364 sbsolval = col->primsol;
4365 sblpobjval = SCIPlpGetObjval(lp, set, prob);
4366 sbnode = stat->nnodes;
4367 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4368
4369 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4370 if( lp->looseobjvalinf > 0 )
4371 {
4372 sbdown = -SCIPsetInfinity(set);
4373 sbup = -SCIPsetInfinity(set);
4374 sbdownvalid = FALSE;
4375 sbupvalid = FALSE;
4376 }
4377 else
4378 {
4379 SCIP_RETCODE retcode;
4380 int iter;
4381
4382 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4383 SCIPvarGetName(col->var), col->primsol, itlim);
4384
4385 /* start timing */
4387
4388 /* call LPI strong branching */
4389 sbitlim = itlim;
4390 nsbcalls++;
4391
4392 sbdown = lp->lpobjval;
4393 sbup = lp->lpobjval;
4394
4395 if( integral )
4396 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4397 else
4398 {
4399 assert( ! SCIPsetIsIntegral(set, col->primsol) );
4400 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4401 }
4402
4403 /* check return code for errors */
4404 if( retcode == SCIP_LPERROR )
4405 {
4406 *lperror = TRUE;
4407 sbdown = SCIP_INVALID;
4408 sbup = SCIP_INVALID;
4409 sbdownvalid = FALSE;
4410 sbupvalid = FALSE;
4411 validsblp = -1;
4412 sbsolval = SCIP_INVALID;
4413 sblpobjval = SCIP_INVALID;
4414 sbnode = -1;
4415 }
4416 else
4417 {
4418 SCIP_Real looseobjval;
4419
4420 *lperror = FALSE;
4421 SCIP_CALL( retcode );
4422
4423 looseobjval = getFiniteLooseObjval(lp, set, prob);
4424 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4425 sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4426
4427 /* update strong branching statistics */
4428 if( updatestat )
4429 {
4430 if( iter == -1 )
4431 {
4432 /* calculate average iteration number */
4433 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4434 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4435 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4436 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4437 : 0;
4438 if( iter/2 >= itlim )
4439 iter = 2*itlim;
4440 }
4441 SCIPstatIncrement(stat, set, nstrongbranchs);
4442 SCIPstatAdd(stat, set, nsblpiterations, iter);
4443 if( stat->nnodes == 1 )
4444 {
4445 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4446 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4447 }
4448 }
4449 }
4450
4451 /* stop timing */
4453 }
4454 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/
4455 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/
4456
4457 if( down != NULL)
4458 *down = sbdown;
4459 if( up != NULL )
4460 *up = sbup;
4461 if( downvalid != NULL )
4462 *downvalid = sbdownvalid;
4463 if( upvalid != NULL )
4464 *upvalid = sbupvalid;
4465
4466 if( updatecol )
4467 {
4468 col->sbdown = sbdown;
4469 col->sbup = sbup;
4470 col->sbdownvalid = sbdownvalid;
4471 col->sbupvalid = sbupvalid;
4472 col->validsblp = validsblp;
4473 col->sbsolval = sbsolval;
4474 col->sblpobjval = sblpobjval;
4475 col->sbnode = sbnode;
4476 col->sbitlim = sbitlim;
4477 col->nsbcalls = nsbcalls;
4478 }
4479
4480 return SCIP_OKAY;
4481}
4482
4483/** gets strong branching information on column variables */
4485 SCIP_COL** cols, /**< LP columns */
4486 int ncols, /**< number of columns */
4487 SCIP_Bool integral, /**< should integral strong branching be performed? */
4488 SCIP_SET* set, /**< global SCIP settings */
4489 SCIP_STAT* stat, /**< dynamic problem statistics */
4490 SCIP_PROB* prob, /**< problem data */
4491 SCIP_LP* lp, /**< LP data */
4492 int itlim, /**< iteration limit for strong branchings */
4493 SCIP_Real* down, /**< stores dual bounds after branching columns down */
4494 SCIP_Real* up, /**< stores dual bounds after branching columns up */
4495 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4496 * otherwise, they can only be used as an estimate value */
4497 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4498 * otherwise, they can only be used as an estimate value */
4499 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4500 )
4501{
4502 SCIP_RETCODE retcode;
4503 SCIP_Real* sbdown;
4504 SCIP_Real* sbup;
4505 SCIP_Bool* sbdownvalid;
4506 SCIP_Bool* sbupvalid;
4507 SCIP_Real* primsols;
4508 SCIP_COL** subcols;
4509 int* lpipos;
4510 int* subidx;
4511 int nsubcols;
4512 int iter;
4513 int j;
4514
4515 assert(cols != NULL);
4516 assert(set != NULL);
4517 assert(stat != NULL);
4518 assert(lp != NULL);
4519 assert(lp->flushed);
4520 assert(lp->solved);
4521 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4522 assert(lp->validsollp == stat->lpcount);
4523 assert(itlim >= 1);
4524 assert(down != NULL);
4525 assert(up != NULL);
4526 assert(lperror != NULL);
4527
4528 *lperror = FALSE;
4529
4530 if ( ncols <= 0 )
4531 return SCIP_OKAY;
4532
4533 /* start timing */
4535
4536 /* initialize storage */
4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4541 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4542 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4543 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4544 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4545
4546 nsubcols = 0;
4547 for( j = 0; j < ncols; ++j )
4548 {
4549 SCIP_COL* col;
4550 col = cols[j];
4551
4552 assert(col->lppos < lp->ncols);
4553 assert(lp->cols[col->lppos] == col);
4554 assert(SCIPcolIsIntegral(col));
4555 assert(SCIPvarIsIntegral(col->var));
4557 assert(SCIPvarGetCol(col->var) == col);
4558 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4559 assert(col->lpipos >= 0);
4560 assert(col->lppos >= 0);
4561
4562 col->validsblp = stat->nlps;
4563 col->sbsolval = col->primsol;
4564 col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4565 col->sbnode = stat->nnodes;
4566 assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4567
4568 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4569 if( lp->looseobjvalinf > 0 )
4570 {
4571 /* directly set up column and result vectors*/
4572 col->sbdown = -SCIPsetInfinity(set);
4573 col->sbup = -SCIPsetInfinity(set);
4574 col->sbdownvalid = FALSE;
4575 col->sbupvalid = FALSE;
4576 down[j] = col->sbdown;
4577 up[j] = col->sbup;
4578 if( downvalid != NULL )
4579 downvalid[j] = col->sbdownvalid;
4580 if( upvalid != NULL )
4581 upvalid[j] = col->sbupvalid;
4582 }
4583 else
4584 {
4585 col->sbitlim = itlim;
4586 col->nsbcalls++;
4587
4588 lpipos[nsubcols] = col->lpipos;
4589 primsols[nsubcols] = col->primsol;
4590 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4591 subidx[nsubcols] = j;
4592 subcols[nsubcols++] = col;
4593 }
4594 }
4595
4596 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4597
4598 /* call LPI strong branching */
4599 if ( integral )
4600 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4601 else
4602 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4603
4604 /* check return code for errors */
4605 if( retcode == SCIP_LPERROR )
4606 {
4607 *lperror = TRUE;
4608
4609 for( j = 0; j < nsubcols; ++j )
4610 {
4611 SCIP_COL* col;
4612 int idx;
4613
4614 col = subcols[j];
4615 idx = subidx[j];
4616
4617 col->sbdown = SCIP_INVALID;
4618 col->sbup = SCIP_INVALID;
4619 col->sbdownvalid = FALSE;
4620 col->sbupvalid = FALSE;
4621 col->validsblp = -1;
4622 col->sbsolval = SCIP_INVALID;
4623 col->sblpobjval = SCIP_INVALID;
4624 col->sbnode = -1;
4625
4626 down[idx] = col->sbdown;
4627 up[idx] = col->sbup;
4628 if( downvalid != NULL )
4629 downvalid[idx] = col->sbdownvalid;
4630 if( upvalid != NULL )
4631 upvalid[idx] = col->sbupvalid;
4632 }
4633 }
4634 else
4635 {
4636 SCIP_Real looseobjval;
4637
4638 *lperror = FALSE;
4639 SCIP_CALL( retcode );
4640
4641 looseobjval = getFiniteLooseObjval(lp, set, prob);
4642
4643 for( j = 0; j < nsubcols; ++j )
4644 {
4645 SCIP_COL* col;
4646 int idx;
4647
4648 col = subcols[j];
4649 idx = subidx[j];
4650
4651 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/
4652 assert( col->sbup != SCIP_INVALID); /*lint !e777*/
4653
4654 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4655 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4656 col->sbdownvalid = sbdownvalid[j];
4657 col->sbupvalid = sbupvalid[j];
4658
4659 down[idx] = col->sbdown;
4660 up[idx] = col->sbup;
4661 if( downvalid != NULL )
4662 downvalid[idx] = col->sbdownvalid;
4663 if( upvalid != NULL )
4664 upvalid[idx] = col->sbupvalid;
4665 }
4666
4667 /* update strong branching statistics */
4668 if( iter == -1 )
4669 {
4670 /* calculate average iteration number */
4671 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4672 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4673 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4674 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4675 : 0;
4676 if( iter/2 >= itlim )
4677 iter = 2*itlim;
4678 }
4679 SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4680 SCIPstatAdd(stat, set, nsblpiterations, iter);
4681 if( stat->nnodes == 1 )
4682 {
4683 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4684 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4685 }
4686 }
4687
4688 SCIPsetFreeBufferArray(set, &sbupvalid);
4689 SCIPsetFreeBufferArray(set, &sbdownvalid);
4691 SCIPsetFreeBufferArray(set, &sbdown);
4692 SCIPsetFreeBufferArray(set, &primsols);
4693 SCIPsetFreeBufferArray(set, &lpipos);
4694 SCIPsetFreeBufferArray(set, &subidx);
4695 SCIPsetFreeBufferArray(set, &subcols);
4696
4697 /* stop timing */
4699
4700 return SCIP_OKAY;
4701}
4702
4703/** gets last strong branching information available for a column variable;
4704 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4705 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4706 */
4708 SCIP_COL* col, /**< LP column */
4709 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4710 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4711 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4712 * otherwise, it can only be used as an estimate value */
4713 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4714 * otherwise, it can only be used as an estimate value */
4715 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4716 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4717 )
4718{
4719 assert(col != NULL);
4720
4721 if( down != NULL )
4722 *down = col->sbdown;
4723 if( up != NULL )
4724 *up = col->sbup;
4725 if( downvalid != NULL )
4726 *downvalid = col->sbdownvalid;
4727 if( upvalid != NULL )
4728 *upvalid = col->sbupvalid;
4729 if( solval != NULL )
4730 *solval = col->sbsolval;
4731 if( lpobjval != NULL )
4732 *lpobjval = col->sblpobjval;
4733}
4734
4735/** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4736 * the LP where the strong branching on this column was applied;
4737 * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4738 */
4740 SCIP_COL* col, /**< LP column */
4741 SCIP_STAT* stat /**< dynamic problem statistics */
4742 )
4743{
4744 assert(col != NULL);
4745 assert(stat != NULL);
4746
4747 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4748}
4749
4750/** marks a column to be not removable from the LP in the current node because it became obsolete */
4752 SCIP_COL* col, /**< LP column */
4753 SCIP_STAT* stat /**< problem statistics */
4754 )
4755{
4756 assert(col != NULL);
4757 assert(stat != NULL);
4758 assert(stat->nnodes > 0);
4759
4760 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4761 col->obsoletenode = stat->nnodes;
4762}
4763
4764
4765/*
4766 * Row methods
4767 */
4768
4769/** calculates row norms and min/maxidx from scratch, and checks for sorting */
4770static
4772 SCIP_ROW* row, /**< LP row */
4773 SCIP_SET* set /**< global SCIP settings */
4774 )
4775{
4776 int i;
4777
4778 assert(row != NULL);
4779 assert(set != NULL);
4780
4781 row->sqrnorm = 0.0;
4782 row->sumnorm = 0.0;
4783 row->objprod = 0.0;
4784 row->maxval = 0.0;
4785 row->nummaxval = 1;
4786 row->minval = SCIPsetInfinity(set);
4787 row->numminval = 1;
4788 row->minidx = INT_MAX;
4789 row->maxidx = INT_MIN;
4790 row->validminmaxidx = TRUE;
4791 row->lpcolssorted = TRUE;
4792 row->nonlpcolssorted = TRUE;
4793
4794 /* check, if row is sorted
4795 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4796 */
4797 for( i = 0; i < row->nlpcols; ++i )
4798 {
4799 assert(row->cols[i] != NULL);
4800 assert(!SCIPsetIsZero(set, row->vals[i]));
4801 assert(row->cols[i]->lppos >= 0);
4802 assert(row->linkpos[i] >= 0);
4803 assert(row->cols[i]->index == row->cols_index[i]);
4804
4805 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4806 if( i > 0 )
4807 {
4808 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4809 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4810 }
4811 }
4812 for( i = row->nlpcols; i < row->len; ++i )
4813 {
4814 assert(row->cols[i] != NULL);
4815 assert(!SCIPsetIsZero(set, row->vals[i]));
4816 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4817 assert(row->cols[i]->index == row->cols_index[i]);
4818
4819 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4820 if( i > row->nlpcols )
4821 {
4822 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4823 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4824 }
4825 }
4826}
4827
4828/** calculates min/maxval and min/maxidx from scratch */
4829static
4831 SCIP_ROW* row, /**< LP row */
4832 SCIP_SET* set /**< global SCIP settings */
4833 )
4834{
4835 SCIP_COL* col;
4836 SCIP_Real absval;
4837 int i;
4838
4839 assert(row != NULL);
4840 assert(set != NULL);
4841
4842 row->maxval = 0.0;
4843 row->nummaxval = 1;
4844 row->numintcols = 0;
4845 row->minval = SCIPsetInfinity(set);
4846 row->numminval = 1;
4847 row->minidx = INT_MAX;
4848 row->maxidx = INT_MIN;
4849 row->validminmaxidx = TRUE;
4850
4851 /* calculate maxval, minval, minidx, and maxidx */
4852 for( i = 0; i < row->len; ++i )
4853 {
4854 col = row->cols[i];
4855 assert(col != NULL);
4856 assert(!SCIPsetIsZero(set, row->vals[i]));
4857
4858 absval = REALABS(row->vals[i]);
4859 assert(!SCIPsetIsZero(set, absval));
4860
4861 /* update min/maxidx */
4862 row->minidx = MIN(row->minidx, col->index);
4863 row->maxidx = MAX(row->maxidx, col->index);
4864 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4865
4866 /* update maximal and minimal non-zero value */
4867 if( row->nummaxval > 0 )
4868 {
4869 if( SCIPsetIsGT(set, absval, row->maxval) )
4870 {
4871 row->maxval = absval;
4872 row->nummaxval = 1;
4873 }
4874 else if( SCIPsetIsGE(set, absval, row->maxval) )
4875 {
4876 /* make sure the maxval is always exactly the same */
4877 row->maxval = MAX(absval, row->maxval);
4878 row->nummaxval++;
4879 }
4880 }
4881 if( row->numminval > 0 )
4882 {
4883 if( SCIPsetIsLT(set, absval, row->minval) )
4884 {
4885 row->minval = absval;
4886 row->numminval = 1;
4887 }
4888 else if( SCIPsetIsLE(set, absval, row->minval) )
4889 {
4890 /* make sure the minval is always exactly the same */
4891 row->minval = MIN(absval, row->minval);
4892 row->numminval++;
4893 }
4894 }
4895 }
4896}
4897
4898/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4899static
4901 SCIP_Real val, /**< value that should be scaled to an integral value */
4902 SCIP_Real scalar, /**< scalar that should be tried */
4903 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4904 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4905 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4906 )
4907{
4908 SCIP_Real sval;
4909 SCIP_Real downval;
4910 SCIP_Real upval;
4911
4912 assert(mindelta <= 0.0);
4913 assert(maxdelta >= 0.0);
4914
4915 sval = val * scalar;
4916 downval = floor(sval);
4917 upval = ceil(sval);
4918
4919 if( SCIPrelDiff(sval, downval) <= maxdelta )
4920 {
4921 if( intval != NULL )
4922 *intval = downval;
4923 return TRUE;
4924 }
4925 else if( SCIPrelDiff(sval, upval) >= mindelta )
4926 {
4927 if( intval != NULL )
4928 *intval = upval;
4929 return TRUE;
4930 }
4931
4932 return FALSE;
4933}
4934
4935/** scales row with given factor, and rounds coefficients to integers if close enough;
4936 * the constant is automatically moved to the sides;
4937 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4938 */
4939static
4941 SCIP_ROW* row, /**< LP row */
4942 BMS_BLKMEM* blkmem, /**< block memory */
4943 SCIP_SET* set, /**< global SCIP settings */
4944 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4945 SCIP_STAT* stat, /**< problem statistics */
4946 SCIP_LP* lp, /**< current LP data */
4947 SCIP_Real scaleval, /**< value to scale row with */
4948 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4949 * if they are close to integral values? */
4950 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4951 * upto which the integral is used instead of the scaled real coefficient */
4952 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4953 * upto which the integral is used instead of the scaled real coefficient */
4954 )
4955{
4956 SCIP_COL* col;
4957 SCIP_Real val;
4958 SCIP_Real newval;
4959 SCIP_Real intval;
4960 SCIP_Real mindelta;
4961 SCIP_Real maxdelta;
4962 SCIP_Real lb;
4963 SCIP_Real ub;
4964 SCIP_Bool mindeltainf;
4965 SCIP_Bool maxdeltainf;
4966 int oldlen;
4967 int c;
4968
4969 assert(row != NULL);
4970 assert(row->len == 0 || row->cols != NULL);
4971 assert(row->len == 0 || row->vals != NULL);
4972 assert(SCIPsetIsPositive(set, scaleval));
4973 assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4974 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4975
4976 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4977
4978 mindelta = 0.0;
4979 maxdelta = 0.0;
4980 mindeltainf = FALSE;
4981 maxdeltainf = FALSE;
4982 oldlen = row->len;
4983
4984 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4985 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4986 * this rounding can lead to
4987 */
4988 row->integral = TRUE;
4989
4990 c = 0;
4991 while( c < row->len )
4992 {
4993 col = row->cols[c];
4994 val = row->vals[c];
4995 assert(!SCIPsetIsZero(set, val));
4996
4997 /* get local or global bounds for column, depending on the local or global feasibility of the row */
4998 if( row->local )
4999 {
5000 lb = col->lb;
5001 ub = col->ub;
5002 }
5003 else
5004 {
5005 lb = SCIPvarGetLbGlobal(col->var);
5006 ub = SCIPvarGetUbGlobal(col->var);
5007 }
5008
5009 /* calculate scaled coefficient */
5010 newval = val * scaleval;
5011 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5012 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5013 {
5014 if( !SCIPsetIsEQ(set, intval, newval) )
5015 {
5016 if( intval < newval )
5017 {
5018 mindelta += (intval - newval)*ub;
5019 maxdelta += (intval - newval)*lb;
5020 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5021 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5022 }
5023 else
5024 {
5025 mindelta += (intval - newval)*lb;
5026 maxdelta += (intval - newval)*ub;
5027 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5028 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5029 }
5030 }
5031 newval = intval;
5032 }
5033
5034 if( !SCIPsetIsEQ(set, val, newval) )
5035 {
5036 /* if column knows of the row, change the corresponding coefficient in the column */
5037 if( row->linkpos[c] >= 0 )
5038 {
5039 assert(col->rows[row->linkpos[c]] == row);
5040 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5041 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5042 }
5043
5044 /* change the coefficient in the row, and update the norms and integrality status */
5045 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5046
5047 /* current coefficient has been deleted from the row because it was almost zero */
5048 if( oldlen != row->len )
5049 {
5050 assert(row->len == oldlen - 1);
5051 c--;
5052 oldlen = row->len;
5053 }
5054 }
5055 else
5056 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5057
5058 ++c;
5059 }
5060
5061 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5062 * to not destroy feasibility due to rounding
5063 */
5064 /**@todo ensure that returned cut does not have infinite lhs and rhs */
5065 if( !SCIPsetIsInfinity(set, -row->lhs) )
5066 {
5067 if( mindeltainf )
5068 newval = -SCIPsetInfinity(set);
5069 else
5070 {
5071 newval = (row->lhs - row->constant) * scaleval + mindelta;
5072 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5073 newval = SCIPsetSumCeil(set, newval);
5074 }
5075 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5076 }
5077 if( !SCIPsetIsInfinity(set, row->rhs) )
5078 {
5079 if( maxdeltainf )
5080 newval = SCIPsetInfinity(set);
5081 else
5082 {
5083 newval = (row->rhs - row->constant) * scaleval + maxdelta;
5084 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5085 newval = SCIPsetSumFloor(set, newval);
5086 }
5087 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5088 }
5089
5090 /* clear the row constant */
5091 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5092
5093 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5094 debugRowPrint(set, row);
5095
5096#ifdef SCIP_DEBUG
5097 /* check integrality status of row */
5098 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5099 {}
5100 assert(row->integral == (c == row->len));
5101#endif
5102
5103 /* invalid the activity */
5104 row->validactivitylp = -1;
5105
5106 return SCIP_OKAY;
5107}
5108
5109/** creates and captures an LP row */
5111 SCIP_ROW** row, /**< pointer to LP row data */
5112 BMS_BLKMEM* blkmem, /**< block memory */
5113 SCIP_SET* set, /**< global SCIP settings */
5114 SCIP_STAT* stat, /**< problem statistics */
5115 const char* name, /**< name of row */
5116 int len, /**< number of nonzeros in the row */
5117 SCIP_COL** cols, /**< array with columns of row entries */
5118 SCIP_Real* vals, /**< array with coefficients of row entries */
5119 SCIP_Real lhs, /**< left hand side of row */
5120 SCIP_Real rhs, /**< right hand side of row */
5121 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
5122 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5123 SCIP_Bool local, /**< is row only valid locally? */
5124 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
5125 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
5126 )
5127{
5128 assert(row != NULL);
5129 assert(blkmem != NULL);
5130 assert(stat != NULL);
5131 assert(len >= 0);
5132 assert(len == 0 || (cols != NULL && vals != NULL));
5133 /* note, that the assert tries to avoid numerical troubles in the LP solver.
5134 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5135 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5136 */
5137 assert(lhs <= rhs);
5138
5139 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5140
5141 (*row)->integral = TRUE;
5142 if( len > 0 )
5143 {
5144 SCIP_VAR* var;
5145 int i;
5146
5147 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5148 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5149 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5150 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5151
5152 for( i = 0; i < len; ++i )
5153 {
5154 assert(cols[i] != NULL);
5155 assert(!SCIPsetIsZero(set, vals[i]));
5156
5157 var = cols[i]->var;
5158 (*row)->cols_index[i] = cols[i]->index;
5159 (*row)->linkpos[i] = -1;
5160 if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5161 {
5162 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5163 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5164 }
5165 else
5166 {
5167 (*row)->integral = FALSE;
5168 }
5169 }
5170 }
5171 else
5172 {
5173 (*row)->cols = NULL;
5174 (*row)->cols_index = NULL;
5175 (*row)->vals = NULL;
5176 (*row)->linkpos = NULL;
5177 }
5178
5179 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5180 (*row)->constant = 0.0;
5181 (*row)->lhs = lhs;
5182 (*row)->rhs = rhs;
5183 (*row)->flushedlhs = -SCIPsetInfinity(set);
5184 (*row)->flushedrhs = SCIPsetInfinity(set);
5185 (*row)->sqrnorm = 0.0;
5186 (*row)->sumnorm = 0.0;
5187 (*row)->objprod = 0.0;
5188 (*row)->maxval = 0.0;
5189 (*row)->minval = SCIPsetInfinity(set);
5190 (*row)->dualsol = 0.0;
5191 (*row)->activity = SCIP_INVALID;
5192 (*row)->dualfarkas = 0.0;
5193 (*row)->pseudoactivity = SCIP_INVALID;
5194 (*row)->minactivity = SCIP_INVALID;
5195 (*row)->maxactivity = SCIP_INVALID;
5196 (*row)->origin = origin;
5197 (*row)->eventfilter = NULL;
5198 (*row)->index = stat->nrowidx;
5199 SCIPstatIncrement(stat, set, nrowidx);
5200 (*row)->size = len;
5201 (*row)->len = len;
5202 (*row)->nlpcols = 0;
5203 (*row)->nunlinked = len;
5204 (*row)->nuses = 0;
5205 (*row)->lppos = -1;
5206 (*row)->lpipos = -1;
5207 (*row)->lpdepth = -1;
5208 (*row)->minidx = INT_MAX;
5209 (*row)->maxidx = INT_MIN;
5210 (*row)->nummaxval = 0;
5211 (*row)->numminval = 0;
5212 (*row)->numintcols = -1;
5213 (*row)->validactivitylp = -1;
5214 (*row)->validpsactivitydomchg = -1;
5215 (*row)->validactivitybdsdomchg = -1;
5216 (*row)->nlpsaftercreation = 0L;
5217 (*row)->activeinlpcounter = 0L;
5218 (*row)->age = 0;
5219 (*row)->rank = 0;
5220 (*row)->obsoletenode = -1;
5221 (*row)->fromcutpool = FALSE;
5222 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5223 (*row)->lpcolssorted = TRUE;
5224 (*row)->nonlpcolssorted = (len <= 1);
5225 (*row)->delaysort = FALSE;
5226 (*row)->validminmaxidx = FALSE;
5227 (*row)->lhschanged = FALSE;
5228 (*row)->rhschanged = FALSE;
5229 (*row)->coefchanged = FALSE;
5230 (*row)->local = local;
5231 (*row)->modifiable = modifiable;
5232 (*row)->nlocks = 0;
5233 (*row)->origintype = origintype; /*lint !e641*/
5234 (*row)->removable = removable;
5235 (*row)->inglobalcutpool = FALSE;
5236 (*row)->storedsolvals = NULL;
5237
5238 /* calculate row norms and min/maxidx, and check if row is sorted */
5239 rowCalcNorms(*row, set);
5240
5241 /* capture the row */
5242 SCIProwCapture(*row);
5243
5244 /* create event filter */
5245 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5246
5247 /* capture origin constraint if available */
5248 if( origintype == SCIP_ROWORIGINTYPE_CONS )
5249 {
5250 SCIP_CONS* cons = (SCIP_CONS*) origin;
5251 assert(cons != NULL);
5252 SCIPconsCapture(cons);
5253 }
5254
5255 return SCIP_OKAY;
5256} /*lint !e715*/
5257
5258/** frees an LP row */
5260 SCIP_ROW** row, /**< pointer to LP row */
5261 BMS_BLKMEM* blkmem, /**< block memory */
5262 SCIP_SET* set, /**< global SCIP settings */
5263 SCIP_LP* lp /**< current LP data */
5264 )
5265{
5266 assert(blkmem != NULL);
5267 assert(row != NULL);
5268 assert(*row != NULL);
5269 assert((*row)->nuses == 0);
5270 assert((*row)->lppos == -1);
5271 assert((*row)->eventfilter != NULL);
5272
5273 /* release constraint that has been used for creating the row */
5274 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5275 {
5276 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5277 assert(cons != NULL);
5278 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5279 }
5280
5281 /* remove column indices from corresponding rows */
5282 SCIP_CALL( rowUnlink(*row, set, lp) );
5283
5284 /* free event filter */
5285 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5286
5287 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5288 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5289 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5290 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5291 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5292 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5293 BMSfreeBlockMemory(blkmem, row);
5294
5295 return SCIP_OKAY;
5296}
5297
5298/** output row to file stream */
5300 SCIP_ROW* row, /**< LP row */
5301 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5302 FILE* file /**< output file (or NULL for standard output) */
5303 )
5304{
5305 int i;
5306
5307 assert(row != NULL);
5308
5309 /* print row name */
5310 if( row->name != NULL && row->name[0] != '\0' )
5311 {
5312 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5313 }
5314
5315 /* print left hand side */
5316 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5317
5318 /* print coefficients */
5319 if( row->len == 0 )
5320 SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5321 for( i = 0; i < row->len; ++i )
5322 {
5323 assert(row->cols[i] != NULL);
5324 assert(row->cols[i]->var != NULL);
5325 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5326 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5327 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5328 }
5329
5330 /* print constant */
5332 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5333
5334 /* print right hand side */
5335 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5336}
5337
5338/** increases usage counter of LP row */
5340 SCIP_ROW* row /**< LP row */
5341 )
5342{
5343 assert(row != NULL);
5344 assert(row->nuses >= 0);
5345 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5346
5347 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5348 row->nuses++;
5349}
5350
5351/** decreases usage counter of LP row, and frees memory if necessary */
5353 SCIP_ROW** row, /**< pointer to LP row */
5354 BMS_BLKMEM* blkmem, /**< block memory */
5355 SCIP_SET* set, /**< global SCIP settings */
5356 SCIP_LP* lp /**< current LP data */
5357 )
5358{
5359 assert(blkmem != NULL);
5360 assert(row != NULL);
5361 assert(*row != NULL);
5362 assert((*row)->nuses >= 1);
5363 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5364
5365 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5366 (*row)->nuses--;
5367 if( (*row)->nuses == 0 )
5368 {
5369 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5370 }
5371
5372 *row = NULL;
5373
5374 return SCIP_OKAY;
5375}
5376
5377/** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5379 SCIP_ROW* row /**< LP row */
5380 )
5381{
5382 assert(row != NULL);
5383
5384 /* check, if row is modifiable */
5385 if( !row->modifiable )
5386 {
5387 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5388 row->nlocks++;
5389 }
5390}
5391
5392/** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5394 SCIP_ROW* row /**< LP row */
5395 )
5396{
5397 assert(row != NULL);
5398
5399 /* check, if row is modifiable */
5400 if( !row->modifiable )
5401 {
5402 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5403 assert(row->nlocks > 0);
5404 row->nlocks--;
5405 }
5406}
5407
5408/** adds a previously non existing coefficient to an LP row */
5410 SCIP_ROW* row, /**< LP row */
5411 BMS_BLKMEM* blkmem, /**< block memory */
5412 SCIP_SET* set, /**< global SCIP settings */
5413 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5414 SCIP_LP* lp, /**< current LP data */
5415 SCIP_COL* col, /**< LP column */
5416 SCIP_Real val /**< value of coefficient */
5417 )
5418{
5419 assert(lp != NULL);
5420 assert(!lp->diving || row->lppos == -1);
5421
5422 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5423
5424 checkLinks(lp);
5425
5426 return SCIP_OKAY;
5427}
5428
5429/** deletes coefficient from row */
5431 SCIP_ROW* row, /**< row to be changed */
5432 BMS_BLKMEM* blkmem, /**< block memory */
5433 SCIP_SET* set, /**< global SCIP settings */
5434 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5435 SCIP_LP* lp, /**< current LP data */
5436 SCIP_COL* col /**< coefficient to be deleted */
5437 )
5438{
5439 int pos;
5440
5441 assert(row != NULL);
5442 assert(!row->delaysort);
5443 assert(lp != NULL);
5444 assert(!lp->diving || row->lppos == -1);
5445 assert(col != NULL);
5446 assert(col->var != NULL);
5447
5448 /* search the position of the column in the row's col vector */
5449 pos = rowSearchCoef(row, col);
5450 if( pos == -1 )
5451 {
5452 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5453 return SCIP_INVALIDDATA;
5454 }
5455 assert(0 <= pos && pos < row->len);
5456 assert(row->cols[pos] == col);
5457 assert(row->cols_index[pos] == col->index);
5458
5459 /* if column knows of the row, remove the row from the column's row vector */
5460 if( row->linkpos[pos] >= 0 )
5461 {
5462 assert(col->rows[row->linkpos[pos]] == row);
5463 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5464 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5465 }
5466
5467 /* delete the column from the row's col vector */
5468 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5469
5470 checkLinks(lp);
5471
5472 return SCIP_OKAY;
5473}
5474
5475/** changes or adds a coefficient to an LP row */
5477 SCIP_ROW* row, /**< LP row */
5478 BMS_BLKMEM* blkmem, /**< block memory */
5479 SCIP_SET* set, /**< global SCIP settings */
5480 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5481 SCIP_LP* lp, /**< current LP data */
5482 SCIP_COL* col, /**< LP column */
5483 SCIP_Real val /**< value of coefficient */
5484 )
5485{
5486 int pos;
5487
5488 assert(row != NULL);
5489 assert(!row->delaysort);
5490 assert(lp != NULL);
5491 assert(!lp->diving || row->lppos == -1);
5492 assert(col != NULL);
5493
5494 /* search the position of the column in the row's col vector */
5495 pos = rowSearchCoef(row, col);
5496
5497 /* check, if column already exists in the row's col vector */
5498 if( pos == -1 )
5499 {
5500 /* add previously not existing coefficient */
5501 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5502 }
5503 else
5504 {
5505 /* modify already existing coefficient */
5506 assert(0 <= pos && pos < row->len);
5507 assert(row->cols[pos] == col);
5508 assert(row->cols_index[pos] == col->index);
5509
5510 /* if column knows of the row, change the corresponding coefficient in the column */
5511 if( row->linkpos[pos] >= 0 )
5512 {
5513 assert(col->rows[row->linkpos[pos]] == row);
5514 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5515 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5516 }
5517
5518 /* change the coefficient in the row */
5519 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5520 }
5521
5522 checkLinks(lp);
5523
5524 return SCIP_OKAY;
5525}
5526
5527/** increases value of an existing or non-existing coefficient in an LP row */
5529 SCIP_ROW* row, /**< LP row */
5530 BMS_BLKMEM* blkmem, /**< block memory */
5531 SCIP_SET* set, /**< global SCIP settings */
5532 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5533 SCIP_LP* lp, /**< current LP data */
5534 SCIP_COL* col, /**< LP column */
5535 SCIP_Real incval /**< value to add to the coefficient */
5536 )
5537{
5538 int pos;
5539
5540 assert(row != NULL);
5541 assert(lp != NULL);
5542 assert(!lp->diving || row->lppos == -1);
5543 assert(col != NULL);
5544
5545 if( SCIPsetIsZero(set, incval) )
5546 return SCIP_OKAY;
5547
5548 /* search the position of the column in the row's col vector */
5549 pos = rowSearchCoef(row, col);
5550
5551 /* check, if column already exists in the row's col vector */
5552 if( pos == -1 )
5553 {
5554 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5555 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5556 }
5557 else
5558 {
5559 /* modify already existing coefficient */
5560 assert(0 <= pos && pos < row->len);
5561 assert(row->cols[pos] == col);
5562 assert(row->cols_index[pos] == col->index);
5563
5564 /* if column knows of the row, change the corresponding coefficient in the column */
5565 if( row->linkpos[pos] >= 0 )
5566 {
5567 assert(col->rows[row->linkpos[pos]] == row);
5568 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5569 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5570 }
5571
5572 /* change the coefficient in the row */
5573 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5574 }
5575
5576 checkLinks(lp);
5577
5578 /* invalid the activity */
5579 row->validactivitylp = -1;
5580
5581 return SCIP_OKAY;
5582}
5583
5584/** changes constant value of a row */
5586 SCIP_ROW* row, /**< LP row */
5587 BMS_BLKMEM* blkmem, /**< block memory */
5588 SCIP_SET* set, /**< global SCIP settings */
5589 SCIP_STAT* stat, /**< problem statistics */
5590 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5591 SCIP_LP* lp, /**< current LP data */
5592 SCIP_Real constant /**< new constant value */
5593 )
5594{
5595 assert(row != NULL);
5596 assert(row->lhs <= row->rhs);
5597 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5598 assert(stat != NULL);
5599 assert(lp != NULL);
5600 assert(!lp->diving || row->lppos == -1);
5601
5602 if( !SCIPsetIsEQ(set, constant, row->constant) )
5603 {
5604 SCIP_Real oldconstant;
5605
5606 if( row->validpsactivitydomchg == stat->domchgcount )
5607 {
5608 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
5609 row->pseudoactivity += constant - row->constant;
5610 }
5611 if( row->validactivitybdsdomchg == stat->domchgcount )
5612 {
5613 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
5614 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
5615 row->minactivity += constant - row->constant;
5616 row->maxactivity += constant - row->constant;
5617 }
5618
5619 if( !SCIPsetIsInfinity(set, -row->lhs) )
5620 {
5622 }
5623 if( !SCIPsetIsInfinity(set, row->rhs) )
5624 {
5626 }
5627
5628 oldconstant = row->constant;
5629
5630 row->constant = constant;
5631
5632 /* issue row constant changed event */
5633 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5634 }
5635
5636 return SCIP_OKAY;
5637}
5638
5639/** add constant value to a row */
5641 SCIP_ROW* row, /**< LP row */
5642 BMS_BLKMEM* blkmem, /**< block memory */
5643 SCIP_SET* set, /**< global SCIP settings */
5644 SCIP_STAT* stat, /**< problem statistics */
5645 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5646 SCIP_LP* lp, /**< current LP data */
5647 SCIP_Real addval /**< constant value to add to the row */
5648 )
5649{
5650 assert(row != NULL);
5651 assert(row->lhs <= row->rhs);
5652 assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5653 assert(stat != NULL);
5654 assert(lp != NULL);
5655 assert(!lp->diving || row->lppos == -1);
5656
5657 if( !SCIPsetIsZero(set, addval) )
5658 {
5659 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5660 }
5661
5662 return SCIP_OKAY;
5663}
5664
5665/** changes left hand side of LP row */
5667 SCIP_ROW* row, /**< LP row */
5668 BMS_BLKMEM* blkmem, /**< block memory */
5669 SCIP_SET* set, /**< global SCIP settings */
5670 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5671 SCIP_LP* lp, /**< current LP data */
5672 SCIP_Real lhs /**< new left hand side */
5673 )
5674{
5675 assert(row != NULL);
5676 assert(lp != NULL);
5677
5678 if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5679 {
5680 SCIP_Real oldlhs;
5681
5682 oldlhs = row->lhs;
5683
5684 row->lhs = lhs;
5686
5687 if( !lp->diving )
5688 {
5689 /* issue row side changed event */
5690 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5691 }
5692 }
5693
5694 return SCIP_OKAY;
5695}
5696
5697/** changes right hand side of LP row */
5699 SCIP_ROW* row, /**< LP row */
5700 BMS_BLKMEM* blkmem, /**< block memory */
5701 SCIP_SET* set, /**< global SCIP settings */
5702 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5703 SCIP_LP* lp, /**< current LP data */
5704 SCIP_Real rhs /**< new right hand side */
5705 )
5706{
5707 assert(row != NULL);
5708 assert(lp != NULL);
5709
5710 if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5711 {
5712 SCIP_Real oldrhs;
5713
5714 oldrhs = row->rhs;
5715
5716 row->rhs = rhs;
5718
5719 if( !lp->diving )
5720 {
5721 /* issue row side changed event */
5722 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5723 }
5724 }
5725
5726 return SCIP_OKAY;
5727}
5728
5729/** changes the local flag of LP row */
5731 SCIP_ROW* row, /**< LP row */
5732 SCIP_Bool local /**< new value for local flag */
5733 )
5734{
5735 assert(row != NULL);
5736
5737 row->local = local;
5738
5739 return SCIP_OKAY;
5740}
5741
5742/** additional scalars that are tried in integrality scaling */
5743static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5744static const int nscalars = 9;
5745
5746/** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5748 SCIP_ROW* row, /**< LP row */
5749 SCIP_SET* set, /**< global SCIP settings */
5750 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5751 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5752 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5753 SCIP_Real maxscale, /**< maximal allowed scalar */
5754 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5755 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5756 SCIP_Bool* success /**< stores whether returned value is valid */
5757 )
5758{
5759#ifndef NDEBUG
5760 SCIP_COL* col;
5761#endif
5762 SCIP_Longint gcd;
5763 SCIP_Longint scm;
5764 SCIP_Longint nominator;
5765 SCIP_Longint denominator;
5766 SCIP_Real val;
5767 SCIP_Real absval;
5768 SCIP_Real minval;
5769 SCIP_Real scaleval;
5770 SCIP_Real twomultval;
5771 SCIP_Bool scalable;
5772 SCIP_Bool twomult;
5773 SCIP_Bool rational;
5774 int c;
5775 int s;
5776
5777 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5778 assert(row != NULL);
5779 assert(row->len == 0 || row->cols != NULL);
5780 assert(row->len == 0 || row->cols_index != NULL);
5781 assert(row->len == 0 || row->vals != NULL);
5782 assert(maxdnom >= 1);
5783 assert(mindelta < 0.0);
5784 assert(maxdelta > 0.0);
5785 assert(success != NULL);
5786
5787 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5788 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5789
5790 if( intscalar != NULL )
5791 *intscalar = SCIP_INVALID;
5792 *success = FALSE;
5793
5794 /* get minimal absolute non-zero value */
5795 minval = SCIP_REAL_MAX;
5796 for( c = 0; c < row->len; ++c )
5797 {
5798#ifndef NDEBUG
5799 col = row->cols[c];
5800 assert(col != NULL);
5801 assert(col->var != NULL);
5803 assert(SCIPvarGetCol(col->var) == col);
5804#endif
5805 val = row->vals[c];
5806 assert(!SCIPsetIsZero(set, val));
5807
5808 if( val < mindelta || val > maxdelta )
5809 {
5810 absval = REALABS(val);
5811 minval = MIN(minval, absval);
5812 }
5813 }
5814 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5815 {
5816 /* all coefficients are zero (inside tolerances) */
5817 if( intscalar != NULL )
5818 *intscalar = 1.0;
5819 *success = TRUE;
5820 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5821
5822 return SCIP_OKAY;
5823 }
5824 assert(minval > MIN(-mindelta, maxdelta));
5825 assert(SCIPsetIsPositive(set, minval));
5826 assert(!SCIPsetIsInfinity(set, minval));
5827
5828 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5829 * and a power of 2
5830 */
5831 scaleval = 1.0/minval;
5832 scalable = (scaleval <= maxscale);
5833 for( c = 0; c < row->len && scalable; ++c )
5834 {
5835 /* don't look at continuous variables, if we don't have to */
5836 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5837 continue;
5838
5839 /* check, if the coefficient can be scaled with a simple scalar */
5840 val = row->vals[c];
5841 absval = REALABS(val);
5842 while( scaleval <= maxscale
5843 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5844 {
5845 for( s = 0; s < nscalars; ++s )
5846 {
5847 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5848 {
5849 scaleval *= scalars[s];
5850 break;
5851 }
5852 }
5853 if( s >= nscalars )
5854 scaleval *= 2.0;
5855 }
5856 scalable = (scaleval <= maxscale);
5857 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5858 }
5859 if( scalable )
5860 {
5861 /* make row coefficients integral by dividing them by the smallest coefficient
5862 * (and multiplying them with a power of 2)
5863 */
5864 assert(scaleval <= maxscale);
5865 if( intscalar != NULL )
5866 *intscalar = scaleval;
5867 *success = TRUE;
5868 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5869
5870 return SCIP_OKAY;
5871 }
5872
5873 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5874 twomultval = 1.0;
5875 twomult = (twomultval <= maxscale);
5876 for( c = 0; c < row->len && twomult; ++c )
5877 {
5878 /* don't look at continuous variables, if we don't have to */
5879 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5880 continue;
5881
5882 /* check, if the coefficient can be scaled with a simple scalar */
5883 val = row->vals[c];
5884 absval = REALABS(val);
5885 while( twomultval <= maxscale
5886 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5887 {
5888 for( s = 0; s < nscalars; ++s )
5889 {
5890 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5891 {
5892 twomultval *= scalars[s];
5893 break;
5894 }
5895 }
5896 if( s >= nscalars )
5897 twomultval *= 2.0;
5898 }
5899 twomult = (twomultval <= maxscale);
5900 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5901 val, twomultval, val*twomultval, twomult);
5902 }
5903 if( twomult )
5904 {
5905 /* make row coefficients integral by multiplying them with a power of 2 */
5906 assert(twomultval <= maxscale);
5907 if( intscalar != NULL )
5908 *intscalar = twomultval;
5909 *success = TRUE;
5910 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5911
5912 return SCIP_OKAY;
5913 }
5914
5915 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5916 * and the smallest common multiple of the denominators
5917 */
5918 gcd = 1;
5919 scm = 1;
5920 rational = (maxdnom > 1);
5921
5922 /* first coefficient (to initialize gcd) */
5923 for( c = 0; c < row->len && rational; ++c )
5924 {
5925 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5926 {
5927 val = row->vals[c];
5928 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5929 if( rational && nominator != 0 )
5930 {
5931 assert(denominator > 0);
5932 gcd = ABS(nominator);
5933 scm = denominator;
5934 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5935 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5936 val, nominator, denominator, gcd, scm, rational);
5937 break;
5938 }
5939 }
5940 }
5941
5942 /* remaining coefficients */
5943 for( ++c; c < row->len && rational; ++c )
5944 {
5945 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5946 {
5947 val = row->vals[c];
5948 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5949 if( rational && nominator != 0 )
5950 {
5951 assert(denominator > 0);
5952 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5953 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5954 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5955 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5956 val, nominator, denominator, gcd, scm, rational);
5957 }
5958 }
5959 }
5960
5961 if( rational )
5962 {
5963 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5964 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5965 if( intscalar != NULL )
5966 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5967 *success = TRUE;
5968 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5969 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5970 }
5971 else
5972 {
5973 assert(!(*success));
5974 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5975 }
5976
5977 return SCIP_OKAY;
5978}
5979
5980/** tries to scale row, s.t. all coefficients become integral */
5982 SCIP_ROW* row, /**< LP row */
5983 BMS_BLKMEM* blkmem, /**< block memory */
5984 SCIP_SET* set, /**< global SCIP settings */
5985 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5986 SCIP_STAT* stat, /**< problem statistics */
5987 SCIP_LP* lp, /**< current LP data */
5988 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5989 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5990 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5991 SCIP_Real maxscale, /**< maximal value to scale row with */
5992 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5993 SCIP_Bool* success /**< stores whether row could be made rational */
5994 )
5995{
5996 SCIP_Real intscalar;
5997
5998 assert(success != NULL);
5999
6000 /* calculate scalar to make coefficients integral */
6001 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
6002 &intscalar, success) );
6003
6004 if( *success )
6005 {
6006 /* scale the row */
6007 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6008 }
6009
6010 return SCIP_OKAY;
6011}
6012
6013/** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6014 * higher ones
6015 */
6017 SCIP_ROW* row /**< row to be sorted */
6018 )
6019{
6020 assert(row != NULL);
6021
6022 /* sort LP columns */
6023 rowSortLP(row);
6024
6025 /* sort non-LP columns */
6026 rowSortNonLP(row);
6027
6028#ifdef SCIP_MORE_DEBUG
6029 /* check the sorting */
6030 {
6031 int c;
6032 if( !row->delaysort )
6033 {
6034 for( c = 1; c < row->nlpcols; ++c )
6035 assert(row->cols[c]->index >= row->cols[c-1]->index);
6036 for( c = row->nlpcols + 1; c < row->len; ++c )
6037 assert(row->cols[c]->index >= row->cols[c-1]->index);
6038 }
6039 }
6040#endif
6041}
6042
6043/** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6044 * zero entries from row
6045 * the row must not be linked to the columns; otherwise, we would need to update the columns as
6046 * well, which is too expensive
6047 */
6048static
6050 SCIP_ROW* row, /**< row to be sorted */
6051 SCIP_SET* set /**< global SCIP settings */
6052 )
6053{
6054 assert(row != NULL);
6055 assert(!row->delaysort);
6056 assert(row->nunlinked == row->len);
6057 assert(row->nlpcols == 0);
6058
6059 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6060
6061 /* do nothing on empty rows; if row is sorted, nothing has to be done */
6062 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6063 {
6064 SCIP_COL** cols;
6065 int* cols_index;
6066 SCIP_Real* vals;
6067 int s;
6068 int t;
6069
6070 /* make sure, the row is sorted */
6071 SCIProwSort(row);
6072 assert(row->lpcolssorted);
6073 assert(row->nonlpcolssorted);
6074
6075 /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6076 cols = row->cols;
6077 cols_index = row->cols_index;
6078 vals = row->vals;
6079 assert(cols != NULL);
6080 assert(cols_index != NULL);
6081 assert(vals != NULL);
6082
6083 t = 0;
6084 row->integral = TRUE;
6085 assert(!SCIPsetIsZero(set, vals[0]));
6086 assert(row->linkpos[0] == -1);
6087
6088 for( s = 1; s < row->len; ++s )
6089 {
6090 assert(!SCIPsetIsZero(set, vals[s]));
6091 assert(row->linkpos[s] == -1);
6092
6093 if( cols[s] == cols[t] )
6094 {
6095 /* merge entries with equal column */
6096 vals[t] += vals[s];
6097 }
6098 else
6099 {
6100 /* go to the next entry, overwriting current entry if coefficient is zero */
6101 if( !SCIPsetIsZero(set, vals[t]) )
6102 {
6103 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6104 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6105
6106 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6107 t++;
6108 }
6109 cols[t] = cols[s];
6110 cols_index[t] = cols_index[s];
6111 vals[t] = vals[s];
6112 }
6113 }
6114 if( !SCIPsetIsZero(set, vals[t]) )
6115 {
6116 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6117 t++;
6118 }
6119 assert(s == row->len);
6120 assert(t <= row->len);
6121
6122 row->len = t;
6123 row->nunlinked = t;
6124
6125 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6126 if( t < s )
6127 rowCalcNorms(row, set);
6128 }
6129
6130#ifndef NDEBUG
6131 /* check for double entries */
6132 {
6133 int i;
6134 int j;
6135
6136 for( i = 0; i < row->len; ++i )
6137 {
6138 assert(row->cols[i] != NULL);
6139 assert(row->cols[i]->index == row->cols_index[i]);
6140 for( j = i+1; j < row->len; ++j )
6141 assert(row->cols[i] != row->cols[j]);
6142 }
6143 }
6144#endif
6145}
6146
6147/** enables delaying of row sorting */
6149 SCIP_ROW* row /**< LP row */
6150 )
6151{
6152 assert(row != NULL);
6153 assert(!row->delaysort);
6154
6155 row->delaysort = TRUE;
6156}
6157
6158/** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6160 SCIP_ROW* row, /**< LP row */
6161 SCIP_SET* set /**< global SCIP settings */
6162 )
6163{
6164 assert(row != NULL);
6165 assert(row->delaysort);
6166
6167 row->delaysort = FALSE;
6168 rowMerge(row, set);
6169}
6170
6171/** recalculates the current activity of a row */
6173 SCIP_ROW* row, /**< LP row */
6174 SCIP_STAT* stat /**< problem statistics */
6175 )
6176{
6177 SCIP_COL* col;
6178 int c;
6179
6180 assert(row != NULL);
6181 assert(stat != NULL);
6182
6183 row->activity = row->constant;
6184 for( c = 0; c < row->nlpcols; ++c )
6185 {
6186 col = row->cols[c];
6187 assert(col != NULL);
6188 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
6189 assert(col->lppos >= 0);
6190 assert(row->linkpos[c] >= 0);
6191 row->activity += row->vals[c] * col->primsol;
6192 }
6193
6194 if( row->nunlinked > 0 )
6195 {
6196 for( c = row->nlpcols; c < row->len; ++c )
6197 {
6198 col = row->cols[c];
6199 assert(col != NULL);
6200 assert(col->lppos >= 0 || col->primsol == 0.0);
6201 assert(col->lppos == -1 || row->linkpos[c] == -1);
6202 if( col->lppos >= 0 )
6203 row->activity += row->vals[c] * col->primsol;
6204 }
6205 }
6206#ifndef NDEBUG
6207 else
6208 {
6209 for( c = row->nlpcols; c < row->len; ++c )
6210 {
6211 col = row->cols[c];
6212 assert(col != NULL);
6213 assert(col->primsol == 0.0);
6214 assert(col->lppos == -1);
6215 assert(row->linkpos[c] >= 0);
6216 }
6217 }
6218#endif
6219
6220 row->validactivitylp = stat->lpcount;
6221}
6222
6223/** returns the activity of a row in the current LP solution */
6225 SCIP_ROW* row, /**< LP row */
6226 SCIP_SET* set, /**< global SCIP settings */
6227 SCIP_STAT* stat, /**< problem statistics */
6228 SCIP_LP* lp /**< current LP data */
6229 )
6230{
6231 SCIP_Real inf;
6232 SCIP_Real activity;
6233
6234 assert(row != NULL);
6235 assert(stat != NULL);
6236 assert(lp != NULL);
6237 assert(row->validactivitylp <= stat->lpcount);
6238 assert(lp->validsollp == stat->lpcount);
6239
6240 if( row->validactivitylp != stat->lpcount )
6241 SCIProwRecalcLPActivity(row, stat);
6242 assert(row->validactivitylp == stat->lpcount);
6243 assert(row->activity != SCIP_INVALID); /*lint !e777*/
6244
6245 activity = row->activity;
6246 inf = SCIPsetInfinity(set);
6247 activity = MAX(activity, -inf);
6248 activity = MIN(activity, +inf);
6249
6250 return activity;
6251}
6252
6253/** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6255 SCIP_ROW* row, /**< LP row */
6256 SCIP_SET* set, /**< global SCIP settings */
6257 SCIP_STAT* stat, /**< problem statistics */
6258 SCIP_LP* lp /**< current LP data */
6259 )
6260{
6261 SCIP_Real activity;
6262
6263 assert(row != NULL);
6264
6265 activity = SCIProwGetLPActivity(row, set, stat, lp);
6266
6267 return MIN(row->rhs - activity, activity - row->lhs);
6268}
6269
6270/** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6271 *
6272 * @todo Implement calculation of activities similar to LPs.
6273 */
6275 SCIP_ROW* row, /**< LP row */
6276 SCIP_SET* set, /**< global SCIP settings */
6277 SCIP_STAT* stat /**< problem statistics */
6278 )
6279{
6280 SCIP_Real inf;
6281 SCIP_Real activity;
6282 SCIP_COL* col;
6283 int c;
6284
6285 assert( row != NULL );
6286 assert( stat != NULL );
6287
6288 activity = row->constant;
6289 for (c = 0; c < row->nlpcols; ++c)
6290 {
6291 col = row->cols[c];
6292 assert( col != NULL );
6293 assert( col->lppos >= 0 );
6294 assert( col->var != NULL );
6295 assert( row->linkpos[c] >= 0 );
6296 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6297 }
6298
6299 if ( row->nunlinked > 0 )
6300 {
6301 for (c = row->nlpcols; c < row->len; ++c)
6302 {
6303 col = row->cols[c];
6304 assert( col != NULL );
6305 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6306 if ( col->lppos >= 0 )
6307 {
6308 assert( col->var != NULL );
6309 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6310 }
6311 }
6312 }
6313#ifndef NDEBUG
6314 else
6315 {
6316 for (c = row->nlpcols; c < row->len; ++c)
6317 {
6318 col = row->cols[c];
6319 assert( col != NULL );
6320 assert( col->lppos == -1 );
6321 assert( row->linkpos[c] >= 0 );
6322 }
6323 }
6324#endif
6325 inf = SCIPsetInfinity(set);
6326 activity = MAX(activity, -inf);
6327 activity = MIN(activity, +inf);
6328
6329 return MIN(row->rhs - activity, activity - row->lhs);
6330}
6331
6332/** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6333 *
6334 * @todo Implement calculation of activities similar to LPs.
6335 */
6337 SCIP_ROW* row, /**< LP row */
6338 SCIP_SET* set, /**< global SCIP settings */
6339 SCIP_STAT* stat /**< problem statistics */
6340 )
6341{
6342 SCIP_Real inf;
6343 SCIP_Real activity;
6344 SCIP_COL* col;
6345 int c;
6346
6347 assert( row != NULL );
6348 assert( stat != NULL );
6349
6350 activity = row->constant;
6351 for (c = 0; c < row->nlpcols; ++c)
6352 {
6353 col = row->cols[c];
6354 assert( col != NULL );
6355 assert( col->lppos >= 0 );
6356 assert( col->var != NULL );
6357 assert( row->linkpos[c] >= 0 );
6358 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6359 }
6360
6361 if ( row->nunlinked > 0 )
6362 {
6363 for (c = row->nlpcols; c < row->len; ++c)
6364 {
6365 col = row->cols[c];
6366 assert( col != NULL );
6367 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6368 if ( col->lppos >= 0 )
6369 {
6370 assert( col->var != NULL );
6371 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6372 }
6373 }
6374 }
6375#ifndef NDEBUG
6376 else
6377 {
6378 for (c = row->nlpcols; c < row->len; ++c)
6379 {
6380 col = row->cols[c];
6381 assert( col != NULL );
6382 assert( col->lppos == -1 );
6383 assert( row->linkpos[c] >= 0 );
6384 }
6385 }
6386#endif
6387 inf = SCIPsetInfinity(set);
6388 activity = MAX(activity, -inf);
6389 activity = MIN(activity, +inf);
6390
6391 return MIN(row->rhs - activity, activity - row->lhs);
6392}
6393
6394/** calculates the current pseudo activity of a row */
6396 SCIP_ROW* row, /**< row data */
6397 SCIP_STAT* stat /**< problem statistics */
6398 )
6399{
6400 SCIP_COL* col;
6401 int i;
6402
6403 assert(row != NULL);
6404 assert(stat != NULL);
6405
6406 row->pseudoactivity = row->constant;
6407 for( i = 0; i < row->len; ++i )
6408 {
6409 col = row->cols[i];
6410 assert(col != NULL);
6411 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6412 assert(col->var != NULL);
6414
6415 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6416 }
6418 assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6419}
6420
6421/** returns the pseudo activity of a row in the current pseudo solution */
6423 SCIP_ROW* row, /**< LP row */
6424 SCIP_SET* set, /**< global SCIP settings */
6425 SCIP_STAT* stat /**< problem statistics */
6426 )
6427{
6428 SCIP_Real inf;
6429 SCIP_Real activity;
6430
6431 assert(row != NULL);
6432 assert(stat != NULL);
6433 assert(row->validpsactivitydomchg <= stat->domchgcount);
6434
6435 /* check, if pseudo activity has to be calculated */
6436 if( row->validpsactivitydomchg != stat->domchgcount )
6437 SCIProwRecalcPseudoActivity(row, stat);
6438 assert(row->validpsactivitydomchg == stat->domchgcount);
6439 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
6440
6441 activity = row->pseudoactivity;
6442 inf = SCIPsetInfinity(set);
6443 activity = MAX(activity, -inf);
6444 activity = MIN(activity, +inf);
6445
6446 return activity;
6447}
6448
6449/** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6451 SCIP_ROW* row, /**< LP row */
6452 SCIP_SET* set, /**< global SCIP settings */
6453 SCIP_STAT* stat /**< problem statistics */
6454 )
6455{
6456 SCIP_Real pseudoactivity;
6457
6458 assert(row != NULL);
6459
6460 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6461
6462 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6463}
6464
6465/** returns the activity of a row for a given solution */
6467 SCIP_ROW* row, /**< LP row */
6468 SCIP_SET* set, /**< global SCIP settings */
6469 SCIP_STAT* stat, /**< problem statistics data */
6470 SCIP_SOL* sol /**< primal CIP solution */
6471 )
6472{
6473 SCIP_COL* col;
6474 SCIP_Real inf;
6475 SCIP_Real activity;
6476 SCIP_Real solval;
6477 int i;
6478
6479 assert(row != NULL);
6480
6481 activity = row->constant;
6482 for( i = 0; i < row->len; ++i )
6483 {
6484 col = row->cols[i];
6485 assert(col != NULL);
6486 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6487 solval = SCIPsolGetVal(sol, set, stat, col->var);
6488 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6489 {
6490 if( SCIPsetIsInfinity(set, -row->lhs) )
6491 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6492 else if( SCIPsetIsInfinity(set, row->rhs) )
6493 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6494 else
6495 solval = (col->lb + col->ub)/2.0;
6496 }
6497 activity += row->vals[i] * solval;
6498 }
6499
6500 inf = SCIPsetInfinity(set);
6501 activity = MAX(activity, -inf);
6502 activity = MIN(activity, +inf);
6503
6504 return activity;
6505}
6506
6507/** returns the feasibility of a row for the given solution */
6509 SCIP_ROW* row, /**< LP row */
6510 SCIP_SET* set, /**< global SCIP settings */
6511 SCIP_STAT* stat, /**< problem statistics data */
6512 SCIP_SOL* sol /**< primal CIP solution */
6513 )
6514{
6515 SCIP_Real activity;
6516
6517 assert(row != NULL);
6518
6519 activity = SCIProwGetSolActivity(row, set, stat, sol);
6520
6521 return MIN(row->rhs - activity, activity - row->lhs);
6522}
6523
6524/** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6525static
6527 SCIP_ROW* row, /**< row data */
6528 SCIP_SET* set, /**< global SCIP settings */
6529 SCIP_STAT* stat /**< problem statistics data */
6530 )
6531{
6532 SCIP_COL* col;
6533 SCIP_Real val;
6534 SCIP_Bool mininfinite;
6535 SCIP_Bool maxinfinite;
6536 int i;
6537
6538 assert(row != NULL);
6539 assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6540 assert(stat != NULL);
6541
6542 /* calculate activity bounds */
6543 mininfinite = FALSE;
6544 maxinfinite = FALSE;
6545 row->minactivity = row->constant;
6546 row->maxactivity = row->constant;
6547 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6548 {
6549 col = row->cols[i];
6550 assert(col != NULL);
6551 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6552 val = row->vals[i];
6553 if( val >= 0.0 )
6554 {
6555 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6556 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6557 if( !mininfinite )
6558 row->minactivity += val * col->lb;
6559 if( !maxinfinite )
6560 row->maxactivity += val * col->ub;
6561 }
6562 else
6563 {
6564 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6565 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6566 if( !mininfinite )
6567 row->minactivity += val * col->ub;
6568 if( !maxinfinite )
6569 row->maxactivity += val * col->lb;
6570 }
6571 }
6572
6573 if( mininfinite )
6575 if( maxinfinite )
6578
6579#ifndef NDEBUG
6580 {
6581 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6582
6583 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6584 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6585 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6586 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6587 * tolerance as a proxy to account for the accumulation effect
6588 */
6589 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6590 || EPSISINT(row->minactivity - row->constant, inttol));
6591 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6592 || EPSISINT(row->maxactivity - row->constant, inttol));
6593 }
6594#endif
6595}
6596
6597/** returns the minimal activity of a row w.r.t. the columns' bounds */
6599 SCIP_ROW* row, /**< LP row */
6600 SCIP_SET* set, /**< global SCIP settings */
6601 SCIP_STAT* stat /**< problem statistics data */
6602 )
6603{
6604 assert(row != NULL);
6605 assert(stat != NULL);
6606 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6607
6608 /* check, if activity bounds has to be calculated */
6609 if( row->validactivitybdsdomchg != stat->domchgcount )
6610 rowCalcActivityBounds(row, set, stat);
6611 assert(row->validactivitybdsdomchg == stat->domchgcount);
6612 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6613 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6614
6615 return row->minactivity;
6616}
6617
6618/** returns the maximal activity of a row w.r.t. the columns' bounds */
6620 SCIP_ROW* row, /**< LP row */
6621 SCIP_SET* set, /**< global SCIP settings */
6622 SCIP_STAT* stat /**< problem statistics data */
6623 )
6624{
6625 assert(row != NULL);
6626 assert(stat != NULL);
6627 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6628
6629 /* check, if activity bounds has to be calculated */
6630 if( row->validactivitybdsdomchg != stat->domchgcount )
6631 rowCalcActivityBounds(row, set, stat);
6632 assert(row->validactivitybdsdomchg == stat->domchgcount);
6633 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6634 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6635
6636 return row->maxactivity;
6637}
6638
6639/** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6641 SCIP_ROW* row, /**< LP row */
6642 SCIP_SET* set, /**< global SCIP settings */
6643 SCIP_STAT* stat /**< problem statistics data */
6644 )
6645{
6646 assert(row != NULL);
6647
6648 if( row->modifiable )
6649 return FALSE;
6650 if( !SCIPsetIsInfinity(set, -row->lhs) )
6651 {
6652 SCIP_Real minactivity;
6653
6654 minactivity = SCIProwGetMinActivity(row, set, stat);
6655 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6656 return FALSE;
6657 }
6658 if( !SCIPsetIsInfinity(set, row->rhs) )
6659 {
6660 SCIP_Real maxactivity;
6661
6662 maxactivity = SCIProwGetMaxActivity(row, set, stat);
6663 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6664 return FALSE;
6665 }
6666
6667 return TRUE;
6668}
6669
6670/** gets maximal absolute value of row vector coefficients */
6672 SCIP_ROW* row, /**< LP row */
6673 SCIP_SET* set /**< global SCIP settings */
6674 )
6675{
6676 assert(row != NULL);
6677
6678 if( row->nummaxval == 0 )
6679 rowCalcIdxsAndVals(row, set);
6680 assert(row->nummaxval > 0);
6681 assert(row->maxval >= 0.0 || row->len == 0);
6682
6683 return row->maxval;
6684}
6685
6686/** gets minimal absolute value of row vector's non-zero coefficients */
6688 SCIP_ROW* row, /**< LP row */
6689 SCIP_SET* set /**< global SCIP settings */
6690 )
6691{
6692 assert(row != NULL);
6693
6694 if( row->numminval == 0 )
6695 rowCalcIdxsAndVals(row, set);
6696 assert(row->numminval > 0);
6697 assert(row->minval >= 0.0 || row->len == 0);
6698
6699 return row->minval;
6700}
6701
6702/** gets maximal column index of row entries */
6704 SCIP_ROW* row, /**< LP row */
6705 SCIP_SET* set /**< global SCIP settings */
6706 )
6707{
6708 assert(row != NULL);
6709
6710 if( row->validminmaxidx == 0 )
6711 rowCalcIdxsAndVals(row, set);
6712 assert(row->maxidx >= 0 || row->len == 0);
6713 assert(row->validminmaxidx);
6714
6715 return row->maxidx;
6716}
6717
6718/** gets minimal column index of row entries */
6720 SCIP_ROW* row, /**< LP row */
6721 SCIP_SET* set /**< global SCIP settings */
6722 )
6723{
6724 assert(row != NULL);
6725
6726 if( row->validminmaxidx == 0 )
6727 rowCalcIdxsAndVals(row, set);
6728 assert(row->minidx >= 0 || row->len == 0);
6729 assert(row->validminmaxidx);
6730
6731 return row->minidx;
6732}
6733
6734/** gets number of integral columns in row */
6736 SCIP_ROW* row, /**< LP row */
6737 SCIP_SET* set /**< global SCIP settings */
6738 )
6739{
6740 assert(row != NULL);
6741
6742 if( row->numintcols == -1 )
6743 rowCalcIdxsAndVals(row, set);
6744
6745 assert(row->numintcols <= row->len && row->numintcols >= 0);
6746
6747 return row->numintcols;
6748}
6749
6750/** returns row's cutoff distance in the direction of the given primal solution */
6752 SCIP_ROW* row, /**< LP row */
6753 SCIP_SET* set, /**< global SCIP settings */
6754 SCIP_STAT* stat, /**< problem statistics data */
6755 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
6756 SCIP_LP* lp /**< current LP data */
6757 )
6758{
6759 SCIP_Real solcutoffdist;
6760 int k;
6761
6762 assert(sol != NULL);
6763
6764 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6765 {
6766 SCIP_Real scale = 0.0;
6767
6768 lp->validsoldirlp = stat->lpcount;
6769 lp->validsoldirsol = sol;
6770
6772
6773 for( k = 0; k < lp->ncols; ++k )
6774 {
6775 assert(lp->cols[k]->lppos == k);
6776 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6777 scale += SQR(lp->soldirection[k]);
6778 }
6779
6780 if( scale > 0.0 )
6781 {
6782 scale = 1.0 / sqrt(scale);
6783
6784 for( k = 0; k < lp->ncols; ++k )
6785 lp->soldirection[k] *= scale;
6786 }
6787 }
6788
6789 solcutoffdist = 0.0;
6790 for( k = 0; k < row->nlpcols; ++k )
6791 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6792
6793 for( k = row->nlpcols; k < row->len; ++k )
6794 {
6795 if( row->cols[k]->lppos >= 0 )
6796 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6797 }
6798
6799 if( SCIPsetIsSumZero(set, solcutoffdist) )
6800 solcutoffdist = set->num_sumepsilon;
6801
6802 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6803
6804 return solcutoffdist;
6805}
6806
6807/** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6809 SCIP_ROW* row, /**< LP row */
6810 SCIP_SET* set, /**< global SCIP settings */
6811 SCIP_STAT* stat, /**< problem statistics data */
6812 SCIP_LP* lp /**< current LP data */
6813 )
6814{
6815 SCIP_Real norm;
6816 SCIP_Real feasibility;
6817 SCIP_Real eps;
6818
6819 assert(set != NULL);
6820
6821 switch( set->sepa_efficacynorm )
6822 {
6823 case 'e':
6824 norm = SCIProwGetNorm(row);
6825 break;
6826 case 'm':
6827 norm = SCIProwGetMaxval(row, set);
6828 break;
6829 case 's':
6830 norm = SCIProwGetSumNorm(row);
6831 break;
6832 case 'd':
6833 norm = (row->len == 0 ? 0.0 : 1.0);
6834 break;
6835 default:
6836 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6837 SCIPABORT();
6838 norm = 0.0; /*lint !e527*/
6839 }
6840
6842 norm = MAX(norm, eps);
6843 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6844
6845 return -feasibility / norm;
6846}
6847
6848/** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6850 SCIP_ROW* row, /**< LP row */
6851 SCIP_SET* set, /**< global SCIP settings */
6852 SCIP_STAT* stat, /**< problem statistics data */
6853 SCIP_LP* lp, /**< current LP data */
6854 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6855 )
6856{
6857 SCIP_Real efficacy;
6858
6859 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6860
6861 return SCIPsetIsEfficacious(set, root, efficacy);
6862}
6863
6864/** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6866 SCIP_ROW* row, /**< LP row */
6867 SCIP_SET* set, /**< global SCIP settings */
6868 SCIP_STAT* stat, /**< problem statistics data */
6869 SCIP_SOL* sol /**< primal CIP solution */
6870 )
6871{
6872 SCIP_Real norm;
6873 SCIP_Real feasibility;
6874 SCIP_Real eps;
6875
6876 assert(set != NULL);
6877
6878 switch( set->sepa_efficacynorm )
6879 {
6880 case 'e':
6881 norm = SCIProwGetNorm(row);
6882 break;
6883 case 'm':
6884 norm = SCIProwGetMaxval(row, set);
6885 break;
6886 case 's':
6887 norm = SCIProwGetSumNorm(row);
6888 break;
6889 case 'd':
6890 norm = (row->len == 0 ? 0.0 : 1.0);
6891 break;
6892 default:
6893 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6894 SCIPABORT();
6895 norm = 0.0; /*lint !e527*/
6896 }
6897
6899 norm = MAX(norm, eps);
6900 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6901
6902 return -feasibility / norm;
6903}
6904
6905/** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6906 * efficacy
6907 */
6909 SCIP_ROW* row, /**< LP row */
6910 SCIP_SET* set, /**< global SCIP settings */
6911 SCIP_STAT* stat, /**< problem statistics data */
6912 SCIP_SOL* sol, /**< primal CIP solution */
6913 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6914 )
6915{
6916 SCIP_Real efficacy;
6917
6918 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6919
6920 return SCIPsetIsEfficacious(set, root, efficacy);
6921}
6922
6923/** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6925 SCIP_ROW* row, /**< LP row */
6926 SCIP_SET* set, /**< global SCIP settings */
6927 SCIP_STAT* stat /**< problem statistics data */
6928 )
6929{
6930 SCIP_Real norm;
6931 SCIP_Real feasibility;
6932 SCIP_Real eps;
6933
6934 assert(set != NULL);
6935
6936 switch( set->sepa_efficacynorm )
6937 {
6938 case 'e':
6939 norm = SCIProwGetNorm(row);
6940 break;
6941 case 'm':
6942 norm = SCIProwGetMaxval(row, set);
6943 break;
6944 case 's':
6945 norm = SCIProwGetSumNorm(row);
6946 break;
6947 case 'd':
6948 norm = (row->len == 0 ? 0.0 : 1.0);
6949 break;
6950 default:
6951 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6952 SCIPABORT();
6953 norm = 0.0; /*lint !e527*/
6954 }
6955
6957 norm = MAX(norm, eps);
6958 feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6959
6960 return -feasibility / norm;
6961}
6962
6963/** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6965 SCIP_ROW* row, /**< LP row */
6966 SCIP_SET* set, /**< global SCIP settings */
6967 SCIP_STAT* stat /**< problem statistics data */
6968 )
6969{
6970 SCIP_Real norm;
6971 SCIP_Real feasibility;
6972 SCIP_Real eps;
6973
6974 assert(set != NULL);
6975
6976 switch( set->sepa_efficacynorm )
6977 {
6978 case 'e':
6979 norm = SCIProwGetNorm(row);
6980 break;
6981 case 'm':
6982 norm = SCIProwGetMaxval(row, set);
6983 break;
6984 case 's':
6985 norm = SCIProwGetSumNorm(row);
6986 break;
6987 case 'd':
6988 norm = (row->len == 0 ? 0.0 : 1.0);
6989 break;
6990 default:
6991 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6992 SCIPABORT();
6993 norm = 0.0; /*lint !e527*/
6994 }
6995
6997 norm = MAX(norm, eps);
6998 feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6999
7000 return -feasibility / norm;
7001}
7002
7003/** returns the scalar product of the coefficient vectors of the two given rows
7004 *
7005 * @note the scalar product is computed w.r.t. the current LP columns only
7006 * @todo also consider non-LP columns for the computation?
7007 */
7009 SCIP_ROW* row1, /**< first LP row */
7010 SCIP_ROW* row2 /**< second LP row */
7011 )
7012{
7013 SCIP_Real scalarprod;
7014 int* row1colsidx;
7015 int* row2colsidx;
7016 int i1;
7017 int i2;
7018
7019 assert(row1 != NULL);
7020 assert(row2 != NULL);
7021
7022 /* Sort the column indices of both rows.
7023 *
7024 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7025 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7026 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7027 * for both or one of the non-LP columns for both.
7028 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7029 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7030 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7031 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7032 *
7033 * We distinguish the following cases:
7034 *
7035 * 1) both rows have no unlinked columns
7036 * -> we just check the LP partitions
7037 *
7038 * 2) exactly one row is completely unlinked, the other one is completely linked
7039 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7040 * (thus all common LP columns are regarded)
7041 *
7042 * 3) we have unlinked and LP columns in both rows
7043 * -> we need to compare four partitions at once
7044 *
7045 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7046 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7047 * other row
7048 *
7049 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7050 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7051 *
7052 * 5) both rows are completely unlinked
7053 * -> we need to compare two partitions: both complete rows
7054 */
7055 SCIProwSort(row1);
7056 assert(row1->lpcolssorted);
7057 assert(row1->nonlpcolssorted);
7058 SCIProwSort(row2);
7059 assert(row2->lpcolssorted);
7060 assert(row2->nonlpcolssorted);
7061
7062 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7063 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7064
7065 row1colsidx = row1->cols_index;
7066 row2colsidx = row2->cols_index;
7067
7068#ifndef NDEBUG
7069 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7070 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7071 {
7072 i1 = 0;
7073 i2 = row2->nlpcols;
7074 while( i1 < row1->nlpcols && i2 < row2->len )
7075 {
7076 assert(row1->cols[i1] != row2->cols[i2]);
7077 if( row1->cols[i1]->index < row2->cols[i2]->index )
7078 ++i1;
7079 else
7080 {
7081 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7082 ++i2;
7083 }
7084 }
7085 assert(i1 == row1->nlpcols || i2 == row2->len);
7086
7087 i1 = row1->nlpcols;
7088 i2 = 0;
7089 while( i1 < row1->len && i2 < row2->nlpcols )
7090 {
7091 assert(row1->cols[i1] != row2->cols[i2]);
7092 if( row1->cols[i1]->index < row2->cols[i2]->index )
7093 ++i1;
7094 else
7095 {
7096 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7097 ++i2;
7098 }
7099 }
7100 assert(i1 == row1->len || i2 == row2->nlpcols);
7101 }
7102#endif
7103
7104 /* The "easy" cases 1) and 2) */
7105 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7106 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7107 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7108 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7109 {
7110 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7111 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7112
7113 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7114 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7115 */
7116 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7117 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7118 scalarprod = 0.0;
7119
7120 /* calculate the scalar product */
7121 while( i1 >= 0 && i2 >= 0 )
7122 {
7123 assert(row1->cols[i1]->index == row1colsidx[i1]);
7124 assert(row2->cols[i2]->index == row2colsidx[i2]);
7125 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7126 if( row1colsidx[i1] < row2colsidx[i2] )
7127 --i2;
7128 else if( row1colsidx[i1] > row2colsidx[i2] )
7129 --i1;
7130 else
7131 {
7132 scalarprod += row1->vals[i1] * row2->vals[i2];
7133 --i1;
7134 --i2;
7135 }
7136 }
7137 }
7138 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7139 else
7140 {
7141 SCIP_Bool lpcols;
7142 int ilp1;
7143 int inlp1;
7144 int ilp2;
7145 int inlp2;
7146 int end1;
7147 int end2;
7148
7149 scalarprod = 0;
7150 ilp1 = 0;
7151 ilp2 = 0;
7152
7153 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7154 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7155 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7156
7157 /* handle the case of four partitions (case 3) until one partition is finished;
7158 * cases 4a), 4b), and 5) will fail the while-condition
7159 */
7160 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7161 {
7162 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7163 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7164 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7165 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7166 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7167 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7168 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7169 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7170
7171 /* rows have the same linked LP columns */
7172 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7173 {
7174 scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7175 ++ilp1;
7176 ++ilp2;
7177 }
7178 /* LP column of row1 is the same as unlinked column of row2 */
7179 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7180 {
7181 scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7182 ++ilp1;
7183 ++inlp2;
7184 }
7185 /* unlinked column of row1 is the same as LP column of row2 */
7186 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7187 {
7188 scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7189 ++inlp1;
7190 ++ilp2;
7191 }
7192 /* two unlinked LP columns are the same */
7193 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7194 {
7195 scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7196 ++inlp1;
7197 ++inlp2;
7198 }
7199 /* increase smallest counter */
7200 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7201 {
7202 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7203 {
7204 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7205 ++ilp1;
7206 else
7207 ++ilp2;
7208 }
7209 else
7210 {
7211 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7212 ++ilp1;
7213 else
7214 ++inlp2;
7215 }
7216 }
7217 else
7218 {
7219 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7220 {
7221 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7222 ++inlp1;
7223 else
7224 ++ilp2;
7225 }
7226 else
7227 {
7228 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7229 ++inlp1;
7230 else
7231 ++inlp2;
7232 }
7233 }
7234 }
7235
7236 /* One partition was completely handled, we just have to handle the three remaining partitions:
7237 * the remaining partition of this row and the two partitions of the other row.
7238 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7239 */
7240 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7241 {
7242 int tmpilp;
7243 int tmpinlp;
7244
7245 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7246
7247 SCIPswapPointers((void**) &row1, (void**) &row2);
7248 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7249 tmpilp = ilp1;
7250 tmpinlp = inlp1;
7251 ilp1 = ilp2;
7252 inlp1 = inlp2;
7253 ilp2 = tmpilp;
7254 inlp2 = tmpinlp;
7255 }
7256
7257 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7258 * -> this merges cases 4a) and 4b)
7259 */
7260 if( ilp1 == row1->nlpcols )
7261 {
7262 i1 = inlp1;
7263 end1 = row1->len;
7264 lpcols = FALSE;
7265 }
7266 else
7267 {
7268 assert(inlp1 == row1->len);
7269
7270 i1 = ilp1;
7271 end1 = row1->nlpcols;
7272 lpcols = TRUE;
7273 }
7274
7275 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7276 * case 5) will fail the while-condition
7277 */
7278 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7279 {
7280 assert(row1->cols[i1]->index == row1colsidx[i1]);
7281 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7282 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7283 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7284 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7285
7286 /* current column in row 1 is the same as the current LP column in row 2 */
7287 if( row1colsidx[i1] == row2colsidx[ilp2] )
7288 {
7289 scalarprod += row1->vals[i1] * row2->vals[ilp2];
7290 ++i1;
7291 ++ilp2;
7292 }
7293 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7294 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7295 {
7296 scalarprod += row1->vals[i1] * row2->vals[inlp2];
7297 ++i1;
7298 ++inlp2;
7299 }
7300 /* increase smallest counter */
7301 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7302 {
7303 if( row1colsidx[i1] < row2colsidx[ilp2] )
7304 ++i1;
7305 else
7306 ++ilp2;
7307 }
7308 else
7309 {
7310 if( row1colsidx[i1] < row2colsidx[inlp2] )
7311 ++i1;
7312 else
7313 ++inlp2;
7314 }
7315 }
7316
7317 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7318 * the two rows
7319 */
7320 if( i1 < end1 )
7321 {
7322 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7323 if( ilp2 == row2->nlpcols )
7324 {
7325 i2 = inlp2;
7326 end2 = row2->len;
7327 lpcols = FALSE;
7328 }
7329 else
7330 {
7331 assert(inlp2 == row2->len);
7332
7333 i2 = ilp2;
7334 end2 = row2->nlpcols;
7335 }
7336
7337 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7338 while( i1 < end1 && i2 < end2 )
7339 {
7340 assert(row1->cols[i1]->index == row1colsidx[i1]);
7341 assert(row2->cols[i2]->index == row2colsidx[i2]);
7342 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7343
7344 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7345 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7346 {
7347 scalarprod += row1->vals[i1] * row2->vals[i2];
7348 ++i1;
7349 ++i2;
7350 }
7351 /* increase smallest counter */
7352 else if( row1colsidx[i1] < row2colsidx[i2] )
7353 ++i1;
7354 else
7355 ++i2;
7356 }
7357 }
7358 }
7359
7360 return scalarprod;
7361}
7362
7363/** returns the discrete scalar product of the coefficient vectors of the two given rows */
7364static
7366 SCIP_ROW* row1, /**< first LP row */
7367 SCIP_ROW* row2 /**< second LP row */
7368 )
7369{
7370 int prod;
7371 int* row1colsidx;
7372 int* row2colsidx;
7373 int i1;
7374 int i2;
7375
7376 assert(row1 != NULL);
7377 assert(row2 != NULL);
7378
7379 /* Sort the column indices of both rows.
7380 *
7381 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7382 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7383 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7384 * for both or one of the non-LP columns for both.
7385 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7386 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7387 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7388 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7389 *
7390 * We distinguish the following cases:
7391 *
7392 * 1) both rows have no unlinked columns
7393 * -> we just check the LP partitions
7394 *
7395 * 2) exactly one row is completely unlinked, the other one is completely linked
7396 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7397 * (thus all common LP columns are regarded)
7398 *
7399 * 3) we have unlinked and LP columns in both rows
7400 * -> we need to compare four partitions at once
7401 *
7402 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7403 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7404 * other row
7405 *
7406 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7407 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7408 *
7409 * 5) both rows are completely unlinked
7410 * -> we need to compare two partitions: both complete rows
7411 */
7412 SCIProwSort(row1);
7413 assert(row1->lpcolssorted);
7414 assert(row1->nonlpcolssorted);
7415 SCIProwSort(row2);
7416 assert(row2->lpcolssorted);
7417 assert(row2->nonlpcolssorted);
7418
7419 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7420 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7421
7422 row1colsidx = row1->cols_index;
7423 row2colsidx = row2->cols_index;
7424
7425#ifndef NDEBUG
7426 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7427 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7428 {
7429 i1 = 0;
7430 i2 = row2->nlpcols;
7431 while( i1 < row1->nlpcols && i2 < row2->len )
7432 {
7433 assert(row1->cols[i1] != row2->cols[i2]);
7434 if( row1->cols[i1]->index < row2->cols[i2]->index )
7435 ++i1;
7436 else
7437 {
7438 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7439 ++i2;
7440 }
7441 }
7442 assert(i1 == row1->nlpcols || i2 == row2->len);
7443
7444 i1 = row1->nlpcols;
7445 i2 = 0;
7446 while( i1 < row1->len && i2 < row2->nlpcols )
7447 {
7448 assert(row1->cols[i1] != row2->cols[i2]);
7449 if( row1->cols[i1]->index < row2->cols[i2]->index )
7450 ++i1;
7451 else
7452 {
7453 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7454 ++i2;
7455 }
7456 }
7457 assert(i1 == row1->len || i2 == row2->nlpcols);
7458 }
7459#endif
7460
7461 /* The "easy" cases 1) and 2) */
7462 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7463 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7464 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7465 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7466 {
7467 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7468 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7469
7470 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7471 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7472 */
7473 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7474 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7475 prod = 0;
7476
7477 /* calculate the scalar product */
7478 while( i1 >= 0 && i2 >= 0 )
7479 {
7480 assert(row1->cols[i1]->index == row1colsidx[i1]);
7481 assert(row2->cols[i2]->index == row2colsidx[i2]);
7482 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7483 if( row1colsidx[i1] < row2colsidx[i2] )
7484 --i2;
7485 else if( row1colsidx[i1] > row2colsidx[i2] )
7486 --i1;
7487 else
7488 {
7489 ++prod;
7490 --i1;
7491 --i2;
7492 }
7493 }
7494 }
7495 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7496 else
7497 {
7498 SCIP_Bool lpcols;
7499 int ilp1;
7500 int inlp1;
7501 int ilp2;
7502 int inlp2;
7503 int end1;
7504 int end2;
7505
7506 prod = 0;
7507 ilp1 = 0;
7508 ilp2 = 0;
7509
7510 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7511 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7512 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7513
7514 /* handle the case of four partitions (case 3) until one partition is finished;
7515 * cases 4a), 4b), and 5) will fail the while-condition
7516 */
7517 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7518 {
7519 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7520 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7521 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7522 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7523 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7524 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7525 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7526 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7527
7528 /* rows have the same linked LP columns */
7529 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7530 {
7531 ++prod;
7532 ++ilp1;
7533 ++ilp2;
7534 }
7535 /* LP column of row1 is the same as unlinked column of row2 */
7536 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7537 {
7538 ++prod;
7539 ++ilp1;
7540 ++inlp2;
7541 }
7542 /* unlinked column of row1 is the same as LP column of row2 */
7543 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7544 {
7545 ++prod;
7546 ++inlp1;
7547 ++ilp2;
7548 }
7549 /* two unlinked LP columns are the same */
7550 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7551 {
7552 ++prod;
7553 ++inlp1;
7554 ++inlp2;
7555 }
7556 /* increase smallest counter */
7557 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7558 {
7559 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7560 {
7561 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7562 ++ilp1;
7563 else
7564 ++ilp2;
7565 }
7566 else
7567 {
7568 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7569 ++ilp1;
7570 else
7571 ++inlp2;
7572 }
7573 }
7574 else
7575 {
7576 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7577 {
7578 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7579 ++inlp1;
7580 else
7581 ++ilp2;
7582 }
7583 else
7584 {
7585 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7586 ++inlp1;
7587 else
7588 ++inlp2;
7589 }
7590 }
7591 }
7592
7593 /* One partition was completely handled, we just have to handle the three remaining partitions:
7594 * the remaining partition of this row and the two partitions of the other row.
7595 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7596 */
7597 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7598 {
7599 int tmpilp;
7600 int tmpinlp;
7601
7602 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7603
7604 SCIPswapPointers((void**) &row1, (void**) &row2);
7605 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7606 tmpilp = ilp1;
7607 tmpinlp = inlp1;
7608 ilp1 = ilp2;
7609 inlp1 = inlp2;
7610 ilp2 = tmpilp;
7611 inlp2 = tmpinlp;
7612 }
7613
7614 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7615 * -> this merges cases 4a) and 4b)
7616 */
7617 if( ilp1 == row1->nlpcols )
7618 {
7619 i1 = inlp1;
7620 end1 = row1->len;
7621 lpcols = FALSE;
7622 }
7623 else
7624 {
7625 assert(inlp1 == row1->len);
7626
7627 i1 = ilp1;
7628 end1 = row1->nlpcols;
7629 lpcols = TRUE;
7630 }
7631
7632 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7633 * case 5) will fail the while-condition
7634 */
7635 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7636 {
7637 assert(row1->cols[i1]->index == row1colsidx[i1]);
7638 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7639 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7640 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7641 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7642
7643 /* current column in row 1 is the same as the current LP column in row 2 */
7644 if( row1colsidx[i1] == row2colsidx[ilp2] )
7645 {
7646 ++prod;
7647 ++i1;
7648 ++ilp2;
7649 }
7650 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7651 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7652 {
7653 ++prod;
7654 ++i1;
7655 ++inlp2;
7656 }
7657 /* increase smallest counter */
7658 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7659 {
7660 if( row1colsidx[i1] < row2colsidx[ilp2] )
7661 ++i1;
7662 else
7663 ++ilp2;
7664 }
7665 else
7666 {
7667 if( row1colsidx[i1] < row2colsidx[inlp2] )
7668 ++i1;
7669 else
7670 ++inlp2;
7671 }
7672 }
7673
7674 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7675 * the two rows
7676 */
7677 if( i1 < end1 )
7678 {
7679 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7680 if( ilp2 == row2->nlpcols )
7681 {
7682 i2 = inlp2;
7683 end2 = row2->len;
7684 lpcols = FALSE;
7685 }
7686 else
7687 {
7688 assert(inlp2 == row2->len);
7689
7690 i2 = ilp2;
7691 end2 = row2->nlpcols;
7692 }
7693
7694 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7695 while( i1 < end1 && i2 < end2 )
7696 {
7697 assert(row1->cols[i1]->index == row1colsidx[i1]);
7698 assert(row2->cols[i2]->index == row2colsidx[i2]);
7699 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7700
7701 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7702 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7703 {
7704 ++prod;
7705 ++i1;
7706 ++i2;
7707 }
7708 /* increase smallest counter */
7709 else if( row1colsidx[i1] < row2colsidx[i2] )
7710 ++i1;
7711 else
7712 ++i2;
7713 }
7714 }
7715 }
7716
7717 return prod;
7718}
7719
7720/** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7721 * p = |v*w|/(|v|*|w|);
7722 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7723 */
7725 SCIP_ROW* row1, /**< first LP row */
7726 SCIP_ROW* row2, /**< second LP row */
7727 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7728 )
7729{
7730 SCIP_Real parallelism;
7731 SCIP_Real scalarprod;
7732
7733 switch( orthofunc )
7734 {
7735 case 'e':
7736 scalarprod = SCIProwGetScalarProduct(row1, row2);
7737 if( scalarprod == 0.0 )
7738 {
7739 parallelism = 0.0;
7740 break;
7741 }
7742
7743 if( SCIProwGetNorm(row1) == 0.0 )
7744 {
7745 /* In theory, this should not happen if the scalarproduct is not zero
7746 * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7747 * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7748 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7749 */
7750 int i;
7751 for( i = 0; i < row1->len; ++i )
7752 if( row1->cols[i]->lppos >= 0 )
7753 row1->sqrnorm += SQR(row1->vals[i]);
7754 assert(SCIProwGetNorm(row1) != 0.0);
7755 }
7756
7757 if( SCIProwGetNorm(row2) == 0.0 )
7758 {
7759 /* same as for row1 above: reeval norms if it is 0, which is wrong */
7760 int i;
7761 for( i = 0; i < row2->len; ++i )
7762 if( row2->cols[i]->lppos >= 0 )
7763 row2->sqrnorm += SQR(row2->vals[i]);
7764 assert(SCIProwGetNorm(row2) != 0.0);
7765 }
7766
7767 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7768 break;
7769
7770 case 'd':
7771 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7772 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7773 break;
7774
7775 default:
7776 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7777 SCIPABORT();
7778 parallelism = 0.0; /*lint !e527*/
7779 }
7780
7781 return parallelism;
7782}
7783
7784/** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7785 * o = 1 - |v*w|/(|v|*|w|);
7786 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7787 */
7789 SCIP_ROW* row1, /**< first LP row */
7790 SCIP_ROW* row2, /**< second LP row */
7791 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7792 )
7793{
7794 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7795}
7796
7797/** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7798 * function, if the value is 0, it is orthogonal to the objective function
7799 */
7801 SCIP_ROW* row, /**< LP row */
7802 SCIP_SET* set, /**< global SCIP settings */
7803 SCIP_LP* lp /**< current LP data */
7804 )
7805{
7806 SCIP_Real prod;
7807 SCIP_Real parallelism;
7808
7809 assert(row != NULL);
7810 assert(lp != NULL);
7811
7812 if( lp->objsqrnormunreliable )
7814
7815 assert(!lp->objsqrnormunreliable);
7816 assert(lp->objsqrnorm >= 0.0);
7817
7818 checkRowSqrnorm(row);
7819 checkRowObjprod(row);
7820
7821 prod = row->sqrnorm * lp->objsqrnorm;
7822
7823 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / sqrt(prod) : 0.0;
7824 assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7825 assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7826 parallelism = MIN(parallelism, 1.0);
7827 parallelism = MAX(parallelism, 0.0);
7828
7829 return parallelism;
7830}
7831
7832/** includes event handler with given data in row's event filter */
7834 SCIP_ROW* row, /**< row */
7835 BMS_BLKMEM* blkmem, /**< block memory */
7836 SCIP_SET* set, /**< global SCIP settings */
7837 SCIP_EVENTTYPE eventtype, /**< event type to catch */
7838 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7839 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7840 int* filterpos /**< pointer to store position of event filter entry, or NULL */
7841 )
7842{
7843 assert(row != NULL);
7844 assert(row->eventfilter != NULL);
7845 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7846 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7847
7848 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7849 eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7850
7851 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7852
7853 return SCIP_OKAY;
7854}
7855
7856/** deletes event handler with given data from row's event filter */
7858 SCIP_ROW* row, /**< row */
7859 BMS_BLKMEM* blkmem, /**< block memory */
7860 SCIP_SET* set, /**< global SCIP settings */
7861 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7862 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7863 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7864 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7865 )
7866{
7867 assert(row != NULL);
7868 assert(row->eventfilter != NULL);
7869
7870 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7871
7872 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7873
7874 return SCIP_OKAY;
7875}
7876
7877/** marks a row to be not removable from the LP in the current node because it became obsolete */
7879 SCIP_ROW* row, /**< LP row */
7880 SCIP_STAT* stat /**< problem statistics */
7881 )
7882{
7883 assert(row != NULL);
7884 assert(stat != NULL);
7885 assert(stat->nnodes > 0);
7886
7887 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7888 row->obsoletenode = stat->nnodes;
7889}
7890
7891/*
7892 * LP solver data update
7893 */
7894
7895/** resets column data to represent a column not in the LP solver */
7896static
7898 SCIP_COL* col /**< column to be marked deleted */
7899 )
7900{
7901 assert(col != NULL);
7902
7903 col->lpipos = -1;
7904 col->primsol = 0.0;
7905 col->redcost = SCIP_INVALID;
7906 col->farkascoef = SCIP_INVALID;
7907 col->sbdown = SCIP_INVALID;
7908 col->sbup = SCIP_INVALID;
7909 col->sbdownvalid = FALSE;
7910 col->sbupvalid = FALSE;
7911 col->validredcostlp = -1;
7912 col->validfarkaslp = -1;
7913 col->sbitlim = -1;
7914 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7915}
7916
7917/** applies all cached column removals to the LP solver */
7918static
7920 SCIP_LP* lp /**< current LP data */
7921 )
7922{
7923 assert(lp != NULL);
7924 assert(lp->lpifirstchgcol <= lp->nlpicols);
7925 assert(lp->lpifirstchgcol <= lp->ncols);
7926
7927 /* find the first column to change */
7928 while( lp->lpifirstchgcol < lp->nlpicols
7929 && lp->lpifirstchgcol < lp->ncols
7930 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7931 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7932 {
7933 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7934 lp->lpifirstchgcol++;
7935 }
7936
7937 /* shrink LP to the part which didn't change */
7938 if( lp->lpifirstchgcol < lp->nlpicols )
7939 {
7940 int i;
7941
7942 assert(!lp->diving);
7943 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7945 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7946 {
7947 markColDeleted(lp->lpicols[i]);
7948 }
7949 lp->nlpicols = lp->lpifirstchgcol;
7950 lp->flushdeletedcols = TRUE;
7951 lp->updateintegrality = TRUE;
7952
7953 /* mark the LP unsolved */
7954 lp->solved = FALSE;
7955 lp->primalfeasible = FALSE;
7956 lp->primalchecked = FALSE;
7957 lp->lpobjval = SCIP_INVALID;
7959 }
7960 assert(lp->nlpicols == lp->lpifirstchgcol);
7961
7962 return SCIP_OKAY;
7963}
7964
7965/** computes for the given column the lower and upper bound that should be flushed into the LP
7966 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7967 * the bounds are explicitly added to the LP in any case
7968 */
7969static
7971 SCIP_LP* lp, /**< current LP data */
7972 SCIP_SET* set, /**< global SCIP settings */
7973 SCIP_COL* col, /**< column to compute bounds for */
7974 SCIP_Real lpiinf, /**< infinity value if the LP solver */
7975 SCIP_Real* lb, /**< pointer to store the new lower bound */
7976 SCIP_Real* ub /**< pointer to store the new upper bound */
7977 )
7978{
7979 assert(lp != NULL);
7980 assert(set != NULL);
7981 assert(col != NULL);
7982 assert(lb != NULL);
7983 assert(ub != NULL);
7984
7985 /* get the correct new lower bound:
7986 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7987 * if we are in diving mode, ignore lazy bounds and always take the lower bound
7988 */
7989 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7990 (*lb) = -lpiinf;
7991 else
7992 (*lb) = col->lb;
7993 /* get the correct new upper bound:
7994 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7995 * if we are in diving mode, ignore lazy bounds and always take the upper bound
7996 */
7997 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7998 (*ub) = lpiinf;
7999 else
8000 (*ub) = col->ub;
8001}
8002
8003/** applies all cached column additions to the LP solver */
8004static
8006 SCIP_LP* lp, /**< current LP data */
8007 BMS_BLKMEM* blkmem, /**< block memory */
8008 SCIP_SET* set, /**< global SCIP settings */
8009 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8010 )
8011{
8012 SCIP_Real* obj;
8013 SCIP_Real* lb;
8014 SCIP_Real* ub;
8015 int* beg;
8016 int* ind;
8017 SCIP_Real* val;
8018 char** name;
8019 SCIP_COL* col;
8020 SCIP_Real lpiinf;
8021 int c;
8022 int pos;
8023 int nnonz;
8024 int naddcols;
8025 int naddcoefs;
8026 int i;
8027 int lpipos;
8028
8029 assert(lp != NULL);
8030 assert(lp->lpifirstchgcol == lp->nlpicols);
8031 assert(blkmem != NULL);
8032 assert(set != NULL);
8033
8034 /* if there are no columns to add, we are ready */
8035 if( lp->ncols == lp->nlpicols )
8036 return SCIP_OKAY;
8037
8038 /* add the additional columns */
8039 assert(!lp->diving);
8040 assert(lp->ncols > lp->nlpicols);
8041 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8042
8043 /* get the solver's infinity value */
8044 lpiinf = SCIPlpiInfinity(lp->lpi);
8045
8046 /* count the (maximal) number of added coefficients, calculate the number of added columns */
8047 naddcols = lp->ncols - lp->nlpicols;
8048 naddcoefs = 0;
8049 for( c = lp->nlpicols; c < lp->ncols; ++c )
8050 naddcoefs += lp->cols[c]->len;
8051 assert(naddcols > 0);
8052
8053 /* get temporary memory for changes */
8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8057 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8058 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8059 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8060 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8061
8062 /* fill temporary memory with column data */
8063 nnonz = 0;
8064 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8065 {
8066 col = lp->cols[c];
8067 assert(col != NULL);
8068 assert(col->var != NULL);
8070 assert(SCIPvarGetCol(col->var) == col);
8071 assert(col->lppos == c);
8072 assert(nnonz + col->nlprows <= naddcoefs);
8073
8074 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8075 debugColPrint(set, col);
8076
8077 /* Because the column becomes a member of the LP solver, it now can take values
8078 * different from zero. That means, we have to include the column in the corresponding
8079 * row vectors.
8080 */
8081 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8082
8083 lp->lpicols[c] = col;
8084 col->lpipos = c;
8085 col->primsol = SCIP_INVALID;
8086 col->redcost = SCIP_INVALID;
8087 col->farkascoef = SCIP_INVALID;
8088 col->sbdown = SCIP_INVALID;
8089 col->sbup = SCIP_INVALID;
8090 col->sbdownvalid = FALSE;
8091 col->sbupvalid = FALSE;
8092 col->validredcostlp = -1;
8093 col->validfarkaslp = -1;
8094 col->sbitlim = -1;
8095 col->objchanged = FALSE;
8096 col->lbchanged = FALSE;
8097 col->ubchanged = FALSE;
8098 col->coefchanged = FALSE;
8099 obj[pos] = col->obj;
8100
8101 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8102 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8103
8104 beg[pos] = nnonz;
8105 name[pos] = (char*)SCIPvarGetName(col->var);
8106
8107 col->flushedobj = obj[pos];
8108 col->flushedlb = lb[pos];
8109 col->flushedub = ub[pos];
8110
8111 for( i = 0; i < col->nlprows; ++i )
8112 {
8113 assert(col->rows[i] != NULL);
8114 lpipos = col->rows[i]->lpipos;
8115 if( lpipos >= 0 )
8116 {
8117 assert(lpipos < lp->nrows);
8118 assert(nnonz < naddcoefs);
8119 ind[nnonz] = lpipos;
8120 val[nnonz] = col->vals[i];
8121 nnonz++;
8122 }
8123 }
8124#ifndef NDEBUG
8125 for( i = col->nlprows; i < col->len; ++i )
8126 {
8127 assert(col->rows[i] != NULL);
8128 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8129 }
8130#endif
8131 }
8132
8133 /* call LP interface */
8134 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8135 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8136 lp->nlpicols = lp->ncols;
8137 lp->lpifirstchgcol = lp->nlpicols;
8138
8139 /* free temporary memory */
8147
8148 lp->flushaddedcols = TRUE;
8149 lp->updateintegrality = TRUE;
8150
8151 /* mark the LP unsolved */
8152 lp->solved = FALSE;
8153 lp->dualfeasible = FALSE;
8154 lp->dualchecked = FALSE;
8155 lp->lpobjval = SCIP_INVALID;
8157
8158 return SCIP_OKAY;
8159}
8160
8161/** resets row data to represent a row not in the LP solver */
8162static
8164 SCIP_ROW* row /**< row to be marked deleted */
8165 )
8166{
8167 assert(row != NULL);
8168
8169 row->lpipos = -1;
8170 row->dualsol = 0.0;
8171 row->activity = SCIP_INVALID;
8172 row->dualfarkas = 0.0;
8173 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8174 row->validactivitylp = -1;
8175}
8176
8177/** applies all cached row removals to the LP solver */
8178static
8180 SCIP_LP* lp, /**< current LP data */
8181 BMS_BLKMEM* blkmem, /**< block memory */
8182 SCIP_SET* set /**< global SCIP settings */
8183 )
8184{
8185 assert(lp != NULL);
8186 assert(lp->lpifirstchgrow <= lp->nlpirows);
8187 assert(lp->lpifirstchgrow <= lp->nrows);
8188
8189 /* find the first row to change */
8190 while( lp->lpifirstchgrow < lp->nlpirows
8191 && lp->lpifirstchgrow < lp->nrows
8192 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8193 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8194 {
8195 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8196 lp->lpifirstchgrow++;
8197 }
8198
8199 /* shrink LP to the part which didn't change */
8200 if( lp->lpifirstchgrow < lp->nlpirows )
8201 {
8202 int i;
8203
8204 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8206 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8207 {
8208 markRowDeleted(lp->lpirows[i]);
8209 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8210 }
8211 lp->nlpirows = lp->lpifirstchgrow;
8212 lp->flushdeletedrows = TRUE;
8213
8214 /* mark the LP unsolved */
8215 lp->solved = FALSE;
8216 lp->dualfeasible = FALSE;
8217 lp->dualchecked = FALSE;
8218 lp->lpobjval = SCIP_INVALID;
8220 }
8221 assert(lp->nlpirows == lp->lpifirstchgrow);
8222
8223 return SCIP_OKAY;
8224}
8225
8226/** applies all cached row additions and removals to the LP solver */
8227static
8229 SCIP_LP* lp, /**< current LP data */
8230 BMS_BLKMEM* blkmem, /**< block memory */
8231 SCIP_SET* set, /**< global SCIP settings */
8232 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8233 )
8234{
8235 SCIP_Real* lhs;
8236 SCIP_Real* rhs;
8237 int* beg;
8238 int* ind;
8239 SCIP_Real* val;
8240 char** name;
8241 SCIP_ROW* row;
8242 SCIP_Real lpiinf;
8243 int r;
8244 int pos;
8245 int nnonz;
8246 int naddrows;
8247 int naddcoefs;
8248 int i;
8249 int lpipos;
8250
8251 assert(lp != NULL);
8252 assert(lp->lpifirstchgrow == lp->nlpirows);
8253 assert(blkmem != NULL);
8254
8255 /* if there are no rows to add, we are ready */
8256 if( lp->nrows == lp->nlpirows )
8257 return SCIP_OKAY;
8258
8259 /* add the additional rows */
8260 assert(lp->nrows > lp->nlpirows);
8261 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8262
8263 /* get the solver's infinity value */
8264 lpiinf = SCIPlpiInfinity(lp->lpi);
8265
8266 /* count the (maximal) number of added coefficients, calculate the number of added rows */
8267 naddrows = lp->nrows - lp->nlpirows;
8268 naddcoefs = 0;
8269 for( r = lp->nlpirows; r < lp->nrows; ++r )
8270 naddcoefs += lp->rows[r]->len;
8271 assert(naddrows > 0);
8272
8273 /* get temporary memory for changes */
8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8276 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8277 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8278 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8279 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8280
8281 /* fill temporary memory with row data */
8282 nnonz = 0;
8283 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8284 {
8285 row = lp->rows[r];
8286 assert(row != NULL);
8287 assert(row->lppos == r);
8288 assert(nnonz + row->nlpcols <= naddcoefs);
8289
8290 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8291 debugRowPrint(set, row);
8292
8293 /* Because the row becomes a member of the LP solver, its dual variable now can take values
8294 * different from zero. That means, we have to include the row in the corresponding
8295 * column vectors.
8296 */
8297 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8298
8299 SCIProwCapture(row);
8300 lp->lpirows[r] = row;
8301 row->lpipos = r;
8302 row->dualsol = SCIP_INVALID;
8303 row->activity = SCIP_INVALID;
8304 row->dualfarkas = SCIP_INVALID;
8305 row->validactivitylp = -1;
8306 row->lhschanged = FALSE;
8307 row->rhschanged = FALSE;
8308 row->coefchanged = FALSE;
8309 if( SCIPsetIsInfinity(set, -row->lhs) )
8310 lhs[pos] = -lpiinf;
8311 else
8312 lhs[pos] = row->lhs - row->constant;
8313 if( SCIPsetIsInfinity(set, row->rhs) )
8314 rhs[pos] = lpiinf;
8315 else
8316 rhs[pos] = row->rhs - row->constant;
8317 beg[pos] = nnonz;
8318 name[pos] = row->name;
8319
8320 row->flushedlhs = lhs[pos];
8321 row->flushedrhs = rhs[pos];
8322
8323 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8324 for( i = 0; i < row->nlpcols; ++i )
8325 {
8326 assert(row->cols[i] != NULL);
8327 lpipos = row->cols[i]->lpipos;
8328 if( lpipos >= 0 )
8329 {
8330 assert(lpipos < lp->ncols);
8331 assert(nnonz < naddcoefs);
8332 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8333 ind[nnonz] = lpipos;
8334 val[nnonz] = row->vals[i];
8335 nnonz++;
8336 }
8337 }
8338 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8339#ifndef NDEBUG
8340 for( i = row->nlpcols; i < row->len; ++i )
8341 {
8342 assert(row->cols[i] != NULL);
8343 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8344 }
8345#endif
8346 }
8347
8348 /* call LP interface */
8349 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8350 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8351 lp->nlpirows = lp->nrows;
8352 lp->lpifirstchgrow = lp->nlpirows;
8353
8354 /* free temporary memory */
8361
8362 lp->flushaddedrows = TRUE;
8363
8364 /* mark the LP unsolved */
8365 lp->solved = FALSE;
8366 lp->primalfeasible = FALSE;
8367 lp->primalchecked = FALSE;
8368 lp->lpobjval = SCIP_INVALID;
8370
8371 return SCIP_OKAY;
8372}
8373
8374/** applies all cached column bound and objective changes to the LP */
8375static
8377 SCIP_LP* lp, /**< current LP data */
8378 SCIP_SET* set /**< global SCIP settings */
8379 )
8380{
8381#ifndef NDEBUG
8382 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8383#endif
8384 SCIP_COL* col;
8385 int* objind;
8386 int* bdind;
8387 SCIP_Real* obj;
8388 SCIP_Real* lb;
8389 SCIP_Real* ub;
8390 SCIP_Real lpiinf;
8391 int nobjchg;
8392 int nbdchg;
8393 int i;
8394
8395 assert(lp != NULL);
8396
8397 if( lp->nchgcols == 0 )
8398 return SCIP_OKAY;
8399
8400 /* get the solver's infinity value */
8401 lpiinf = SCIPlpiInfinity(lp->lpi);
8402
8403 /* get temporary memory for changes */
8404 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8406 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8409
8410 /* collect all cached bound and objective changes */
8411 nobjchg = 0;
8412 nbdchg = 0;
8413 for( i = 0; i < lp->nchgcols; ++i )
8414 {
8415 col = lp->chgcols[i];
8416 assert(col != NULL);
8417 assert(col->var != NULL);
8419 assert(SCIPvarGetCol(col->var) == col);
8420
8421 if( col->lpipos >= 0 )
8422 {
8423#ifndef NDEBUG
8424 /* do not check consistency of data with LPI in case of LPI=none */
8425 if( !lpinone )
8426 {
8427 SCIP_Real lpiobj;
8428 SCIP_Real lpilb;
8429 SCIP_Real lpiub;
8430
8431 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8432 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8433 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8434 assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb))
8435 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8436 assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub))
8437 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8438 }
8439#endif
8440
8441 if( col->objchanged )
8442 {
8443 SCIP_Real newobj;
8444
8445 newobj = col->obj;
8446 if( col->flushedobj != newobj ) /*lint !e777*/
8447 {
8448 assert(nobjchg < lp->ncols);
8449 objind[nobjchg] = col->lpipos;
8450 obj[nobjchg] = newobj;
8451 nobjchg++;
8452 col->flushedobj = newobj;
8453 }
8454 col->objchanged = FALSE;
8455 }
8456
8457 if( col->lbchanged || col->ubchanged )
8458 {
8459 SCIP_Real newlb;
8460 SCIP_Real newub;
8461
8462 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8463 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8464
8465 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8466 {
8467 assert(nbdchg < lp->ncols);
8468 bdind[nbdchg] = col->lpipos;
8469 lb[nbdchg] = newlb;
8470 ub[nbdchg] = newub;
8471 nbdchg++;
8472 col->flushedlb = newlb;
8473 col->flushedub = newub;
8474 }
8475 col->lbchanged = FALSE;
8476 col->ubchanged = FALSE;
8477 }
8478 }
8479 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8480 }
8481
8482 /* change objective values in LP */
8483 if( nobjchg > 0 )
8484 {
8485 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8486 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8487
8488 /* mark the LP unsolved */
8489 lp->solved = FALSE;
8490 lp->dualfeasible = FALSE;
8491 lp->dualchecked = FALSE;
8492 lp->lpobjval = SCIP_INVALID;
8494 }
8495
8496 /* change bounds in LP */
8497 if( nbdchg > 0 )
8498 {
8499 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8500 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8501
8502 /* mark the LP unsolved */
8503 lp->solved = FALSE;
8504 lp->primalfeasible = FALSE;
8505 lp->primalchecked = FALSE;
8506 lp->lpobjval = SCIP_INVALID;
8508 }
8509
8510 lp->nchgcols = 0;
8511
8512 /* free temporary memory */
8515 SCIPsetFreeBufferArray(set, &bdind);
8517 SCIPsetFreeBufferArray(set, &objind);
8518
8519 return SCIP_OKAY;
8520}
8521
8522/** applies all cached row side changes to the LP */
8523static
8525 SCIP_LP* lp, /**< current LP data */
8526 SCIP_SET* set /**< global SCIP settings */
8527 )
8528{
8529#ifndef NDEBUG
8530 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8531#endif
8532 SCIP_ROW* row;
8533 int* ind;
8534 SCIP_Real* lhs;
8535 SCIP_Real* rhs;
8536 SCIP_Real lpiinf;
8537 int i;
8538 int nchg;
8539
8540 assert(lp != NULL);
8541
8542 if( lp->nchgrows == 0 )
8543 return SCIP_OKAY;
8544
8545 /* get the solver's infinity value */
8546 lpiinf = SCIPlpiInfinity(lp->lpi);
8547
8548 /* get temporary memory for changes */
8552
8553 /* collect all cached left and right hand side changes */
8554 nchg = 0;
8555 for( i = 0; i < lp->nchgrows; ++i )
8556 {
8557 row = lp->chgrows[i];
8558 assert(row != NULL);
8559
8560 if( row->lpipos >= 0 )
8561 {
8562#ifndef NDEBUG
8563 /* do not check consistency of data with LPI in case of LPI=none */
8564 if( !lpinone )
8565 {
8566 SCIP_Real lpilhs;
8567 SCIP_Real lpirhs;
8568
8569 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8570 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8571 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8572 }
8573#endif
8574 if( row->lhschanged || row->rhschanged )
8575 {
8576 SCIP_Real newlhs;
8577 SCIP_Real newrhs;
8578
8579 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8580 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8581 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8582 {
8583 assert(nchg < lp->nrows);
8584 ind[nchg] = row->lpipos;
8585 lhs[nchg] = newlhs;
8586 rhs[nchg] = newrhs;
8587 nchg++;
8588 row->flushedlhs = newlhs;
8589 row->flushedrhs = newrhs;
8590 }
8591 row->lhschanged = FALSE;
8592 row->rhschanged = FALSE;
8593 }
8594 }
8595 }
8596
8597 /* change left and right hand sides in LP */
8598 if( nchg > 0 )
8599 {
8600 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8601 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8602
8603 /* mark the LP unsolved */
8604 lp->solved = FALSE;
8605 lp->primalfeasible = FALSE;
8606 lp->primalchecked = FALSE;
8607 lp->lpobjval = SCIP_INVALID;
8609 }
8610
8611 lp->nchgrows = 0;
8612
8613 /* free temporary memory */
8617
8618 return SCIP_OKAY;
8619}
8620
8621/** copy integrality information to the LP */
8622static
8624 SCIP_LP* lp, /**< current LP data */
8625 SCIP_SET* set /**< global SCIP settings */
8626 )
8627{
8628 int i;
8629 int nintegers;
8630 int* integerInfo;
8631 SCIP_VAR* var;
8632
8633 assert(lp != NULL);
8634
8635 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8636
8637 /* count total number of integralities */
8638 nintegers = 0;
8639
8640 for( i = 0; i < lp->ncols; ++i )
8641 {
8642 var = SCIPcolGetVar(lp->cols[i]);
8643 if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) )
8644 {
8645 integerInfo[i] = 1;
8646 ++nintegers;
8647 }
8648 else
8649 integerInfo[i] = 0;
8650 }
8651
8652 /* only pass integrality information if integer variables are present */
8653 if( nintegers > 0 )
8654 {
8655 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8656 }
8657 else
8658 {
8660 }
8661
8662 SCIPsetFreeBufferArray(set, &integerInfo);
8663
8664 /* mark integralities to be updated */
8666
8667 return SCIP_OKAY;
8668}
8669
8670/** applies all cached changes to the LP solver */
8672 SCIP_LP* lp, /**< current LP data */
8673 BMS_BLKMEM* blkmem, /**< block memory */
8674 SCIP_SET* set, /**< global SCIP settings */
8675 SCIP_PROB* prob, /**< problem data */
8676 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8677 )
8678{
8679 assert(lp != NULL);
8680 assert(blkmem != NULL);
8681
8682 SCIPsetDebugMsg(set, "flushing LP changes: old (%d cols, %d rows), nchgcols=%d, nchgrows=%d, firstchgcol=%d, firstchgrow=%d, new (%d cols, %d rows), flushed=%u\n",
8683 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8684
8685 if( !lp->flushed )
8686 {
8687 lp->flushdeletedcols = FALSE;
8688 lp->flushaddedcols = FALSE;
8689 lp->flushdeletedrows = FALSE;
8690 lp->flushaddedrows = FALSE;
8691
8693 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8696 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8697 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8698
8699 lp->flushed = TRUE;
8700
8701 checkLinks(lp);
8702 }
8703
8704 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8705 * we want to re-optimize the LP even if nothing else has changed */
8706 if( lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 && ! lpCutoffDisabled(set, prob) ) /*lint !e777*/
8707 {
8708 lp->solved = FALSE;
8710 }
8711
8712 assert(lp->nlpicols == lp->ncols);
8713 assert(lp->lpifirstchgcol == lp->nlpicols);
8714 assert(lp->nlpirows == lp->nrows);
8715 assert(lp->lpifirstchgrow == lp->nlpirows);
8716 assert(lp->nchgcols == 0);
8717 assert(lp->nchgrows == 0);
8718#ifndef NDEBUG
8719 {
8720 int ncols;
8721 int nrows;
8722
8723 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8724 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8725 assert(ncols == lp->ncols);
8726 assert(nrows == lp->nrows);
8727 }
8728#endif
8729
8730 return SCIP_OKAY;
8731}
8732
8733/** marks the LP to be flushed, even if the LP thinks it is not flushed */
8735 SCIP_LP* lp, /**< current LP data */
8736 SCIP_SET* set /**< global SCIP settings */
8737 )
8738{
8739#ifndef NDEBUG
8740 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8741#endif
8742 int i;
8743
8744 assert(lp != NULL);
8745
8746#ifndef NDEBUG
8747 /* check, if there are really no column or row deletions or coefficient changes left */
8748 while( lp->lpifirstchgcol < lp->nlpicols
8749 && lp->lpifirstchgcol < lp->ncols
8750 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8751 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8752 {
8753 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8754 lp->lpifirstchgcol++;
8755 }
8756 assert(lp->nlpicols == lp->lpifirstchgcol);
8757
8758 while( lp->lpifirstchgrow < lp->nlpirows
8759 && lp->lpifirstchgrow < lp->nrows
8760 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8761 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8762 {
8763 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8764 lp->lpifirstchgrow++;
8765 }
8766 assert(lp->nlpirows == lp->lpifirstchgrow);
8767#endif
8768
8769 lp->lpifirstchgcol = lp->nlpicols;
8770 lp->lpifirstchgrow = lp->nlpirows;
8771
8772 /* check, if there are really no column or row additions left */
8773 assert(lp->ncols == lp->nlpicols);
8774 assert(lp->nrows == lp->nlpirows);
8775
8776 /* mark the changed columns to be unchanged, and check, if this is really correct */
8777 for( i = 0; i < lp->nchgcols; ++i )
8778 {
8779 SCIP_COL* col;
8780
8781 col = lp->chgcols[i];
8782 assert(col != NULL);
8783 assert(col->var != NULL);
8785 assert(SCIPvarGetCol(col->var) == col);
8786
8787 if( col->lpipos >= 0 )
8788 {
8789#ifndef NDEBUG
8790 /* do not check consistency of data with LPI in case of LPI=none */
8791 if( !lpinone )
8792 {
8793 SCIP_Real lpiobj;
8794 SCIP_Real lpilb;
8795 SCIP_Real lpiub;
8796
8797 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8798 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8799 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8800 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8801 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8802 assert(col->flushedobj == col->obj); /*lint !e777*/
8803 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8804 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8805 }
8806#endif
8807 col->objchanged = FALSE;
8808 col->lbchanged = FALSE;
8809 col->ubchanged = FALSE;
8810 }
8811 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8812 }
8813 lp->nchgcols = 0;
8814
8815 /* mark the changed rows to be unchanged, and check, if this is really correct */
8816 for( i = 0; i < lp->nchgrows; ++i )
8817 {
8818 SCIP_ROW* row;
8819
8820 row = lp->chgrows[i];
8821 assert(row != NULL);
8822
8823 if( row->lpipos >= 0 )
8824 {
8825#ifndef NDEBUG
8826 /* do not check consistency of data with LPI in case of LPI=none */
8827 if( !lpinone )
8828 {
8829 SCIP_Real lpilhs;
8830 SCIP_Real lpirhs;
8831
8832 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8833 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8834 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8835 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8836 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8837 }
8838#endif
8839 row->lhschanged = FALSE;
8840 row->rhschanged = FALSE;
8841 }
8842 }
8843 lp->nchgrows = 0;
8844
8845 /* mark the LP to be flushed */
8846 lp->flushed = TRUE;
8847
8848 checkLinks(lp);
8849
8850 return SCIP_OKAY;
8851}
8852
8853
8854
8855
8856/*
8857 * LP methods
8858 */
8859
8860/** updates link data after addition of column */
8861static
8863 SCIP_COL* col, /**< LP column */
8864 SCIP_SET* set /**< global SCIP settings */
8865 )
8866{
8867 SCIP_ROW* row;
8868 int i;
8869 int pos;
8870
8871 assert(col != NULL);
8872 assert(col->lppos >= 0);
8873
8874 /* update column arrays of all linked rows */
8875 for( i = 0; i < col->len; ++i )
8876 {
8877 pos = col->linkpos[i];
8878 if( pos >= 0 )
8879 {
8880 row = col->rows[i];
8881 assert(row != NULL);
8882 assert(row->linkpos[pos] == i);
8883 assert(row->cols[pos] == col);
8884 assert(row->nlpcols <= pos && pos < row->len);
8885
8886 row->nlpcols++;
8887 rowSwapCoefs(row, pos, row->nlpcols-1);
8888 assert(row->cols[row->nlpcols-1] == col);
8889
8890 /* if no swap was necessary, mark lpcols to be unsorted */
8891 if( pos == row->nlpcols-1 )
8892 row->lpcolssorted = FALSE;
8893
8894 /* update norms */
8895 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8896 }
8897 }
8898}
8899
8900/** updates link data after addition of row */
8901static
8903 SCIP_ROW* row /**< LP row */
8904 )
8905{
8906 SCIP_COL* col;
8907 int i;
8908 int pos;
8909
8910 assert(row != NULL);
8911 assert(row->lppos >= 0);
8912
8913 /* update row arrays of all linked columns */
8914 for( i = 0; i < row->len; ++i )
8915 {
8916 pos = row->linkpos[i];
8917 if( pos >= 0 )
8918 {
8919 col = row->cols[i];
8920 assert(col != NULL);
8921 assert(col->linkpos[pos] == i);
8922 assert(col->rows[pos] == row);
8923 assert(col->nlprows <= pos && pos < col->len);
8924
8925 col->nlprows++;
8926 colSwapCoefs(col, pos, col->nlprows-1);
8927
8928 /* if no swap was necessary, mark lprows to be unsorted */
8929 if( pos == col->nlprows-1 )
8930 col->lprowssorted = FALSE;
8931 }
8932 }
8933}
8934
8935/** updates link data after removal of column */
8936static
8938 SCIP_COL* col, /**< LP column */
8939 SCIP_SET* set /**< global SCIP settings */
8940 )
8941{
8942 SCIP_ROW* row;
8943 int i;
8944 int pos;
8945
8946 assert(col != NULL);
8947 assert(col->lppos == -1);
8948
8949 /* update column arrays of all linked rows */
8950 for( i = 0; i < col->len; ++i )
8951 {
8952 pos = col->linkpos[i];
8953 if( pos >= 0 )
8954 {
8955 row = col->rows[i];
8956 assert(row != NULL);
8957 assert(row->linkpos[pos] == i);
8958 assert(row->cols[pos] == col);
8959 assert(0 <= pos && pos < row->nlpcols);
8960
8961 /* update norms */
8962 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8963
8964 row->nlpcols--;
8965 rowSwapCoefs(row, pos, row->nlpcols);
8966
8967 /* if no swap was necessary, mark nonlpcols to be unsorted */
8968 if( pos == row->nlpcols )
8969 row->nonlpcolssorted = FALSE;
8970 }
8971 }
8972}
8973
8974/** updates link data after removal of row */
8975static
8977 SCIP_ROW* row /**< LP row */
8978 )
8979{
8980 SCIP_COL* col;
8981 int i;
8982 int pos;
8983
8984 assert(row != NULL);
8985 assert(row->lppos == -1);
8986
8987 /* update row arrays of all linked columns */
8988 for( i = 0; i < row->len; ++i )
8989 {
8990 pos = row->linkpos[i];
8991 if( pos >= 0 )
8992 {
8993 col = row->cols[i];
8994 assert(col != NULL);
8995 assert(0 <= pos && pos < col->nlprows);
8996 assert(col->linkpos[pos] == i);
8997 assert(col->rows[pos] == row);
8998
8999 col->nlprows--;
9000 colSwapCoefs(col, pos, col->nlprows);
9001
9002 /* if no swap was necessary, mark lprows to be unsorted */
9003 if( pos == col->nlprows )
9004 col->nonlprowssorted = FALSE;
9005 }
9006 }
9007}
9008
9009static
9011 SCIP_LP* lp, /**< LP data object */
9012 int initsize /**< initial size of the arrays */
9013 )
9014{
9015 assert(lp != NULL);
9016 assert(lp->divechgsides == NULL);
9017 assert(lp->divechgsidetypes == NULL);
9018 assert(lp->divechgrows == NULL);
9019 assert(lp->ndivechgsides == 0);
9020 assert(lp->divechgsidessize == 0);
9021 assert(initsize > 0);
9022
9023 lp->divechgsidessize = initsize;
9027
9028 return SCIP_OKAY;
9029}
9030
9031static
9033 SCIP_LP* lp, /**< LP data object */
9034 int minsize, /**< minimal number of elements */
9035 SCIP_Real growfact /**< growing factor */
9036 )
9037{
9038 assert(lp != NULL);
9039 assert(lp->divechgsides != NULL);
9040 assert(lp->divechgsidetypes != NULL);
9041 assert(lp->divechgrows != NULL);
9042 assert(lp->ndivechgsides > 0);
9043 assert(lp->divechgsidessize > 0);
9044 assert(minsize > 0);
9045
9046 if( minsize <= lp->divechgsidessize )
9047 return SCIP_OKAY;
9048
9049 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9053
9054 return SCIP_OKAY;
9055}
9056
9057static
9059 SCIP_LP* lp /**< LP data object */
9060 )
9061{
9062 assert(lp != NULL);
9063 assert(lp->divechgsides != NULL);
9064 assert(lp->divechgsidetypes != NULL);
9065 assert(lp->divechgrows != NULL);
9066 assert(lp->ndivechgsides == 0);
9067 assert(lp->divechgsidessize > 0);
9068
9072 lp->divechgsidessize = 0;
9073}
9074
9075#define DIVESTACKINITSIZE 100
9076
9077/** creates empty LP data object */
9079 SCIP_LP** lp, /**< pointer to LP data object */
9080 SCIP_SET* set, /**< global SCIP settings */
9081 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
9082 SCIP_STAT* stat, /**< problem statistics */
9083 const char* name /**< problem name */
9084 )
9085{
9086 SCIP_Bool success;
9087
9088 assert(lp != NULL);
9089 assert(set != NULL);
9090 assert(stat != NULL);
9091 assert(name != NULL);
9092
9094
9095 /* open LP Solver interface */
9096 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9097
9098 (*lp)->lpicols = NULL;
9099 (*lp)->lpirows = NULL;
9100 (*lp)->chgcols = NULL;
9101 (*lp)->chgrows = NULL;
9102 (*lp)->cols = NULL;
9103 (*lp)->soldirection = NULL;
9104 (*lp)->lazycols = NULL;
9105 (*lp)->rows = NULL;
9106 (*lp)->lpobjval = 0.0;
9107 (*lp)->glbpseudoobjval = 0.0;
9108 (*lp)->relglbpseudoobjval = 0.0;
9109 (*lp)->glbpseudoobjvalid = TRUE;
9110 (*lp)->glbpseudoobjvalinf = 0;
9111 (*lp)->pseudoobjval = 0.0;
9112 (*lp)->relpseudoobjval = 0.0;
9113 (*lp)->pseudoobjvalid = TRUE;
9114 (*lp)->pseudoobjvalinf = 0;
9115 (*lp)->looseobjval = 0.0;
9116 (*lp)->rellooseobjval = 0.0;
9117 (*lp)->looseobjvalid = TRUE;
9118 (*lp)->looseobjvalinf = 0;
9119 (*lp)->nloosevars = 0;
9120 (*lp)->rootlpobjval = SCIP_INVALID;
9121 (*lp)->rootlooseobjval = SCIP_INVALID;
9122 (*lp)->cutoffbound = SCIPsetInfinity(set);
9123 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9124 SCIPlpResetFeastol(*lp, set);
9125 (*lp)->validdegeneracylp = -1;
9126 (*lp)->objsqrnorm = 0.0;
9127 (*lp)->objsumnorm = 0.0;
9128 (*lp)->lpicolssize = 0;
9129 (*lp)->nlpicols = 0;
9130 (*lp)->lpirowssize = 0;
9131 (*lp)->nlpirows = 0;
9132 (*lp)->lpifirstchgcol = 0;
9133 (*lp)->lpifirstchgrow = 0;
9134 (*lp)->colssize = 0;
9135 (*lp)->soldirectionsize = 0;
9136 (*lp)->ncols = 0;
9137 (*lp)->lazycolssize = 0;
9138 (*lp)->nlazycols = 0;
9139 (*lp)->rowssize = 0;
9140 (*lp)->nrows = 0;
9141 (*lp)->chgcolssize = 0;
9142 (*lp)->nchgcols = 0;
9143 (*lp)->chgrowssize = 0;
9144 (*lp)->nchgrows = 0;
9145 (*lp)->firstnewcol = 0;
9146 (*lp)->firstnewrow = 0;
9147 (*lp)->nremovablecols = 0;
9148 (*lp)->nremovablerows = 0;
9149 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9150 (*lp)->validfarkaslp = -1;
9151 (*lp)->validsoldirlp = -1;
9152 (*lp)->validsoldirsol = NULL;
9153 (*lp)->objsqrnormunreliable = FALSE;
9154 (*lp)->flushdeletedcols = FALSE;
9155 (*lp)->flushaddedcols = FALSE;
9156 (*lp)->flushdeletedrows = FALSE;
9157 (*lp)->flushaddedrows = FALSE;
9158 (*lp)->updateintegrality = TRUE;
9159 (*lp)->flushed = TRUE;
9160 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9161 (*lp)->solved = TRUE;
9162 (*lp)->primalfeasible = TRUE;
9163 (*lp)->primalchecked = TRUE;
9164 (*lp)->dualfeasible = TRUE;
9165 (*lp)->dualchecked = TRUE;
9166 (*lp)->solisbasic = FALSE;
9167 (*lp)->rootlpisrelax = TRUE;
9168 (*lp)->isrelax = TRUE;
9169 (*lp)->installing = FALSE;
9170 (*lp)->strongbranching = FALSE;
9171 (*lp)->strongbranchprobing = FALSE;
9172 (*lp)->probing = FALSE;
9173 (*lp)->diving = FALSE;
9174 (*lp)->divingobjchg = FALSE;
9175 (*lp)->divinglazyapplied = FALSE;
9176 (*lp)->divelpistate = NULL;
9177 (*lp)->divelpwasprimfeas = TRUE;
9178 (*lp)->divelpwasprimchecked = TRUE;
9179 (*lp)->divelpwasdualfeas = TRUE;
9180 (*lp)->divelpwasdualchecked = TRUE;
9181 (*lp)->divechgsides = NULL;
9182 (*lp)->divechgsidetypes = NULL;
9183 (*lp)->divechgrows = NULL;
9184 (*lp)->ndivechgsides = 0;
9185 (*lp)->divechgsidessize = 0;
9186 (*lp)->ndivingrows = 0;
9187 (*lp)->divinglpiitlim = INT_MAX;
9188 (*lp)->resolvelperror = FALSE;
9189 (*lp)->divenolddomchgs = 0;
9190 (*lp)->adjustlpval = FALSE;
9191 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9192 (*lp)->lpifeastol = (*lp)->feastol;
9193 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9194 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9195 (*lp)->lpifromscratch = FALSE;
9196 (*lp)->lpifastmip = set->lp_fastmip;
9197 (*lp)->lpiscaling = set->lp_scaling;
9198 (*lp)->lpipresolving = set->lp_presolving;
9199 (*lp)->lpilpinfo = set->disp_lpinfo;
9200 (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9201 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9202 (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9203 (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9204 (*lp)->lpimarkowitz = set->lp_markowitz;
9205 (*lp)->lpiitlim = INT_MAX;
9206 (*lp)->lpipricing = SCIP_PRICING_AUTO;
9207 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9208 (*lp)->lpithreads = set->lp_threads;
9209 (*lp)->lpitiming = (int) set->time_clocktype;
9210 (*lp)->lpirandomseed = set->random_randomseed;
9211 (*lp)->storedsolvals = NULL;
9212
9213 /* allocate arrays for diving */
9215
9216 /* set default parameters in LP solver */
9217 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9218 if( !success )
9219 {
9220 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9221 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9223 }
9224 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9225 (*lp)->lpihasfeastol = success;
9226 if( !success )
9227 {
9228 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9229 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9231 }
9232 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9233 (*lp)->lpihasdualfeastol = success;
9234 if( !success )
9235 {
9236 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9237 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9239 }
9240 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9241 (*lp)->lpihasbarrierconvtol = success;
9242 if( !success )
9243 {
9244 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9245 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9247 }
9248 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9249 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9250 (*lp)->lpihasfastmip = success;
9251 if( !success )
9252 {
9253 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9254 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9256 }
9257 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9258 (*lp)->lpihasscaling = success;
9259 if( !success )
9260 {
9261 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9262 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9264 }
9265 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9266 (*lp)->lpihaspresolving = success;
9267 if( !success )
9268 {
9269 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9270 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9272 }
9273 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9274 if( !success )
9275 {
9276 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9277 "LP Solver <%s>: clock type cannot be set\n",
9279 }
9280 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9281 if( !success )
9282 {
9283 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9284 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9286 }
9287 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9288 if( !success )
9289 {
9290 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9291 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9293 }
9294 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9295 if( !success )
9296 {
9297 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9298 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9300 }
9301 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9302 (*lp)->lpihasrowrep = success;
9303 if( !success )
9304 {
9305 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9306 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9308 }
9309 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9310 (*lp)->lpihaspolishing = success;
9311 if( !success )
9312 {
9313 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9314 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9316 }
9317 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9318 (*lp)->lpihasrefactor = success;
9319 if( !success )
9320 {
9321 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9322 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9324 }
9325 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9326 if( !success )
9327 {
9328 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9329 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9331 }
9332 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9333 if( !success )
9334 {
9335 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9336 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9338 }
9339 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9340 if( !success )
9341 {
9342 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9343 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9345 }
9346 /* keep the default LP random seed if this parameter is set to 0 (current default) */
9347 if( (*lp)->lpirandomseed != 0 )
9348 {
9349 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9350 if( !success )
9351 {
9352 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9353 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9355 }
9356 }
9357
9358 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9359 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9360 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9361 {
9362 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9364 }
9365
9366 return SCIP_OKAY;
9367}
9368
9369/** frees LP data object */
9371 SCIP_LP** lp, /**< pointer to LP data object */
9372 BMS_BLKMEM* blkmem, /**< block memory */
9373 SCIP_SET* set, /**< global SCIP settings */
9374 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9375 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9376 )
9377{
9378 int i;
9379
9380 assert(lp != NULL);
9381 assert(*lp != NULL);
9382
9383 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9384
9386
9387 /* release LPI rows */
9388 for( i = 0; i < (*lp)->nlpirows; ++i )
9389 {
9390 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9391 }
9392
9393 if( (*lp)->lpi != NULL )
9394 {
9395 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9396 }
9397
9398 BMSfreeMemoryNull(&(*lp)->storedsolvals);
9399 BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9400 BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9401 BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9402 BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9403 BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9404 BMSfreeMemoryArrayNull(&(*lp)->cols);
9405 BMSfreeMemoryArrayNull(&(*lp)->rows);
9406 BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9407 BMSfreeMemory(lp);
9408
9409 return SCIP_OKAY;
9410}
9411
9412/** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9413 * changes to the LP solver
9414 */
9416 SCIP_LP* lp, /**< LP data */
9417 BMS_BLKMEM* blkmem, /**< block memory */
9418 SCIP_SET* set, /**< global SCIP settings */
9419 SCIP_PROB* prob, /**< problem data */
9420 SCIP_STAT* stat, /**< problem statistics */
9421 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9422 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9423 )
9424{
9425 assert(stat != NULL);
9426
9427 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9428 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9429
9430 /* mark the empty LP to be solved */
9432 lp->lpobjval = 0.0;
9433 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9434 lp->validfarkaslp = -1;
9435 lp->validdegeneracylp = -1;
9436 lp->validsoldirlp = -1;
9437 lp->validsoldirsol = NULL;
9438 lp->solved = TRUE;
9439 lp->primalfeasible = TRUE;
9440 lp->primalchecked = TRUE;
9441 lp->dualfeasible = TRUE;
9442 lp->dualchecked = TRUE;
9443 lp->solisbasic = FALSE;
9445
9446 return SCIP_OKAY;
9447}
9448
9449/** adds a column to the LP */
9451 SCIP_LP* lp, /**< LP data */
9452 SCIP_SET* set, /**< global SCIP settings */
9453 SCIP_COL* col, /**< LP column */
9454 int depth /**< depth in the tree where the column addition is performed */
9455 )
9456{
9457 assert(lp != NULL);
9458 assert(!lp->diving);
9459 assert(col != NULL);
9460 assert(col->len == 0 || col->rows != NULL);
9461 assert(col->lppos == -1);
9462 assert(col->var != NULL);
9464 assert(SCIPvarGetCol(col->var) == col);
9465 assert(SCIPvarIsIntegral(col->var) == col->integral);
9466
9467 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9468#ifdef SCIP_DEBUG
9469 {
9470 int i;
9471 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9472 for( i = 0; i < col->len; ++i )
9473 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9475 }
9476#endif
9477
9478 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9479 lp->cols[lp->ncols] = col;
9480 col->lppos = lp->ncols;
9481 col->lpdepth = depth;
9482 col->age = 0;
9483 lp->ncols++;
9484 if( col->removable )
9485 lp->nremovablecols++;
9486
9487 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9488 {
9490 lp->lazycols[lp->nlazycols] = col;
9491 lp->nlazycols++;
9492 }
9493
9494 /* mark the current LP unflushed */
9495 lp->flushed = FALSE;
9496
9497 /* update column arrays of all linked rows */
9498 colUpdateAddLP(col, set);
9499
9500 /* update the objective function vector norms */
9501 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9502
9503 checkLinks(lp);
9504
9505 return SCIP_OKAY;
9506}
9507
9508/** adds a row to the LP and captures it */
9510 SCIP_LP* lp, /**< LP data */
9511 BMS_BLKMEM* blkmem, /**< block memory buffers */
9512 SCIP_SET* set, /**< global SCIP settings */
9513 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9514 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9515 SCIP_ROW* row, /**< LP row */
9516 int depth /**< depth in the tree where the row addition is performed */
9517 )
9518{
9519 assert(lp != NULL);
9520 assert(row != NULL);
9521 assert(row->len == 0 || row->cols != NULL);
9522 assert(row->lppos == -1);
9523
9524 SCIProwCapture(row);
9525 SCIProwLock(row);
9526
9527 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9528#ifdef SCIP_DEBUG
9529 {
9530 int i;
9531 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs);
9532 for( i = 0; i < row->len; ++i )
9533 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9534 if( !SCIPsetIsZero(set, row->constant) )
9535 SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9536 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9537 }
9538#endif
9539
9540 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9541 lp->rows[lp->nrows] = row;
9542 row->lppos = lp->nrows;
9543 row->lpdepth = depth;
9544 row->age = 0;
9545 lp->nrows++;
9546 if( row->removable )
9547 lp->nremovablerows++;
9548
9549 /* mark the current LP unflushed */
9550 lp->flushed = FALSE;
9551
9552 /* update row arrays of all linked columns */
9553 rowUpdateAddLP(row);
9554
9555 checkLinks(lp);
9556
9557 rowCalcNorms(row, set);
9558
9559 /* check, if row addition to LP events are tracked
9560 * if so, issue ROWADDEDLP event
9561 */
9562 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9563 {
9564 SCIP_EVENT* event;
9565
9566 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9567 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9568 }
9569
9570 return SCIP_OKAY;
9571}
9572
9573
9574#ifndef NDEBUG
9575/** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9576 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9577 * the lazycols array
9578 */
9579static
9581 SCIP_LP* lp, /**< LP data */
9582 SCIP_SET* set /**< global SCIP settings */
9583 )
9584{
9585 SCIP_Bool contained;
9586 int c;
9587 int i;
9588
9589 assert(lp != NULL);
9590
9591 /* check if each column in the lazy column array has a counter part in the column array */
9592 for( i = 0; i < lp->nlazycols; ++i )
9593 {
9594 /* check if each lazy column has at least on lazy bound */
9595 assert(lp->lazycols[i] != NULL);
9596 assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9597
9598 contained = FALSE;
9599 for( c = 0; c < lp->ncols; ++c )
9600 {
9601 if( lp->lazycols[i] == lp->cols[c] )
9602 {
9603 assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9604 contained = TRUE;
9605 }
9606 }
9607 assert(contained);
9608 }
9609
9610 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9611 * array */
9612 for( c = 0; c < lp->ncols; ++c )
9613 {
9614 contained = FALSE;
9615 assert(lp->cols[c] != NULL);
9616
9617 for( i = 0; i < lp->nlazycols; ++i )
9618 {
9619 if( lp->lazycols[i] == lp->cols[c] )
9620 {
9621 contained = TRUE;
9622 }
9623 }
9624
9625 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9626 }
9627}
9628#else
9629#define checkLazyColArray(lp, set) /**/
9630#endif
9631
9632/** removes all columns after the given number of cols from the LP */
9634 SCIP_LP* lp, /**< LP data */
9635 SCIP_SET* set, /**< global SCIP settings */
9636 int newncols /**< new number of columns in the LP */
9637 )
9638{
9639 SCIP_COL* col;
9640 int c;
9641
9642 assert(lp != NULL);
9643
9644 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9645 assert(0 <= newncols);
9646 assert(newncols <= lp->ncols);
9647
9648 if( newncols < lp->ncols )
9649 {
9650 assert(!lp->diving);
9651
9652 for( c = lp->ncols-1; c >= newncols; --c )
9653 {
9654 col = lp->cols[c];
9655 assert(col != NULL);
9656 assert(col->len == 0 || col->rows != NULL);
9657 assert(col->var != NULL);
9659 assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9660 assert(col->lppos == c);
9661
9662 /* mark column to be removed from the LP */
9663 col->lppos = -1;
9664 col->lpdepth = -1;
9665 lp->ncols--;
9666
9667 /* count removable columns */
9668 if( col->removable )
9669 lp->nremovablecols--;
9670
9671 /* update column arrays of all linked rows */
9672 colUpdateDelLP(col, set);
9673
9674 /* update the objective function vector norms */
9675 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9676 }
9677 assert(lp->ncols == newncols);
9678 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9679
9680 /* remove columns which are deleted from the lazy column array */
9681 c = 0;
9682 while( c < lp->nlazycols )
9683 {
9684 if( lp->lazycols[c]->lppos < 0 )
9685 {
9686 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9687 lp->nlazycols--;
9688 }
9689 else
9690 c++;
9691 }
9692
9693 /* mark the current LP unflushed */
9694 lp->flushed = FALSE;
9695
9697 checkLinks(lp);
9698 }
9699 assert(lp->nremovablecols <= lp->ncols);
9700
9701 return SCIP_OKAY;
9702}
9703
9704/** removes and releases all rows after the given number of rows from the LP */
9706 SCIP_LP* lp, /**< LP data */
9707 BMS_BLKMEM* blkmem, /**< block memory */
9708 SCIP_SET* set, /**< global SCIP settings */
9709 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9710 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9711 int newnrows /**< new number of rows in the LP */
9712 )
9713{
9714 SCIP_ROW* row;
9715 int r;
9716
9717 assert(lp != NULL);
9718 assert(0 <= newnrows && newnrows <= lp->nrows);
9719
9720 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9721 if( newnrows < lp->nrows )
9722 {
9723 for( r = lp->nrows-1; r >= newnrows; --r )
9724 {
9725 row = lp->rows[r];
9726 assert(row != NULL);
9727 assert(row->len == 0 || row->cols != NULL);
9728 assert(row->lppos == r);
9729
9730 /* mark row to be removed from the LP */
9731 row->lppos = -1;
9732 row->lpdepth = -1;
9733 lp->nrows--;
9734
9735 /* count removable rows */
9736 if( row->removable )
9737 lp->nremovablerows--;
9738
9739 /* update row arrays of all linked columns */
9740 rowUpdateDelLP(row);
9741
9742 SCIProwUnlock(lp->rows[r]);
9743
9744 /* check, if row deletion events are tracked
9745 * if so, issue ROWDELETEDLP event
9746 */
9747 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9748 {
9749 SCIP_EVENT* event;
9750
9751 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9752 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9753 }
9754
9755 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9756 }
9757 assert(lp->nrows == newnrows);
9758 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9759
9760 /* mark the current LP unflushed */
9761 lp->flushed = FALSE;
9762
9763 checkLinks(lp);
9764 }
9765 assert(lp->nremovablerows <= lp->nrows);
9766
9767 return SCIP_OKAY;
9768}
9769
9770/** removes all columns and rows from LP, releases all rows */
9772 SCIP_LP* lp, /**< LP data */
9773 BMS_BLKMEM* blkmem, /**< block memory */
9774 SCIP_SET* set, /**< global SCIP settings */
9775 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9776 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9777 )
9778{
9779 assert(lp != NULL);
9780 assert(!lp->diving);
9781
9782 SCIPsetDebugMsg(set, "clearing LP\n");
9783 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9784 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9785
9786 return SCIP_OKAY;
9787}
9788
9789/** remembers number of columns and rows to track the newly added ones */
9791 SCIP_LP* lp /**< current LP data */
9792 )
9793{
9794 assert(lp != NULL);
9795 assert(!lp->diving);
9796
9797 lp->firstnewrow = lp->nrows;
9798 lp->firstnewcol = lp->ncols;
9799}
9800
9801/** sets the remembered number of columns and rows to the given values */
9803 SCIP_LP* lp, /**< current LP data */
9804 int nrows, /**< number of rows to set the size marker to */
9805 int ncols /**< number of columns to set the size marker to */
9806 )
9807{
9808 assert(lp != NULL);
9809 assert(!lp->diving);
9810
9811 lp->firstnewrow = nrows;
9812 lp->firstnewcol = ncols;
9813}
9814
9815/** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9817 SCIP_LP* lp, /**< LP data */
9818 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9819 )
9820{
9821 assert(lp != NULL);
9822 assert(lp->flushed);
9823 assert(lp->solved);
9824 assert(lp->solisbasic);
9825 assert(basisind != NULL);
9826
9827 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9828
9829 return SCIP_OKAY;
9830}
9831
9832/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9834 SCIP_LP* lp, /**< LP data */
9835 int* cstat, /**< array to store column basis status, or NULL */
9836 int* rstat /**< array to store row basis status, or NULL */
9837 )
9838{
9839 assert(lp != NULL);
9840 assert(lp->flushed);
9841 assert(lp->solved);
9842 assert(lp->solisbasic);
9843
9844 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9845
9846 return SCIP_OKAY;
9847}
9848
9849/** gets a row from the inverse basis matrix B^-1 */
9851 SCIP_LP* lp, /**< LP data */
9852 int r, /**< row number */
9853 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9854 int* inds, /**< array to store the non-zero indices, or NULL */
9855 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9856 * (-1: if we do not store sparsity informations) */
9857 )
9858{
9859 assert(lp != NULL);
9860 assert(lp->flushed);
9861 assert(lp->solved);
9862 assert(lp->solisbasic);
9863 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9864 assert(coef != NULL);
9865
9866 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9867
9868 return SCIP_OKAY;
9869}
9870
9871/** gets a column from the inverse basis matrix B^-1 */
9873 SCIP_LP* lp, /**< LP data */
9874 int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9875 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9876 * to get the array which links the B^-1 column numbers to the row and
9877 * column numbers of the LP! c must be between 0 and nrows-1, since the
9878 * basis has the size nrows * nrows */
9879 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9880 int* inds, /**< array to store the non-zero indices, or NULL */
9881 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9882 * (-1: if we do not store sparsity informations) */
9883 )
9884{
9885 assert(lp != NULL);
9886 assert(lp->flushed);
9887 assert(lp->solved);
9888 assert(lp->solisbasic);
9889 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9890 assert(coef != NULL);
9891
9892 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9893
9894 return SCIP_OKAY;
9895}
9896
9897/** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9899 SCIP_LP* lp, /**< LP data */
9900 int r, /**< row number */
9901 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9902 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9903 int* inds, /**< array to store the non-zero indices, or NULL */
9904 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9905 * (-1: if we do not store sparsity informations) */
9906 )
9907{
9908 assert(lp != NULL);
9909 assert(lp->flushed);
9910 assert(lp->solved);
9911 assert(lp->solisbasic);
9912 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9913 assert(coef != NULL);
9914
9915 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9916
9917 return SCIP_OKAY;
9918}
9919
9920/** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9921 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9922 */
9924 SCIP_LP* lp, /**< LP data */
9925 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9926 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9927 int* inds, /**< array to store the non-zero indices, or NULL */
9928 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9929 * (-1: if we do not store sparsity informations) */
9930 )
9931{
9932 assert(lp != NULL);
9933 assert(lp->flushed);
9934 assert(lp->solved);
9935 assert(lp->solisbasic);
9936 assert(0 <= c && c < lp->ncols);
9937 assert(coef != NULL);
9938
9939 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9940
9941 return SCIP_OKAY;
9942}
9943
9944/** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9945 * LP row are swapped in the summation
9946 */
9948 SCIP_LP* lp, /**< LP data */
9949 SCIP_SET* set, /**< global SCIP settings */
9950 SCIP_PROB* prob, /**< problem data */
9951 SCIP_Real* weights, /**< row weights in row summation */
9952 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9953 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9954 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9955 )
9956{
9957 SCIP_ROW* row;
9958 int r;
9959 int i;
9960 int idx;
9961 SCIP_Bool lhsinfinite;
9962 SCIP_Bool rhsinfinite;
9963
9964 assert(lp != NULL);
9965 assert(prob != NULL);
9966 assert(weights != NULL);
9967 assert(sumcoef != NULL);
9968 assert(sumlhs != NULL);
9969 assert(sumrhs != NULL);
9970
9971 /**@todo test, if a column based summation is faster */
9972
9973 SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9974 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9975 *sumlhs = 0.0;
9976 *sumrhs = 0.0;
9977 lhsinfinite = FALSE;
9978 rhsinfinite = FALSE;
9979 for( r = 0; r < lp->nrows; ++r )
9980 {
9981 if( !SCIPsetIsZero(set, weights[r]) )
9982 {
9983 row = lp->rows[r];
9984 assert(row != NULL);
9985 assert(row->len == 0 || row->cols != NULL);
9986 assert(row->len == 0 || row->cols_index != NULL);
9987 assert(row->len == 0 || row->vals != NULL);
9988
9989 /* add the row coefficients to the sum */
9990 for( i = 0; i < row->len; ++i )
9991 {
9992 assert(row->cols[i] != NULL);
9993 assert(row->cols[i]->var != NULL);
9994 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9995 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9996 assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9997 idx = row->cols[i]->var_probindex;
9998 assert(0 <= idx && idx < prob->nvars);
9999 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
10000 }
10001
10002 /* add the row sides to the sum, depending on the sign of the weight */
10003 if( weights[r] > 0.0 )
10004 {
10005 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10006 if( !lhsinfinite )
10007 (*sumlhs) += weights[r] * (row->lhs - row->constant);
10008 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10009 if( !rhsinfinite )
10010 (*sumrhs) += weights[r] * (row->rhs - row->constant);
10011 }
10012 else
10013 {
10014 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10015 if( !lhsinfinite )
10016 (*sumlhs) += weights[r] * (row->rhs - row->constant);
10017 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10018 if( !rhsinfinite )
10019 (*sumrhs) += weights[r] * (row->lhs - row->constant);
10020 }
10021 }
10022 }
10023
10024 if( lhsinfinite )
10025 *sumlhs = -SCIPsetInfinity(set);
10026 if( rhsinfinite )
10027 *sumrhs = SCIPsetInfinity(set);
10028
10029 return SCIP_OKAY;
10030}
10031
10032/** stores LP state (like basis information) into LP state object */
10034 SCIP_LP* lp, /**< LP data */
10035 BMS_BLKMEM* blkmem, /**< block memory */
10036 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10037 )
10038{
10039 assert(lp != NULL);
10040 assert(lp->flushed);
10041 assert(lp->solved);
10042 assert(blkmem != NULL);
10043 assert(lpistate != NULL);
10044
10045 /* check whether there is no lp */
10046 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10047 *lpistate = NULL;
10048 else
10049 {
10050 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10051 }
10052
10053 return SCIP_OKAY;
10054}
10055
10056/** loads LP state (like basis information) into solver */
10058 SCIP_LP* lp, /**< LP data */
10059 BMS_BLKMEM* blkmem, /**< block memory */
10060 SCIP_SET* set, /**< global SCIP settings */
10061 SCIP_PROB* prob, /**< problem data */
10062 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10063 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
10064 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
10065 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */
10066 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */
10067 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */
10068 )
10069{
10070 assert(lp != NULL);
10071 assert(blkmem != NULL);
10072
10073 /* flush changes to the LP solver */
10074 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10075 assert(lp->flushed);
10076
10077 if( lp->solved && lp->solisbasic )
10078 return SCIP_OKAY;
10079
10080 /* set LPI state in the LP solver */
10081 if( lpistate == NULL )
10082 lp->solisbasic = FALSE;
10083 else
10084 {
10085 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10086 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10087 }
10088 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10089 * flushed and solved, also, e.g., when we hit the iteration limit
10090 */
10091 lp->primalfeasible = wasprimfeas;
10092 lp->primalchecked = wasprimchecked;
10093 lp->dualfeasible = wasdualfeas;
10094 lp->dualchecked = wasdualchecked;
10095
10096 return SCIP_OKAY;
10097}
10098
10099/** frees LP state information */
10101 SCIP_LP* lp, /**< LP data */
10102 BMS_BLKMEM* blkmem, /**< block memory */
10103 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10104 )
10105{
10106 assert(lp != NULL);
10107
10108 if( *lpistate != NULL )
10109 {
10110 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10111 }
10112
10113 return SCIP_OKAY;
10114}
10115
10116/** interrupts the currently ongoing lp solve, or disables the interrupt */
10118 SCIP_LP* lp, /**< LP data */
10119 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10120 )
10121{
10122 assert(lp != NULL);
10123
10124 if( lp->lpi == NULL )
10125 return SCIP_OKAY;
10126
10127 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10128
10129 return SCIP_OKAY;
10130}
10131
10132/** stores pricing norms into LP norms object */
10134 SCIP_LP* lp, /**< LP data */
10135 BMS_BLKMEM* blkmem, /**< block memory */
10136 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10137 )
10138{
10139 assert(lp != NULL);
10140 assert(lp->flushed);
10141 assert(lp->solved);
10142 assert(blkmem != NULL);
10143 assert(lpinorms != NULL);
10144
10145 /* check whether there is no lp */
10146 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10147 *lpinorms = NULL;
10148 else
10149 {
10150 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10151 }
10152
10153 return SCIP_OKAY;
10154}
10155
10156/** loads pricing norms from LP norms object into solver */
10158 SCIP_LP* lp, /**< LP data */
10159 BMS_BLKMEM* blkmem, /**< block memory */
10160 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
10161 )
10162{
10163 assert(lp != NULL);
10164 assert(blkmem != NULL);
10165 assert(lp->flushed);
10166
10167 /* set LPI norms in the LP solver */
10168 if( lpinorms != NULL )
10169 {
10170 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10171 }
10172
10173 return SCIP_OKAY;
10174}
10175
10176/** frees pricing norms information */
10178 SCIP_LP* lp, /**< LP data */
10179 BMS_BLKMEM* blkmem, /**< block memory */
10180 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10181 )
10182{
10183 assert(lp != NULL);
10184
10185 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10186
10187 return SCIP_OKAY;
10188}
10189
10190/** return the current cutoff bound of the lp */
10192 SCIP_LP* lp /**< current LP data */
10193 )
10194{
10195 assert(lp != NULL);
10196
10197 return lp->cutoffbound;
10198}
10199
10200/** sets the upper objective limit of the LP solver */
10202 SCIP_LP* lp, /**< current LP data */
10203 SCIP_SET* set, /**< global SCIP settings */
10204 SCIP_PROB* prob, /**< problem data */
10205 SCIP_Real cutoffbound /**< new upper objective limit */
10206 )
10207{
10208 assert(lp != NULL);
10209
10210 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10211
10212 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10213 * in SCIPendDive())
10214 */
10215 if( SCIPlpDivingObjChanged(lp) )
10216 {
10217 assert(SCIPsetIsInfinity(set, lp->cutoffbound));
10218 return SCIP_OKAY;
10219 }
10220
10221 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10222 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10223 {
10224 /* mark the current solution invalid */
10225 lp->solved = FALSE;
10226 lp->lpobjval = SCIP_INVALID;
10228 }
10229 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10230 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10231 */
10233 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10234 {
10235 assert(lp->flushed);
10236 assert(lp->solved);
10238 }
10239
10240 lp->cutoffbound = cutoffbound;
10241
10242 return SCIP_OKAY;
10243}
10244
10245/** gets current primal feasibility tolerance of LP solver */
10247 SCIP_LP* lp /**< current LP data */
10248 )
10249{
10250 assert(lp != NULL);
10251
10252 return lp->feastol;
10253}
10254
10255/** sets primal feasibility tolerance of LP solver */
10257 SCIP_LP* lp, /**< current LP data */
10258 SCIP_SET* set, /**< global SCIP settings */
10259 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */
10260 )
10261{
10262 assert(lp != NULL);
10263 assert(newfeastol > 0.0);
10264
10265 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10266
10267 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10268 if( newfeastol < lp->feastol )
10269 {
10270 lp->solved = FALSE;
10272 }
10273
10274 lp->feastol = newfeastol;
10275}
10276
10277/** resets primal feasibility tolerance of LP solver
10278 *
10279 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10280 */
10282 SCIP_LP* lp, /**< current LP data */
10283 SCIP_SET* set /**< global SCIP settings */
10284 )
10285{
10286 assert(lp != NULL);
10287
10288 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10289
10290 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10292 else
10294}
10295
10296/** returns the name of the given LP algorithm */
10297static
10298const char* lpalgoName(
10299 SCIP_LPALGO lpalgo /**< LP algorithm */
10300 )
10301{
10302 switch( lpalgo )
10303 {
10305 return "primal simplex";
10307 return "dual simplex";
10309 return "barrier";
10311 return "barrier/crossover";
10312 default:
10313 SCIPerrorMessage("invalid LP algorithm\n");
10314 SCIPABORT();
10315 return "invalid"; /*lint !e527*/
10316 }
10317}
10318
10319/** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10320static
10322 SCIP_LP* lp, /**< current LP data */
10323 SCIP_SET* set, /**< global SCIP settings */
10324 SCIP_STAT* stat, /**< problem statistics */
10325 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10326 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10327 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10328 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10329 )
10330{
10331 SCIP_Real timedelta;
10332 SCIP_RETCODE retcode;
10333 int iterations;
10334
10335 assert(lp != NULL);
10336 assert(lp->flushed);
10337 assert(set != NULL);
10338 assert(stat != NULL);
10339 assert(lperror != NULL);
10340
10341 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10342 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10343
10344 *lperror = FALSE;
10345
10346#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10347 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10348 {
10349 char fname[SCIP_MAXSTRLEN];
10350 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10351 SCIP_CALL( SCIPlpWrite(lp, fname) );
10352 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10353 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10355 }
10356#endif
10357
10358 /* start timing */
10359 if( lp->diving || lp->probing )
10360 {
10361 if( lp->strongbranchprobing )
10363 else
10365
10366 timedelta = 0.0; /* unused for diving or probing */
10367 }
10368 else
10369 {
10371 timedelta = -SCIPclockGetTime(stat->primallptime);
10372 }
10373
10374 /* if this is a call to resolve an instable LP, collect time */
10375 if( instable )
10376 {
10378 }
10379
10380 /* call primal simplex */
10381 retcode = SCIPlpiSolvePrimal(lp->lpi);
10382 if( retcode == SCIP_LPERROR )
10383 {
10384 *lperror = TRUE;
10385 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10386 }
10387 else
10388 {
10389 SCIP_CALL( retcode );
10390 }
10392 lp->solisbasic = TRUE;
10393
10394 /* stop timing */
10395 if( lp->diving || lp->probing )
10396 {
10397 if( lp->strongbranchprobing )
10399 else
10401 }
10402 else
10403 {
10404 timedelta += SCIPclockGetTime(stat->primallptime);
10406 }
10407
10408 if ( instable )
10409 {
10411 }
10412
10413 /* count number of iterations */
10414 SCIPstatIncrement(stat, set, lpcount);
10415 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10416 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10417 {
10418 if( !lp->strongbranchprobing )
10419 {
10420 SCIPstatIncrement(stat, set, nlps);
10421 SCIPstatAdd( stat, set, nlpiterations, iterations );
10422 }
10423 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10424 {
10425 SCIPstatIncrement(stat, set, nprimalresolvelps );
10426 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10427 }
10428 if ( instable )
10429 {
10430 SCIPstatIncrement(stat, set, nresolveinstablelps);
10431 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10432 }
10433 if( lp->diving || lp->probing )
10434 {
10435 if( lp->strongbranchprobing )
10436 {
10437 SCIPstatIncrement(stat, set, nsbdivinglps);
10438 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10439 }
10440 else
10441 {
10442 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10443 SCIPstatIncrement(stat, set, ndivinglps);
10444 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10445 }
10446 }
10447 else
10448 {
10449 SCIPstatIncrement(stat, set, nprimallps);
10450 SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10451 }
10452 }
10453 else
10454 {
10455 if ( ! lp->diving && ! lp->probing )
10456 {
10457 SCIPstatIncrement(stat, set, nprimalzeroitlps);
10458 SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10459 }
10460
10461 if ( keepsol && !(*lperror) )
10462 {
10463 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10464 if( lp->validsollp == stat->lpcount-1 )
10465 lp->validsollp = stat->lpcount;
10466 if( lp->validfarkaslp == stat->lpcount-1 )
10467 lp->validfarkaslp = stat->lpcount;
10468 }
10469 }
10470
10471 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10472 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10473
10474 return SCIP_OKAY;
10475}
10476
10477/** calls LPI to perform dual simplex, measures time and counts iterations */
10478static
10480 SCIP_LP* lp, /**< current LP data */
10481 SCIP_SET* set, /**< global SCIP settings */
10482 SCIP_STAT* stat, /**< problem statistics */
10483 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10484 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10485 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10486 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10487 )
10488{
10489 SCIP_Real timedelta;
10490 SCIP_RETCODE retcode;
10491 int iterations;
10492
10493 assert(lp != NULL);
10494 assert(lp->flushed);
10495 assert(set != NULL);
10496 assert(stat != NULL);
10497 assert(lperror != NULL);
10498
10499 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10500 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10501
10502 *lperror = FALSE;
10503
10504#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10505 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10506 {
10507 char fname[SCIP_MAXSTRLEN];
10508 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10509 SCIP_CALL( SCIPlpWrite(lp, fname) );
10510 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10511 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10513 }
10514#endif
10515
10516 /* start timing */
10517 if( lp->diving || lp->probing )
10518 {
10519 if( lp->strongbranchprobing )
10521 else
10523
10524 timedelta = 0.0; /* unused for diving or probing */
10525 }
10526 else
10527 {
10529 timedelta = -SCIPclockGetTime(stat->duallptime);
10530 }
10531
10532 /* if this is a call to resolve an instable LP, collect time */
10533 if ( instable )
10534 {
10536 }
10537
10538 /* call dual simplex */
10539 retcode = SCIPlpiSolveDual(lp->lpi);
10540 if( retcode == SCIP_LPERROR )
10541 {
10542 *lperror = TRUE;
10543 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10544 }
10545 else
10546 {
10547 SCIP_CALL( retcode );
10548 }
10550 lp->solisbasic = TRUE;
10551
10552 /* stop timing */
10553 if( lp->diving || lp->probing )
10554 {
10555 if( lp->strongbranchprobing )
10557 else
10559 }
10560 else
10561 {
10562 timedelta += SCIPclockGetTime(stat->duallptime);
10564 }
10565
10566 if ( instable )
10567 {
10569 }
10570
10571 /* count number of iterations */
10572 SCIPstatIncrement(stat, set, lpcount);
10573 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10574 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10575 {
10576 if( !lp->strongbranchprobing )
10577 {
10578 SCIPstatIncrement(stat, set, nlps);
10579 SCIPstatAdd(stat, set, nlpiterations, iterations);
10580 }
10581 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10582 {
10583 SCIPstatIncrement(stat, set, ndualresolvelps);
10584 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10585 }
10586 if ( instable )
10587 {
10588 SCIPstatIncrement(stat, set, nresolveinstablelps);
10589 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10590 }
10591 if( lp->diving || lp->probing )
10592 {
10593 if( lp->strongbranchprobing )
10594 {
10595 SCIPstatIncrement(stat, set, nsbdivinglps);
10596 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10597 }
10598 else
10599 {
10600 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10601 SCIPstatIncrement(stat, set, ndivinglps);
10602 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10603 }
10604 }
10605 else
10606 {
10607 SCIPstatIncrement(stat, set, nduallps);
10608 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10609 }
10610 }
10611 else
10612 {
10613 if ( ! lp->diving && ! lp->probing )
10614 {
10615 SCIPstatIncrement(stat, set, ndualzeroitlps);
10616 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10617 }
10618
10619 if( keepsol && !(*lperror) )
10620 {
10621 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10622 if( lp->validsollp == stat->lpcount-1 )
10623 lp->validsollp = stat->lpcount;
10624 if( lp->validfarkaslp == stat->lpcount-1 )
10625 lp->validfarkaslp = stat->lpcount;
10626 }
10627 }
10628
10629 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10630 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10631
10632 return SCIP_OKAY;
10633}
10634
10635/** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10636 *
10637 * We follow the approach of the following paper to find a lexicographically minimal optimal
10638 * solution:
10639 *
10640 * Zanette, Fischetti, Balas@n
10641 * Can pure cutting plane algorithms work?@n
10642 * IPCO 2008, Bertinoro, Italy.
10643 *
10644 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10645 * heuristic, i.e., we limit the number of components which are minimized.
10646 *
10647 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10648 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10649 * variables) that have nonzero reduced cost. This fixes the objective function value, because only
10650 * pivots that will not change the objective are allowed afterwards.
10651 *
10652 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10653 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10654 * candidate is found, we set the objective to minimize this variable. We run the primal simplex
10655 * algorithm (since the objective is changed the solution is not dual feasible anymore; if
10656 * variables out of the basis have been fixed to their lower bound, the basis is also not primal
10657 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10658 * reduced cost. We then choose the next variable and iterate.
10659 *
10660 * We stop the process once we do not find candidates or have performed a maximum number of
10661 * iterations.
10662 *
10663 * @todo Does this really produce a lexicographically minimal solution?
10664 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10665 * guarantee that these variables will not be changed in later stages? We can fix these variables
10666 * to their lower bound, but this destroys the basis.
10667 * @todo Should we use lexicographical minimization in diving/probing or not?
10668 */
10669static
10671 SCIP_LP* lp, /**< current LP data */
10672 SCIP_SET* set, /**< global SCIP settings */
10673 SCIP_STAT* stat, /**< problem statistics */
10674 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10675 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10676 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10677 )
10678{
10679 SCIP_Real timedelta;
10680 SCIP_RETCODE retcode;
10681 int totalIterations;
10682 int lexIterations;
10683 int iterations;
10684 int rounds;
10685
10686 assert(lp != NULL);
10687 assert(lp->flushed);
10688 assert(set != NULL);
10689 assert(stat != NULL);
10690 assert(lperror != NULL);
10691
10692 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10693 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10694
10695 *lperror = FALSE;
10696
10697 /* start timing */
10698 if( lp->diving || lp->probing )
10699 {
10700 if( lp->strongbranchprobing )
10702 else
10704
10705 timedelta = 0.0; /* unused for diving or probing */
10706 }
10707 else
10708 {
10710 timedelta = -SCIPclockGetTime(stat->duallptime);
10711 }
10712
10713 /* call dual simplex for first lp */
10714 retcode = SCIPlpiSolveDual(lp->lpi);
10715 if( retcode == SCIP_LPERROR )
10716 {
10717 *lperror = TRUE;
10718 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10719 }
10720 else
10721 {
10722 SCIP_CALL( retcode );
10723 }
10724 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10725 totalIterations = iterations;
10726
10727 /* stop timing */
10728 if( lp->diving || lp->probing )
10729 {
10730 if( lp->strongbranchprobing )
10732 else
10734 }
10735 else
10736 {
10737 timedelta += SCIPclockGetTime(stat->duallptime);
10739 }
10740
10741 /* count number of iterations */
10742 SCIPstatIncrement(stat, set, lpcount);
10743 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10744 {
10745 if( lp->strongbranchprobing )
10746 {
10747 SCIPstatAdd(stat, set, nlpiterations, iterations);
10748 }
10749 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10750 {
10751 SCIPstatIncrement(stat, set, ndualresolvelps);
10752 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10753 }
10754 if( lp->diving || lp->probing )
10755 {
10756 if( lp->strongbranchprobing )
10757 {
10758 SCIPstatIncrement(stat, set, nsbdivinglps);
10759 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10760 }
10761 else
10762 {
10763 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10764 SCIPstatIncrement(stat, set, ndivinglps);
10765 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10766 }
10767 }
10768 else
10769 {
10770 SCIPstatIncrement(stat, set, nduallps);
10771 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10772 }
10773 }
10774 else
10775 {
10776 if ( ! lp->diving && ! lp->probing )
10777 {
10778 SCIPstatIncrement(stat, set, ndualzeroitlps);
10779 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10780 }
10781 }
10782 lexIterations = 0;
10783
10784 /* search for lexicographically minimal optimal solution */
10785 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10786 {
10787 SCIP_Bool chooseBasic;
10788 SCIP_Real* primsol;
10789 SCIP_Real* dualsol;
10790 SCIP_Real* redcost;
10791 int* cstat;
10792 int* rstat;
10793 SCIP_Real* newobj;
10794 SCIP_Real* newlb;
10795 SCIP_Real* newub;
10796 SCIP_Real* newlhs;
10797 SCIP_Real* newrhs;
10798 SCIP_Real* oldlb;
10799 SCIP_Real* oldub;
10800 SCIP_Real* oldlhs;
10801 SCIP_Real* oldrhs;
10802 SCIP_Real* oldobj;
10803 SCIP_Bool* fixedc;
10804 SCIP_Bool* fixedr;
10805 int* indcol;
10806 int* indrow;
10807 int* indallcol;
10808 int* indallrow;
10809 int nDualDeg;
10810 int r, c;
10811 int cntcol;
10812 int cntrow;
10813 int nruns;
10814 int pos;
10815
10816 chooseBasic = set->lp_lexdualbasic;
10817
10818 /* start timing */
10820
10821 /* get all solution information */
10822 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10823 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10824 if( chooseBasic )
10825 {
10826 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10827 }
10828 else
10829 primsol = NULL;
10830
10831 /* get basic and nonbasic information */
10834
10835 /* save bounds, lhs/rhs, and objective */
10841 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10842 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10843 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10844
10845 /* get storage for several arrays */
10849
10853
10854 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10855 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10856
10859
10860 /* initialize: set objective to 0, get fixed variables */
10862 for( c = 0; c < lp->nlpicols; ++c )
10863 {
10864 newobj[c] = 0.0;
10865 indallcol[c] = c;
10866 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10867 fixedc[c] = TRUE;
10868 else
10869 fixedc[c] = FALSE;
10870 }
10871
10872 /* initialize: get fixed slack variables */
10873 for( r = 0; r < lp->nlpirows; ++r )
10874 {
10875 indallrow[r] = r;
10876 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10877 fixedr[r] = TRUE;
10878 else
10879 fixedr[r] = FALSE;
10880 }
10881
10882#ifdef DEBUG_LEXDUAL
10883 {
10884 int j;
10885
10886 if( !chooseBasic )
10887 {
10888 assert(primsol == NULL);
10889 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10890 }
10891 assert(primsol != NULL);
10892 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10893 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10894
10895 for( j = 0; j < lp->nlpicols; ++j )
10896 {
10897 if( fixedc[j] )
10898 {
10899 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10900 }
10901 else
10902 {
10903 char type;
10904 switch( (SCIP_BASESTAT) cstat[j] )
10905 {
10907 type = 'l';
10908 break;
10910 type = 'u';
10911 break;
10912 case SCIP_BASESTAT_ZERO:
10913 type = 'z';
10914 break;
10916 type = 'b';
10917 break;
10918 default:
10919 type = '?';
10920 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10921 SCIPABORT();
10922 }
10923 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10924 }
10925 }
10926 SCIPsetDebugMsg(set, "\n\n");
10927
10928 if( !chooseBasic )
10929 {
10930 SCIPsetFreeBufferArray(set, &primsol);
10931 assert(primsol == NULL);
10932 }
10933 }
10934#endif
10935
10936 /* perform lexicographic rounds */
10937 pos = -1;
10938 nruns = 0;
10939 rounds = 0;
10940 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10941 do
10942 {
10943 int oldpos;
10944
10945 /* get current solution */
10946 if( chooseBasic )
10947 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10948 else
10949 {
10950 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10951 assert(primsol == NULL);
10952 }
10953
10954 /* get current basis */
10955 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10956
10957 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10958 nDualDeg = 0;
10959 cntcol = 0;
10960 oldpos = pos;
10961 pos = -1;
10962 for( c = 0; c < lp->nlpicols; ++c )
10963 {
10964 if( !fixedc[c] )
10965 {
10966 /* check whether variable is in basis */
10967 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10968 {
10969 /* store first candidate */
10970 if( pos == -1 && c > oldpos )
10971 {
10972 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10973 pos = c;
10974 }
10975 }
10976 else
10977 {
10978 /* reduced cost == 0 -> possible candidate */
10979 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10980 {
10981 ++nDualDeg;
10982 /* only if we have not yet found a candidate */
10983 if( pos == -1 && c > oldpos )
10984 {
10985 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10986 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10987 {
10988 newlb[cntcol] = oldlb[c];
10989 newub[cntcol] = oldlb[c];
10990 indcol[cntcol++] = c;
10991 fixedc[c] = TRUE;
10992 }
10993 else /* found a non-fixed candidate */
10994 {
10995 if( !chooseBasic )
10996 pos = c;
10997 }
10998 }
10999 }
11000 else
11001 {
11002 /* nonzero reduced cost -> variable can be fixed */
11003 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11004 {
11005 newlb[cntcol] = oldlb[c];
11006 newub[cntcol] = oldlb[c];
11007 }
11008 else
11009 {
11010 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11011 {
11012 newlb[cntcol] = oldub[c];
11013 newub[cntcol] = oldub[c];
11014 }
11015 else
11016 {
11017 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11018 newlb[cntcol] = 0.0;
11019 newub[cntcol] = 0.0;
11020 }
11021 }
11022 indcol[cntcol++] = c;
11023 fixedc[c] = TRUE;
11024 }
11025 }
11026 }
11027 }
11028
11029 /* check rows */
11030 cntrow = 0;
11031 for( r = 0; r < lp->nlpirows; ++r )
11032 {
11033 if( !fixedr[r] )
11034 {
11035 /* consider only nonbasic rows */
11036 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11037 {
11038 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11039 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11040 ++nDualDeg;
11041 else
11042 {
11043 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11044 {
11045 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11046 newlhs[cntrow] = oldlhs[r];
11047 newrhs[cntrow] = oldlhs[r];
11048 }
11049 else
11050 {
11051 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11052 newlhs[cntrow] = oldrhs[r];
11053 newrhs[cntrow] = oldrhs[r];
11054 }
11055 indrow[cntrow++] = r;
11056 fixedr[r] = TRUE;
11057 }
11058 }
11059 }
11060 }
11061
11062 if( nDualDeg > 0 && pos >= 0 )
11063 {
11064 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11065
11066 /* change objective */
11067 if( nruns == 0 )
11068 {
11069 /* set objective to appropriate unit vector for first run */
11070 newobj[pos] = 1.0;
11071 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11072 }
11073 else
11074 {
11075 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11076 SCIP_Real obj = 1.0;
11077 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11078 }
11079
11080 /* fix variables */
11081 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11082 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11083
11084 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11085 retcode = SCIPlpiSolvePrimal(lp->lpi);
11086 if( retcode == SCIP_LPERROR )
11087 {
11088 *lperror = TRUE;
11089 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11090 }
11091 else
11092 {
11093 SCIP_CALL( retcode );
11094 }
11095 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11096 lexIterations += iterations;
11097
11098#ifdef DEBUG_LEXDUAL
11099 if( iterations > 0 )
11100 {
11101 int j;
11102
11103 if( !chooseBasic )
11104 {
11105 assert(primsol == NULL);
11106 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11107 }
11108 assert(primsol != NULL);
11109 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11110
11111 for( j = 0; j < lp->nlpicols; ++j )
11112 {
11113 if( fixedc[j] )
11114 {
11115 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11116 }
11117 else
11118 {
11119 char cstart = '[';
11120 char cend = ']';
11121 char type;
11122
11123 if(j == pos)
11124 {
11125 cstart = '*';
11126 cend = '*';
11127 }
11128
11129 switch( (SCIP_BASESTAT) cstat[j] )
11130 {
11132 type = 'l';
11133 break;
11135 type = 'u';
11136 break;
11137 case SCIP_BASESTAT_ZERO:
11138 type = 'z';
11139 break;
11141 type = 'b';
11142 break;
11143 default:
11144 type = '?';
11145 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11146 SCIPABORT();
11147 }
11148 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11149 }
11150 }
11151 SCIPsetDebugMsg(set, "\n\n");
11152
11153 if( !chooseBasic )
11154 {
11155 SCIPsetFreeBufferArray(set, &primsol);
11156 assert(primsol == NULL);
11157 }
11158 }
11159#endif
11160
11161 /* count only as round if iterations have been performed */
11162 if( iterations > 0 )
11163 ++rounds;
11164 ++nruns;
11165 }
11166 }
11167 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11168
11169 /* reset bounds, lhs/rhs, and obj */
11170 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11171 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11172 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11173
11174 /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
11175 retcode = SCIPlpiSolveDual(lp->lpi);
11176 if( retcode == SCIP_LPERROR )
11177 {
11178 *lperror = TRUE;
11179 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11180 }
11181 else
11182 {
11183 SCIP_CALL( retcode );
11184 }
11185 assert(SCIPlpiIsOptimal(lp->lpi));
11186 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11187 lexIterations += iterations;
11188
11189 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11190
11191 /* count number of iterations */
11192 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11193 SCIPstatIncrement(stat, set, nlps);
11194
11195 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11196 {
11197 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11198 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11199 {
11200 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11201 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11202 }
11203 SCIPstatIncrement(stat, set, nlexduallps);
11204 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11205
11206 totalIterations += lexIterations;
11207 }
11208
11209 /* free space */
11210 SCIPsetFreeBufferArray(set, &newobj);
11211
11212 SCIPsetFreeBufferArray(set, &fixedr);
11213 SCIPsetFreeBufferArray(set, &fixedc);
11214
11215 SCIPsetFreeBufferArray(set, &indallrow);
11216 SCIPsetFreeBufferArray(set, &indallcol);
11217
11218 SCIPsetFreeBufferArray(set, &indrow);
11219 SCIPsetFreeBufferArray(set, &newrhs);
11220 SCIPsetFreeBufferArray(set, &newlhs);
11221
11222 SCIPsetFreeBufferArray(set, &indcol);
11223 SCIPsetFreeBufferArray(set, &newub);
11224 SCIPsetFreeBufferArray(set, &newlb);
11225
11226 SCIPsetFreeBufferArray(set, &oldobj);
11227 SCIPsetFreeBufferArray(set, &oldrhs);
11228 SCIPsetFreeBufferArray(set, &oldlhs);
11229 SCIPsetFreeBufferArray(set, &oldub);
11230 SCIPsetFreeBufferArray(set, &oldlb);
11231
11232 SCIPsetFreeBufferArray(set, &rstat);
11233 SCIPsetFreeBufferArray(set, &cstat);
11234
11235 SCIPsetFreeBufferArray(set, &redcost);
11236 SCIPsetFreeBufferArray(set, &dualsol);
11237 if( chooseBasic )
11238 SCIPsetFreeBufferArray(set, &primsol);
11239
11240 /* stop timing */
11242
11243 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11244 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11245 }
11247 lp->solisbasic = TRUE;
11248
11249 if( totalIterations > 0 && !lp->strongbranchprobing )
11250 SCIPstatIncrement(stat, set, nlps);
11251 else
11252 {
11253 if( keepsol && !(*lperror) )
11254 {
11255 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11256 if( lp->validsollp == stat->lpcount-1 )
11257 lp->validsollp = stat->lpcount;
11258 if( lp->validfarkaslp == stat->lpcount-1 )
11259 lp->validfarkaslp = stat->lpcount;
11260 }
11261 }
11262
11263 return SCIP_OKAY;
11264}
11265
11266/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11267static
11269 SCIP_LP* lp, /**< current LP data */
11270 SCIP_SET* set, /**< global SCIP settings */
11271 SCIP_STAT* stat, /**< problem statistics */
11272 SCIP_Bool crossover, /**< should crossover be performed? */
11273 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11274 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11275 )
11276{
11277 SCIP_Real timedelta;
11278 SCIP_RETCODE retcode;
11279 int iterations;
11280
11281 assert(lp != NULL);
11282 assert(lp->flushed);
11283 assert(set != NULL);
11284 assert(stat != NULL);
11285 assert(lperror != NULL);
11286
11287 SCIPsetDebugMsg(set, "solving LP %" SCIP_LONGINT_FORMAT " (%d cols, %d rows) with barrier%s (diving=%d, nbarrierlps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11288 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11289 stat->nbarrierlps, stat->ndivinglps);
11290
11291 *lperror = FALSE;
11292
11293#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11294 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11295 {
11296 char fname[SCIP_MAXSTRLEN];
11297 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11298 SCIP_CALL( SCIPlpWrite(lp, fname) );
11299 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11300 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11302 }
11303#endif
11304
11305 /* start timing */
11306 if( lp->diving || lp->probing )
11307 {
11308 if( lp->strongbranchprobing )
11310 else
11312
11313 timedelta = 0.0; /* unused for diving or probing */
11314 }
11315 else
11316 {
11318 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11319 }
11320
11321 /* call barrier algorithm */
11322 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11323 if( retcode == SCIP_LPERROR )
11324 {
11325 *lperror = TRUE;
11326 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11327 }
11328 else
11329 {
11330 SCIP_CALL( retcode );
11331 }
11333 lp->solisbasic = crossover;
11334
11335 /* stop timing */
11336 if( lp->diving || lp->probing )
11337 {
11338 if( lp->strongbranchprobing )
11340 else
11342 }
11343 else
11344 {
11346 timedelta += SCIPclockGetTime(stat->barrierlptime);
11347 }
11348
11349 /* count number of iterations */
11350 SCIPstatIncrement(stat, set, lpcount);
11351 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11352 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11353 {
11354 if( !lp->strongbranchprobing )
11355 {
11356 SCIPstatIncrement(stat, set, nlps);
11357 SCIPstatAdd(stat, set, nlpiterations, iterations);
11358 }
11359 if( lp->diving || lp->probing )
11360 {
11361 if( lp->strongbranchprobing )
11362 {
11363 SCIPstatIncrement(stat, set, nsbdivinglps);
11364 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11365 }
11366 else
11367 {
11368 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11369 SCIPstatIncrement(stat, set, ndivinglps);
11370 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11371 }
11372 }
11373 else
11374 {
11375 SCIPstatIncrement(stat, set, nbarrierlps);
11376 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11377 }
11378 }
11379 else
11380 {
11381 if ( ! lp->diving && ! lp->probing )
11382 {
11383 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11384 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11385 }
11386
11387 if( keepsol && !(*lperror) )
11388 {
11389 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11390 if( lp->validsollp == stat->lpcount-1 )
11391 lp->validsollp = stat->lpcount;
11392 if( lp->validfarkaslp == stat->lpcount-1 )
11393 lp->validfarkaslp = stat->lpcount;
11394 }
11395 }
11396
11397 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11398 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11399
11400 return SCIP_OKAY;
11401}
11402
11403/** solves the LP with the given algorithm */
11404static
11406 SCIP_LP* lp, /**< current LP data */
11407 SCIP_SET* set, /**< global SCIP settings */
11408 SCIP_STAT* stat, /**< problem statistics */
11409 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11410 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11411 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11412 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11413 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11414 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11415 )
11416{
11417 SCIP_Real lptimelimit;
11418 SCIP_Bool success;
11419
11420 assert(lp != NULL);
11421 assert(lp->flushed);
11422 assert(lperror != NULL);
11423
11424 /* check if a time limit is set, and set time limit for LP solver accordingly */
11425 lptimelimit = SCIPlpiInfinity(lp->lpi);
11426 if( set->istimelimitfinite )
11427 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11428
11429 success = FALSE;
11430 if( lptimelimit > 0.0 )
11431 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11432
11433 if( lptimelimit <= 0.0 || !success )
11434 {
11435 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11436 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11437 *timelimit = TRUE;
11438 return SCIP_OKAY;
11439 }
11440 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11441
11442 /* call appropriate LP algorithm */
11443 switch( lpalgo )
11444 {
11446 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11447 break;
11448
11450 /* run dual lexicographic simplex if required */
11451 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11452 {
11453 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11454 }
11455 else
11456 {
11457 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11458 }
11459 break;
11460
11462 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11463 break;
11464
11466 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11467 break;
11468
11469 default:
11470 SCIPerrorMessage("invalid LP algorithm\n");
11471 return SCIP_INVALIDDATA;
11472 }
11473
11474 if( !(*lperror) )
11475 {
11476 /* check for primal and dual feasibility */
11478
11479 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11480 }
11481
11482 return SCIP_OKAY;
11483}
11484
11485/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11486 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11487 */
11488#define MAXNUMTROUBLELPMSGS 10
11489
11490/** prints message about numerical trouble
11491 *
11492 * If message has verblevel at most high and display/verblevel is not full,
11493 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11494 * were printed before in the current run.
11495 */
11496static
11498 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11499 SCIP_SET* set, /**< global SCIP settings */
11500 SCIP_STAT* stat, /**< problem statistics */
11501 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11502 const char* formatstr, /**< message format string */
11503 ... /**< arguments to format string */
11504 )
11505{
11506 va_list ap;
11507
11508 assert(verblevel > SCIP_VERBLEVEL_NONE);
11509 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11510 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11511
11512 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11513 {
11514 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11515 {
11516 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11518 return;
11519
11520 /* increase count on messages with verblevel high */
11521 ++stat->nnumtroublelpmsgs ;
11522 }
11523
11524 /* if messages wouldn't be printed, then return already */
11525 if( verblevel > set->disp_verblevel )
11526 return;
11527 }
11528
11529 /* print common begin of message */
11530 SCIPmessagePrintInfo(messagehdlr,
11531 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11532 stat->nnodes, stat->nlps);
11533
11534 /* print individual part of message */
11535 va_start(ap, formatstr); /*lint !e838*/
11536 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11537 va_end(ap);
11538
11539 /* warn that further messages will be suppressed */
11540 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11541 {
11542 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11543 }
11544
11545 /* print closing new-line */
11546 SCIPmessagePrintInfo(messagehdlr, "\n");
11547}
11548
11549static
11551 SCIP_LP* lp, /**< current LP data */
11552 SCIP_SET* set, /**< global SCIP settings */
11553 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11554 SCIP_STAT* stat, /**< problem statistics */
11555 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11556 SCIP_Bool* success /**< was instability successfully ignored */
11557 )
11558{
11559 assert(lp != NULL);
11560 assert(set != NULL);
11561
11562 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11563
11564 if( *success )
11565 {
11566 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11567 if( !set->lp_checkdualfeas )
11568 lp->dualfeasible = TRUE;
11569 if( !set->lp_checkprimfeas )
11570 lp->primalchecked = TRUE;
11571 }
11572
11573 return SCIP_OKAY;
11574}
11575
11576#define FEASTOLTIGHTFAC 0.001
11577/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11578static
11580 SCIP_LP* lp, /**< current LP data */
11581 SCIP_SET* set, /**< global SCIP settings */
11582 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11583 SCIP_STAT* stat, /**< problem statistics */
11584 SCIP_PROB* prob, /**< problem data */
11585 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11586 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11587 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11588 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11589 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11590 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11591 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11592 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11593 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11594 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11595 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11596 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11597 )
11598{
11599 SCIP_Bool success;
11600 SCIP_Bool success2;
11601 SCIP_Bool success3;
11602 SCIP_Bool simplex;
11603 SCIP_Bool itlimishard;
11604 SCIP_Bool usepolishing;
11605
11606 assert(lp != NULL);
11607 assert(lp->flushed);
11608 assert(set != NULL);
11609 assert(stat != NULL);
11610 assert(lperror != NULL);
11611 assert(timelimit != NULL);
11612
11613 *lperror = FALSE;
11614
11615 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11616 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11617 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11618 * SCIP_LP such that we can return a primal ray
11619 */
11620 if( lp->looseobjvalinf > 0 )
11621 {
11622 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11623 return SCIP_ERROR;
11624 }
11625
11626 /* check, whether we solve with a simplex algorithm */
11627 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11628
11629 /* check whether the iteration limit is a hard one */
11630 itlimishard = (itlim == harditlim);
11631
11632 /* check whether solution polishing should be used */
11633 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11634 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11635 {
11636 usepolishing = TRUE;
11637 if( lp->updateintegrality )
11638 {
11640 }
11641 }
11642 else
11643 usepolishing = FALSE;
11644
11645 /* solve with given settings (usually fast but imprecise) */
11647 {
11648 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11649 }
11650 else
11651 {
11652 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11653 }
11654 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11655 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11657 &success) );
11658 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11659 : SCIPsetBarrierconvtol(set), &success) );
11660 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11661 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11662 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11663 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11664 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11665 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11666 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11667 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11668 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11669 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11670 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11671 SCIP_CALL( lpSetRandomseed(lp, (int) (SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed) % INT_MAX), &success) );
11672 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11673 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11674
11675 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11676
11677 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11678 * optimal without preforming scaling/change tolerances/presolving */
11679 resolve = FALSE;
11680
11681 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11682 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11683 return SCIP_OKAY;
11684
11685 if( !set->lp_checkstability )
11686 {
11687 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11688
11689 if( success )
11690 return SCIP_OKAY;
11691 }
11692
11693 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11694 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11695 */
11696
11697 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11698 * do this only if the iteration limit was not exceeded in the last LP solving call
11699 */
11700 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11701 {
11702 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11703 if( success )
11704 {
11705 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11706 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11707
11708 /* check for stability */
11709 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11710 return SCIP_OKAY;
11711
11712 if( !set->lp_checkstability )
11713 {
11714 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11715
11716 if( success )
11717 return SCIP_OKAY;
11718 }
11719 }
11720 }
11721
11722 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11723 * and go directly to solving the LP from scratch
11724 */
11725 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11726 {
11727 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11728 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11729 if( success )
11730 {
11731 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11732 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11733 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11734
11735 /* check for stability */
11736 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11737 return SCIP_OKAY;
11738
11739 if( !set->lp_checkstability )
11740 {
11741 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11742
11743 if( success )
11744 return SCIP_OKAY;
11745 }
11746
11747 /* reset scaling */
11748 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11749 assert(success);
11750 }
11751 }
11752
11753 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11754 * and go directly to solving the LP from scratch */
11755 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11756 {
11757 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11758 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11759 if( success )
11760 {
11761 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11762 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11763 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11764
11765 /* check for stability */
11766 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11767 return SCIP_OKAY;
11768
11769 if( !set->lp_checkstability )
11770 {
11771 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11772
11773 if( success )
11774 return SCIP_OKAY;
11775 }
11776
11777 /* reset presolving */
11778 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11779 assert(success);
11780 }
11781 }
11782
11783 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11784 * do this only if the iteration limit was not exceeded in the last LP solving call
11785 */
11786 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11787 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11788 {
11789 success = FALSE;
11790 if( !tightprimfeastol )
11791 {
11792 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11793 }
11794
11795 success2 = FALSE;
11796 if( !tightdualfeastol )
11797 {
11799 }
11800
11801 success3 = FALSE;
11802 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11803 {
11805 }
11806
11807 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11808 if( success || success2 || success3 )
11809 {
11810 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11811 lpalgoName(lpalgo));
11812 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11813
11814 /* check for stability */
11815 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11816 return SCIP_OKAY;
11817
11818 if( !set->lp_checkstability )
11819 {
11820 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11821
11822 if( success )
11823 return SCIP_OKAY;
11824 }
11825
11826 /* reset feasibility tolerance */
11827 if( !tightprimfeastol )
11828 {
11829 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11830 }
11831 if( !tightdualfeastol )
11832 {
11834 }
11835 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11836 {
11838 }
11839 }
11840 }
11841
11842 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11843 * the given iteration limit might be a soft one to restrict resolving calls only */
11844 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11845
11846 /* if not already done, solve again from scratch */
11847 if( !fromscratch && simplex )
11848 {
11849 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11850 if( success )
11851 {
11852 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11853 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11854
11855 /* check for stability */
11856 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11857 return SCIP_OKAY;
11858
11859 if( !set->lp_checkstability )
11860 {
11861 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11862
11863 if( success )
11864 return SCIP_OKAY;
11865 }
11866 }
11867 }
11868
11869 /* solve again, use other simplex this time */
11870 if( simplex )
11871 {
11873 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11874 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11875
11876 /* check for stability */
11877 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11878 return SCIP_OKAY;
11879
11880 if( !set->lp_checkstability )
11881 {
11882 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11883
11884 if( success )
11885 return SCIP_OKAY;
11886 }
11887
11888 /* solve again with opposite scaling and other simplex */
11889 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11890 if( success )
11891 {
11892 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11893 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11894 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11895
11896 /* check for stability */
11897 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11898 return SCIP_OKAY;
11899
11900 if( !set->lp_checkstability )
11901 {
11902 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11903
11904 if( success )
11905 return SCIP_OKAY;
11906 }
11907
11908 /* reset scaling */
11909 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11910 assert(success);
11911 }
11912
11913 /* solve again with opposite presolving and other simplex */
11914 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11915 if( success )
11916 {
11917 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11918 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11919 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11920
11921 /* check for stability */
11922 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11923 return SCIP_OKAY;
11924
11925 if( !set->lp_checkstability )
11926 {
11927 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11928
11929 if( success )
11930 return SCIP_OKAY;
11931 }
11932
11933 /* reset presolving */
11934 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11935 assert(success);
11936 }
11937
11938 /* solve again with tighter feasibility tolerance, use other simplex this time */
11939 if( !tightprimfeastol || !tightdualfeastol )
11940 {
11941 success = FALSE;
11942 if( !tightprimfeastol )
11943 {
11944 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11945 }
11946
11947 success2 = FALSE;
11948 if( !tightdualfeastol )
11949 {
11951 }
11952
11953 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11954 if( success || success2 )
11955 {
11956 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11957 lpalgoName(lpalgo));
11958 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11959
11960 /* check for stability */
11961 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11962 return SCIP_OKAY;
11963
11964 if( !set->lp_checkstability )
11965 {
11966 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11967
11968 if( success )
11969 return SCIP_OKAY;
11970 }
11971
11972 /* reset feasibility tolerance */
11973 if( !tightprimfeastol )
11974 {
11975 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11976 }
11977 if( !tightdualfeastol )
11978 {
11980 }
11981 SCIP_UNUSED(success);
11982 }
11983 }
11984 }
11985
11986 /* nothing worked -- exit with an LPERROR */
11987 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11988 *lperror = TRUE;
11989
11990 return SCIP_OKAY;
11991}
11992
11993/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
11994static
11996 SCIP_LP* lp, /**< current LP data */
11997 SCIP_SET* set, /**< global SCIP settings */
11998 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
11999 )
12000{
12001 assert(lp != NULL);
12002 assert(set != NULL);
12003
12004 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12005 {
12006 if( !lp->adjustlpval && messagehdlr != NULL )
12007 {
12008 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12009 lp->adjustlpval = TRUE;
12010 }
12012 }
12013 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12014 {
12015 if( !lp->adjustlpval && messagehdlr != NULL )
12016 {
12017 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12018 lp->adjustlpval = TRUE;
12019 }
12021 }
12022}
12023
12024/** solves the LP with the given algorithm and evaluates return status */
12025static
12027 SCIP_LP* lp, /**< current LP data */
12028 SCIP_SET* set, /**< global SCIP settings */
12029 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12030 SCIP_STAT* stat, /**< problem statistics */
12031 SCIP_PROB* prob, /**< problem data */
12032 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12033 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12034 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12035 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12036 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12037 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12038 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12039 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12040 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12041 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12042 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12043 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12044 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12045 )
12046{
12047 SCIP_Bool solvedprimal;
12048 SCIP_Bool solveddual;
12049 SCIP_Bool timelimit;
12050 int itlim;
12051
12052 assert(lp != NULL);
12053 assert(lp->flushed);
12054 assert(set != NULL);
12055 assert(stat != NULL);
12056 assert(lperror != NULL);
12057
12058 checkLinks(lp);
12059
12060 solvedprimal = FALSE;
12061 solveddual = FALSE;
12062 timelimit = FALSE;
12063
12064 /* select the basic iteration limit depending on whether this is a resolving call or not */
12065 itlim = ( resolve ? resolveitlim : harditlim );
12066
12067 SOLVEAGAIN:
12068 /* call simplex */
12069 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12070 scaling, keepsol, &timelimit, lperror) );
12071 resolve = FALSE; /* only the first solve should be counted as resolving call */
12072 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12073 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12074
12075 /* check, if an error occurred */
12076 if( *lperror )
12077 {
12078 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12079 lp->solved = FALSE;
12081 return SCIP_OKAY;
12082 }
12083
12084 /* check, if a time limit was exceeded */
12085 if( timelimit )
12086 {
12087 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12088 lp->solved = TRUE;
12091 return SCIP_OKAY;
12092 }
12093
12094 /* only one should return true */
12097
12098 /* evaluate solution status */
12099 if( SCIPlpiIsOptimal(lp->lpi) )
12100 {
12101 assert(lp->primalfeasible);
12102 assert(lp->dualfeasible);
12104 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12105 adjustLPobjval(lp, set, messagehdlr);
12106
12108 {
12109 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12110 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12113 }
12114 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12115 * reached if the LP objective value is greater than the cutoff bound
12116 */
12118 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12119 }
12120 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12121 {
12122 assert(!lpCutoffDisabled(set, prob));
12123
12124#ifndef NDEBUG
12125 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12126 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12127 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12128 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12129#endif
12130
12133 }
12134 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12135 {
12136 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12137 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12138 {
12139 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12140 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12141 goto SOLVEAGAIN;
12142 }
12145 }
12146 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12147 {
12148 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12149 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12150 {
12151 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12154 goto SOLVEAGAIN;
12155 }
12158 }
12159 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12160 {
12161 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12162
12163 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12164 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12165 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12166 adjustLPobjval(lp, set, NULL);
12167 else
12168 adjustLPobjval(lp, set, messagehdlr);
12169
12171 }
12172 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12173 {
12176 }
12177 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12178 {
12179 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12180 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12181 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12182 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12183 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12184 goto SOLVEAGAIN;
12185 }
12186 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12187 {
12190 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12191 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12192 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12193 goto SOLVEAGAIN;
12194 }
12195 else
12196 {
12197 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12198 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12200 return SCIP_LPERROR;
12201 }
12202
12203 lp->solved = TRUE;
12204
12205 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12208
12209 return SCIP_OKAY;
12210}
12211
12212/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12213static
12215 SCIP_LP* lp, /**< current LP data */
12216 BMS_BLKMEM* blkmem, /**< block memory */
12217 SCIP_SET* set, /**< global SCIP settings */
12218 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12219 SCIP_STAT* stat, /**< problem statistics */
12220 SCIP_PROB* prob, /**< problem data */
12221 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12222 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12223 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12224 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12225 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12226 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12227 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12228 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12229 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12230 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12231 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12232 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12233 )
12234{
12235 SCIP_Bool resolve;
12236 char algo;
12237
12238 assert(lp != NULL);
12239 assert(set != NULL);
12240 assert(lperror != NULL);
12241
12242 /* flush changes to the LP solver */
12243 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12244 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12245
12246 /* select LP algorithm to apply */
12247 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12248 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12249
12250 switch( algo )
12251 {
12252 case 's':
12253 /* select simplex method */
12254 if( lp->dualfeasible || !lp->primalfeasible )
12255 {
12256 SCIPsetDebugMsg(set, "solving dual LP\n");
12257 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12258 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12259 }
12260 else
12261 {
12262 SCIPsetDebugMsg(set, "solving primal LP\n");
12263 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12264 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12265 }
12266 break;
12267
12268 case 'p':
12269 SCIPsetDebugMsg(set, "solving primal LP\n");
12270 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12271 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12272 break;
12273
12274 case 'd':
12275 SCIPsetDebugMsg(set, "solving dual LP\n");
12276 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12277 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12278 break;
12279
12280 case 'b':
12281 SCIPsetDebugMsg(set, "solving barrier LP\n");
12282 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12283 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12284 break;
12285
12286 case 'c':
12287 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12288 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12289 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12290 break;
12291
12292 default:
12293 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12295 }
12296 assert(!(*lperror) || !lp->solved);
12297
12298 return SCIP_OKAY;
12299}
12300
12301#ifndef NDEBUG
12302/** checks if the lazy bounds are valid */
12303static
12305 SCIP_LP* lp, /**< LP data */
12306 SCIP_SET* set /**< global SCIP settings */
12307 )
12308{
12309 SCIP_COL* col;
12310 int c;
12311
12312 assert(lp->flushed);
12313
12314 for( c = 0; c < lp->nlazycols; ++c )
12315 {
12316 col = lp->lazycols[c];
12317
12318 /* in case lazy bounds are given, check that the primal solution satisfies them */
12319 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12320 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12321 }
12322}
12323#else
12324#define checkLazyBounds(lp, set) /**/
12325#endif
12326
12327/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12328 * diving
12329 */
12330static
12332 SCIP_LP* lp, /**< LP data */
12333 SCIP_SET* set /**< global SCIP settings */
12334 )
12335{
12336 SCIP_COL* col;
12337 int c;
12338
12339 assert(lp->nlazycols > 0);
12340
12341 /* return, if we are in diving, and bounds were already applied
12342 * or if we are not in diving and bounds were not applied
12343 */
12344 if( lp->diving == lp->divinglazyapplied )
12345 return SCIP_OKAY;
12346
12347 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12348 lp->diving, lp->divinglazyapplied);
12349
12350 for( c = 0; c < lp->nlazycols; ++c )
12351 {
12352 col = lp->lazycols[c];
12353
12354 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12355 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12356 {
12357 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12358 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12359 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12360
12361 /* insert column in the chgcols list (if not already there) */
12362 SCIP_CALL( insertColChgcols(col, set, lp) );
12363
12364 /* mark bound change in the column */
12365 col->lbchanged = TRUE;
12366 }
12367
12368 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12369 if( !SCIPsetIsInfinity(set, col->lazyub) )
12370 {
12371 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12372 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12373 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12374
12375 /* insert column in the chgcols list (if not already there) */
12376 SCIP_CALL( insertColChgcols(col, set, lp) );
12377
12378 /* mark bound change in the column */
12379 col->ubchanged = TRUE;
12380 }
12381 }
12382
12383 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12384 * if not, we just removed them
12385 */
12386 lp->divinglazyapplied = lp->diving;
12387
12388 return SCIP_OKAY;
12389}
12390
12391/** returns the iteration limit for an LP resolving call */
12392static
12394 SCIP_SET* set, /**< global SCIP settings */
12395 SCIP_STAT* stat, /**< dynamic problem statistics */
12396 int itlim /**< hard iteration limit */
12397 )
12398{
12399 /* no limit set or average not yet reliable */
12400 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12401 return itlim;
12402 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12403 if( itlim == -1 )
12404 itlim = INT_MAX;
12405 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12406 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12407 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12408}
12409
12410
12411
12412/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12414 SCIP_LP* lp, /**< LP data */
12415 SCIP_SET* set, /**< global SCIP settings */
12416 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12417 BMS_BLKMEM* blkmem, /**< block memory buffers */
12418 SCIP_STAT* stat, /**< problem statistics */
12419 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12420 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12421 SCIP_PROB* prob, /**< problem data */
12422 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12423 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12424 * (limit is computed within the method w.r.t. the average LP iterations) */
12425 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12426 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12427 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12428 )
12429{
12430 SCIP_RETCODE retcode;
12431 SCIP_Bool needprimalray;
12432 SCIP_Bool needdualray;
12433 int harditlim;
12434 int resolveitlim;
12435
12436 assert(lp != NULL);
12437 assert(prob != NULL);
12438 assert(prob->nvars >= lp->ncols);
12439 assert(lperror != NULL);
12440
12441 retcode = SCIP_OKAY;
12442 *lperror = FALSE;
12443
12444 if( lp->flushed && lp->solved )
12445 {
12446 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12447 return SCIP_OKAY;
12448 }
12449
12450 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12451 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12452
12453 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12454 needprimalray = TRUE;
12455 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12456 || (set->conf_enable && set->conf_useinflp != 'o'));
12457
12458 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12459 harditlim = (int) MIN(itlim, INT_MAX);
12460 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12461 assert(harditlim == -1 || (resolveitlim <= harditlim));
12462
12463 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12464 * or removed from the LP (diving was ended)
12465 */
12466 if( lp->nlazycols > 0 )
12467 {
12468 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12469 * first resolve LP?
12470 */
12472 assert(lp->diving == lp->divinglazyapplied);
12473 }
12474
12475 /* flush changes to the LP solver */
12476 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12477 assert(lp->flushed);
12478
12479 /* if the time limit was reached in the last call and the LP did not change, lp->solved is set to TRUE, but we want
12480 * to run again anyway, since there seems to be some time left / the time limit was increased
12481 */
12482 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12483 {
12484 SCIP_Bool* primalfeaspointer;
12485 SCIP_Bool* dualfeaspointer;
12486 SCIP_Bool primalfeasible;
12487 SCIP_Bool dualfeasible;
12488 SCIP_Bool farkasvalid;
12489 SCIP_Bool rayfeasible;
12490 SCIP_Bool tightprimfeastol;
12491 SCIP_Bool tightdualfeastol;
12492 SCIP_Bool fromscratch;
12493 SCIP_Bool wasfromscratch;
12494 int scaling;
12495 SCIP_Longint oldnlps;
12496 int fastmip;
12497
12498 /* set initial LP solver settings */
12499 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12500 tightprimfeastol = FALSE;
12501 tightdualfeastol = FALSE;
12502 fromscratch = FALSE;
12503 primalfeasible = FALSE;
12504 dualfeasible = FALSE;
12505 wasfromscratch = (stat->nlps == 0);
12506 scaling = set->lp_scaling;
12507
12508 SOLVEAGAIN:
12509 /* solve the LP */
12510 oldnlps = stat->nlps;
12511 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12512 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12513 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12514 assert(!(*lperror) || !lp->solved);
12515
12516 /* check for error */
12517 if( *lperror )
12518 {
12519 retcode = SCIP_OKAY;
12520 goto TERMINATE;
12521 }
12522
12523 /* evaluate solution status */
12524 switch( SCIPlpGetSolstat(lp) )
12525 {
12527 /* get LP solution and possibly check the solution's feasibility again */
12528 if( set->lp_checkprimfeas )
12529 {
12530 primalfeaspointer = &primalfeasible;
12531 lp->primalchecked = TRUE;
12532 }
12533 else
12534 {
12535 /* believe in the primal feasibility of the LP solution */
12536 primalfeasible = TRUE;
12537 primalfeaspointer = NULL;
12538 lp->primalchecked = FALSE;
12539 }
12540 if( set->lp_checkdualfeas )
12541 {
12542 dualfeaspointer = &dualfeasible;
12543 lp->dualchecked = TRUE;
12544 }
12545 else
12546 {
12547 /* believe in the dual feasibility of the LP solution */
12548 dualfeasible = TRUE;
12549 dualfeaspointer = NULL;
12550 lp->dualchecked = FALSE;
12551 }
12552
12553 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12554
12555 /* in debug mode, check that lazy bounds (if present) are not violated */
12556 checkLazyBounds(lp, set);
12557
12558 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12559 {
12560 /* update ages and remove obsolete columns and rows from LP */
12561 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12562 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12563 {
12564 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12565 }
12566
12567 if( !lp->solved )
12568 {
12569 /* resolve LP after removing obsolete columns and rows */
12570 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12571 aging = FALSE; /* to prevent infinite loops */
12572 goto SOLVEAGAIN;
12573 }
12574 }
12575 if( !primalfeasible || !dualfeasible )
12576 {
12578
12579 if( (fastmip > 0) && simplex )
12580 {
12581 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12582 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12583 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12584 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12585 fastmip = 0;
12586 goto SOLVEAGAIN;
12587 }
12588 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12589 {
12590 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12591 * tolerance
12592 */
12593 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12594 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12595 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12596 tightprimfeastol = tightprimfeastol || !primalfeasible;
12597 tightdualfeastol = tightdualfeastol || !dualfeasible;
12598 goto SOLVEAGAIN;
12599 }
12600 else if( !fromscratch && !wasfromscratch && simplex )
12601 {
12602 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12603 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12604 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12605 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12606 fromscratch = TRUE;
12607 goto SOLVEAGAIN;
12608 }
12609 else
12610 {
12611 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12612 lp->solved = FALSE;
12614 *lperror = TRUE;
12615 }
12616 }
12617 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12618 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12619 lp->lpsolstat, lp->cutoffbound);
12620 break;
12621
12623 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12624 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve || set->lp_alwaysgetduals )
12625 {
12626 if( SCIPlpiHasDualRay(lp->lpi) )
12627 {
12628 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12629 }
12630 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12631 * with the primal simplex due to numerical problems) - treat this case like an LP error
12632 */
12633 else
12634 {
12635 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12636 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12637 lp->solved = FALSE;
12639 farkasvalid = FALSE;
12640 *lperror = TRUE;
12641 }
12642 }
12643 else
12644 farkasvalid = TRUE;
12645
12646 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12647 if( !farkasvalid && !(*lperror) )
12648 {
12650
12651 if( (fastmip > 0) && simplex )
12652 {
12653 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12654 * without FASTMIP
12655 */
12656 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12657 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12658 stat->nnodes, stat->nlps);
12659 fastmip = 0;
12660 goto SOLVEAGAIN;
12661 }
12662 else if( !tightdualfeastol )
12663 {
12664 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12665 * solve again with tighter feasibility tolerance
12666 */
12667 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12668 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12669 stat->nnodes, stat->nlps);
12670 tightdualfeastol = TRUE;
12671 goto SOLVEAGAIN;
12672 }
12673 else if( !fromscratch && simplex )
12674 {
12675 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12676 * from scratch
12677 */
12678 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12679 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12680 stat->nnodes, stat->nlps);
12681 fromscratch = TRUE;
12682 goto SOLVEAGAIN;
12683 }
12684 else
12685 {
12686 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12687 * helped forget about the LP at this node and mark it to be unsolved
12688 */
12689 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12690 lp->solved = FALSE;
12692 *lperror = TRUE;
12693 }
12694 }
12695
12696 break;
12697
12699 if( set->lp_checkprimfeas )
12700 {
12701 /* get unbounded LP solution and check the solution's feasibility again */
12702 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12703
12704 lp->primalchecked = TRUE;
12705 }
12706 else
12707 {
12708 /* get unbounded LP solution believing in the feasibility of the LP solution */
12710
12711 primalfeasible = TRUE;
12712 rayfeasible = TRUE;
12713 lp->primalchecked = FALSE;
12714 }
12715
12716 /* in debug mode, check that lazy bounds (if present) are not violated */
12717 checkLazyBounds(lp, set);
12718
12719 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12720 primalfeasible, rayfeasible);
12721
12722 if( !primalfeasible || !rayfeasible )
12723 {
12725
12726 if( (fastmip > 0) && simplex )
12727 {
12728 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12729 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12730 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12731 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12732 fastmip = 0;
12733 goto SOLVEAGAIN;
12734 }
12735 else if( !tightprimfeastol )
12736 {
12737 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12738 * tolerance
12739 */
12740 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12741 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again with tighter primal feasibility tolerance\n",
12742 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12743 tightprimfeastol = TRUE;
12744 goto SOLVEAGAIN;
12745 }
12746 else if( !fromscratch && simplex )
12747 {
12748 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12749 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12750 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12751 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12752 fromscratch = TRUE;
12753 goto SOLVEAGAIN;
12754 }
12755 else if( scaling > 0 )
12756 {
12757 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12758 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12759 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12760 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12761 scaling = 0;
12762 goto SOLVEAGAIN;
12763 }
12764 else
12765 {
12766 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12767 * forget about the LP at this node and mark it to be unsolved
12768 */
12769 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12770 lp->solved = FALSE;
12772 *lperror = TRUE;
12773 }
12774 }
12775
12776 break;
12777
12779 assert(!lpCutoffDisabled(set, prob));
12780 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12781 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12782 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12783 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12784 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12785 * FASTMIP and solve again. */
12786 if( !SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve )
12787 {
12788 SCIP_LPI* lpi;
12789 SCIP_Real objval;
12790
12791 lpi = SCIPlpGetLPI(lp);
12792
12793 assert(lpi != NULL);
12794 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12795 * the assert by using !SCIPsetIsFeasNegative()
12796 */
12797 assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim));
12798
12799 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12800
12801 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12802 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12803 {
12804 SCIP_Real tmpcutoff;
12805 char tmppricingchar;
12806 SCIP_LPSOLSTAT solstat;
12807
12808 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12809
12810 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12811 fromscratch = FALSE;
12812
12813 /* temporarily disable cutoffbound, which also disables the objective limit */
12814 tmpcutoff = lp->cutoffbound;
12815 lp->cutoffbound = SCIPlpiInfinity(lpi);
12816
12817 /* set lp pricing strategy to steepest edge */
12818 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12819 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12820
12821 /* resolve LP with an iteration limit of 1 */
12822 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12823 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12824
12825 /* reinstall old cutoff bound and lp pricing strategy */
12826 lp->cutoffbound = tmpcutoff;
12827 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12828
12829 /* get objective value */
12830 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12831
12832 /* get solution status for the lp */
12833 solstat = SCIPlpGetSolstat(lp);
12834 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12835
12836 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12837
12838 /* the solution is still not exceeding the objective limit and the solving process
12839 * was stopped due to time or iteration limit, solve again with fastmip turned off
12840 */
12841 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12842 SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12843 {
12845 if( !(*lperror) && (fastmip > 0) && simplex )
12846 {
12847 fastmip = 0;
12848 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12849 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12850
12851 /* get objective value */
12852 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12853
12854 /* get solution status for the lp */
12855 solstat = SCIPlpGetSolstat(lp);
12856
12857 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12858 }
12859 }/*lint !e438*/
12860
12861 /* check for lp errors */
12862 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12863 {
12864 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12865 lp->solved = FALSE;
12867
12868 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12869 goto TERMINATE;
12870 }
12871
12872 lp->solved = TRUE;
12873
12874 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12875 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12876 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12877 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12878 {
12879 /* get LP solution and possibly check the solution's feasibility again */
12880 if( set->lp_checkprimfeas )
12881 {
12882 primalfeaspointer = &primalfeasible;
12883 lp->primalchecked = TRUE;
12884 }
12885 else
12886 {
12887 /* believe in the primal feasibility of the LP solution */
12888 primalfeasible = TRUE;
12889 primalfeaspointer = NULL;
12890 lp->primalchecked = FALSE;
12891 }
12892 if( set->lp_checkdualfeas )
12893 {
12894 dualfeaspointer = &dualfeasible;
12895 lp->dualchecked = TRUE;
12896 }
12897 else
12898 {
12899 /* believe in the dual feasibility of the LP solution */
12900 dualfeasible = TRUE;
12901 dualfeaspointer = NULL;
12902 lp->dualchecked = FALSE;
12903 }
12904
12905 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12906
12907 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12908 if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12909 {
12910 checkLazyBounds(lp, set);
12911 }
12912
12913 /* if objective value is larger than the cutoff bound, set solution status to objective
12914 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12915 * this was already done in the lpSolve() method
12916 */
12917 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12918 {
12921 }
12922
12923 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12924 * the cutoffbound; mark the LP to be unsolved
12925 */
12926 if( !primalfeasible || !dualfeasible
12927 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12928 !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
12929 {
12930 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12931 lp->solved = FALSE;
12933 *lperror = TRUE;
12934 }
12935
12936 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12937 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12938 lp->lpsolstat, lp->cutoffbound);
12939 }
12940 /* infeasible solution */
12941 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12942 {
12943 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12944
12945 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve )
12946 {
12947 if( SCIPlpiHasDualRay(lp->lpi) )
12948 {
12949 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12950 }
12951 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12952 * with the primal simplex due to numerical problems) - treat this case like an LP error
12953 */
12954 else
12955 {
12956 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12957 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12958 lp->solved = FALSE;
12960 farkasvalid = FALSE;
12961 *lperror = TRUE;
12962 }
12963 }
12964 else
12965 farkasvalid = TRUE;
12966
12967 if( !farkasvalid )
12968 {
12970
12971 if( !tightprimfeastol )
12972 {
12973 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12974 * solve again with tighter feasibility tolerance
12975 */
12976 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12977 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12978 stat->nnodes, stat->nlps);
12979 tightprimfeastol = TRUE;
12980 goto SOLVEAGAIN;
12981 }
12982 else if( simplex )
12983 {
12984 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12985 * from scratch
12986 */
12987 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12988 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12989 stat->nnodes, stat->nlps);
12990 fromscratch = TRUE;
12991 goto SOLVEAGAIN;
12992 }
12993 else
12994 {
12995 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12996 * helped forget about the LP at this node and mark it to be unsolved
12997 */
12998 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12999 lp->solved = FALSE;
13001 *lperror = TRUE;
13002 }
13003 }
13004 }
13005 /* unbounded solution */
13006 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13007 {
13008 if( set->lp_checkprimfeas )
13009 {
13010 /* get unbounded LP solution and check the solution's feasibility again */
13011 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13012
13013 lp->primalchecked = TRUE;
13014 }
13015 else
13016 {
13017 /* get unbounded LP solution believing in its feasibility */
13019
13020 primalfeasible = TRUE;
13021 rayfeasible = TRUE;
13022 lp->primalchecked = FALSE;
13023 }
13024
13025 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13026
13027 /* in debug mode, check that lazy bounds (if present) are not violated */
13028 checkLazyBounds(lp, set);
13029
13030 if( !primalfeasible || !rayfeasible )
13031 {
13032 /* unbounded solution is infeasible (this can happen due to numerical problems):
13033 * forget about the LP at this node and mark it to be unsolved
13034 *
13035 * @todo: like in the default LP solving evaluation, solve without fastmip,
13036 * with tighter feasibility tolerance and from scratch
13037 */
13038 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13039 lp->solved = FALSE;
13041 *lperror = TRUE;
13042 }
13043 }
13044
13045 assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
13046 assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
13048 }
13049 else
13050 {
13051 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13052 }
13053 }
13054 SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13055 break;
13056
13058 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13059 break;
13060
13062 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13063
13064 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13065 stat->nclockskipsleft = 0;
13066 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13067 {
13068 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13069 "you might consider switching the clock type of SCIP\n");
13071 }
13072 break;
13073
13076 SCIPerrorMessage("error in LP solver\n");
13077 retcode = SCIP_LPERROR;
13078 goto TERMINATE;
13079
13080 default:
13081 SCIPerrorMessage("unknown LP solution status\n");
13082 retcode = SCIP_ERROR;
13083 goto TERMINATE;
13084 }
13085 }
13086 assert(!(*lperror) || !lp->solved);
13087
13088 TERMINATE:
13089 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13090 * may happen that we continue to solve from scratch during strong branching */
13091 if( lp->lpifromscratch )
13092 {
13093 SCIP_Bool success;
13094 (void) lpSetFromscratch(lp, FALSE, &success);
13095 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13096 SCIP_UNUSED(success);
13097 }
13098
13099 return retcode;
13100}
13101
13102/** gets solution status of current LP */
13104 SCIP_LP* lp /**< current LP data */
13105 )
13106{
13107 assert(lp != NULL);
13108 assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
13109
13110 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13111}
13112
13113/** gets objective value of current LP
13114 *
13115 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13116 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13117 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13118 */
13120 SCIP_LP* lp, /**< current LP data */
13121 SCIP_SET* set, /**< global SCIP settings */
13122 SCIP_PROB* prob /**< problem data */
13123 )
13124{
13125 assert(lp != NULL);
13126 assert(lp->solved);
13127 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13128 assert(set != NULL);
13129
13130 if( !lp->flushed )
13131 return SCIP_INVALID;
13133 return lp->lpobjval;
13134 else if( lp->looseobjvalinf > 0 )
13135 return -SCIPsetInfinity(set);
13136 else
13137 {
13138 /* recalculate the loose objective value, if needed */
13139 if( !lp->looseobjvalid )
13141
13142 return lp->lpobjval + lp->looseobjval;
13143 }
13144}
13145
13146/** gets part of objective value of current LP that results from COLUMN variables only */
13148 SCIP_LP* lp /**< current LP data */
13149 )
13150{
13151 assert(lp != NULL);
13152 assert(lp->solved);
13153
13154 return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13155}
13156
13157/** gets part of objective value of current LP that results from LOOSE variables only */
13159 SCIP_LP* lp, /**< current LP data */
13160 SCIP_SET* set, /**< global SCIP settings */
13161 SCIP_PROB* prob /**< problem data */
13162 )
13163{
13164 assert(lp != NULL);
13165 assert(lp->solved);
13166 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13167 assert(set != NULL);
13168
13169 if( !lp->flushed )
13170 return SCIP_INVALID;
13171 else if( lp->looseobjvalinf > 0 )
13172 return -SCIPsetInfinity(set);
13173 else
13174 return getFiniteLooseObjval(lp, set, prob);
13175}
13176
13177/** remembers the current LP objective value as root solution value */
13179 SCIP_LP* lp, /**< current LP data */
13180 SCIP_SET* set, /**< global SCIP settings */
13181 SCIP_PROB* prob /**< problem data */
13182 )
13183{
13184 assert(lp != NULL);
13185
13187 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13188}
13189
13190/** invalidates the root LP solution value */
13192 SCIP_LP* lp /**< current LP data */
13193 )
13194{
13195 assert(lp != NULL);
13196
13199}
13200
13201/** recomputes local and global pseudo objective values */
13203 SCIP_LP* lp, /**< current LP data */
13204 SCIP_SET* set, /**< global SCIP settings */
13205 SCIP_PROB* prob /**< problem data */
13206 )
13207{
13208 SCIP_VAR** vars;
13209 int nvars;
13210 int v;
13211
13212 assert(lp != NULL);
13213 assert(set != NULL);
13214 assert(prob != NULL);
13215
13216 vars = prob->vars;
13217 nvars = prob->nvars;
13218
13219 lp->glbpseudoobjvalinf = 0;
13220 lp->glbpseudoobjval = 0.0;
13221
13222 lp->pseudoobjvalinf = 0;
13223 lp->pseudoobjval = 0.0;
13224
13225 for( v = 0; v < nvars; ++v )
13226 {
13227 SCIP_Real obj = SCIPvarGetObj(vars[v]);
13228
13229 if( SCIPsetIsPositive(set, obj) )
13230 {
13231 /* update the global pseudo objective value */
13232 if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
13233 ++(lp->glbpseudoobjvalinf);
13234 else
13235 lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
13236
13237 /* update the local pseudo objective value */
13238 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
13239 ++(lp->pseudoobjvalinf);
13240 else
13241 lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
13242 }
13243
13244 if( SCIPsetIsNegative(set, obj) )
13245 {
13246 /* update the global pseudo objective value */
13248 ++(lp->glbpseudoobjvalinf);
13249 else
13250 lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
13251
13252 /* update the local pseudo objective value */
13253 if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
13254 ++(lp->pseudoobjvalinf);
13255 else
13256 lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
13257 }
13258 }
13259
13260 /* the recomputed values are reliable */
13262 lp->glbpseudoobjvalid = TRUE;
13263 lp->relpseudoobjval = lp->pseudoobjval;
13264 lp->pseudoobjvalid = TRUE;
13265}
13266
13267/** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13268 * global bound
13269 */
13271 SCIP_LP* lp, /**< current LP data */
13272 SCIP_SET* set, /**< global SCIP settings */
13273 SCIP_PROB* prob /**< problem data */
13274 )
13275{
13276 assert(lp != NULL);
13277 assert(lp->glbpseudoobjvalinf >= 0);
13278 assert(set != NULL);
13279
13280 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13281 return -SCIPsetInfinity(set);
13282 else
13283 {
13284 /* recalculate the global pseudo solution value, if needed */
13285 if( !lp->glbpseudoobjvalid )
13287
13288 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13290 return -SCIPsetInfinity(set);
13291
13293 return SCIPsetInfinity(set);
13294
13295 return lp->glbpseudoobjval;
13296 }
13297}
13298
13299/** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13300 * objective function) local bound
13301 */
13303 SCIP_LP* lp, /**< current LP data */
13304 SCIP_SET* set, /**< global SCIP settings */
13305 SCIP_PROB* prob /**< problem data */
13306 )
13307{
13308 assert(lp != NULL);
13309 assert(lp->pseudoobjvalinf >= 0);
13310 assert(set != NULL);
13311
13312 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13313 return -SCIPsetInfinity(set);
13314 else
13315 {
13316 /* recalculate the pseudo solution value, if needed */
13317 if( !lp->pseudoobjvalid )
13319
13320 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13322 return -SCIPsetInfinity(set);
13323
13325 return SCIPsetInfinity(set);
13326
13327 return lp->pseudoobjval;
13328 }
13329}
13330
13331/** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13333 SCIP_LP* lp, /**< current LP data */
13334 SCIP_SET* set, /**< global SCIP settings */
13335 SCIP_PROB* prob, /**< problem data */
13336 SCIP_VAR* var, /**< problem variable */
13337 SCIP_Real oldbound, /**< old value for bound */
13338 SCIP_Real newbound, /**< new value for bound */
13339 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13340 )
13341{
13342 SCIP_Real pseudoobjval;
13343 int pseudoobjvalinf;
13344 SCIP_Real obj;
13345
13346 pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13347 pseudoobjvalinf = lp->pseudoobjvalinf;
13348 obj = SCIPvarGetObj(var);
13349 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13350 {
13351 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13352 pseudoobjvalinf--;
13353 else
13354 pseudoobjval -= oldbound * obj;
13355 assert(pseudoobjvalinf >= 0);
13356 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13357 pseudoobjvalinf++;
13358 else
13359 pseudoobjval += newbound * obj;
13360 }
13361 assert(pseudoobjvalinf >= 0);
13362
13363 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13364 return -SCIPsetInfinity(set);
13365 else
13366 return pseudoobjval;
13367}
13368
13369/** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13370 * perform calculations with interval arithmetic to get an exact lower bound
13371 */
13373 SCIP_LP* lp, /**< current LP data */
13374 SCIP_SET* set, /**< global SCIP settings */
13375 SCIP_VAR* var, /**< problem variable */
13376 SCIP_Real oldbound, /**< old value for bound */
13377 SCIP_Real newbound, /**< new value for bound */
13378 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13379 )
13380{
13381 SCIP_Real pseudoobjval;
13382 int pseudoobjvalinf;
13383 SCIP_Real obj;
13384
13385 assert(lp->pseudoobjvalid);
13386
13387 pseudoobjval = lp->pseudoobjval;
13388 pseudoobjvalinf = lp->pseudoobjvalinf;
13389 obj = SCIPvarGetObj(var);
13390 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13391 {
13392 SCIP_INTERVAL objint;
13393 SCIP_INTERVAL bd;
13394 SCIP_INTERVAL prod;
13395 SCIP_INTERVAL psval;
13396
13397 SCIPintervalSet(&psval, pseudoobjval);
13398 SCIPintervalSet(&objint, SCIPvarGetObj(var));
13399
13400 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13401 pseudoobjvalinf--;
13402 else
13403 {
13404 SCIPintervalSet(&bd, oldbound);
13405 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13406 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13407 }
13408 assert(pseudoobjvalinf >= 0);
13409 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13410 pseudoobjvalinf++;
13411 else
13412 {
13413 SCIPintervalSet(&bd, newbound);
13414 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13415 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13416 }
13417
13418 pseudoobjval = SCIPintervalGetInf(psval);
13419 }
13420 assert(pseudoobjvalinf >= 0);
13421
13422 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13423 return -SCIPsetInfinity(set);
13424 else
13425 return pseudoobjval;
13426}
13427
13428/** compute the objective delta due the new objective coefficient */
13429static
13431 SCIP_SET* set, /**< global SCIP settings */
13432 SCIP_Real oldobj, /**< old objective value of variable */
13433 SCIP_Real newobj, /**< new objective value of variable */
13434 SCIP_Real lb, /**< lower bound of variable */
13435 SCIP_Real ub, /**< upper bound of variable */
13436 SCIP_Real* deltaval, /**< pointer to store the delta value */
13437 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13438 )
13439{
13440 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13441 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13442 assert(!SCIPsetIsInfinity(set, lb));
13443 assert(!SCIPsetIsInfinity(set, -ub));
13444 assert(!SCIPsetIsEQ(set, oldobj, newobj));
13445
13446 (*deltaval) = 0.0;
13447 (*deltainf) = 0;
13448
13449 if( SCIPsetIsPositive(set, oldobj) )
13450 {
13451 /* sign of objective did not change */
13452 if( SCIPsetIsPositive(set, newobj) )
13453 {
13454 /* if the bound is finite, calculate the deltaval */
13455 if( !SCIPsetIsInfinity(set, -lb) )
13456 (*deltaval) = lb * (newobj - oldobj);
13457 }
13458 /* sign of objective did change, so the best bound does change */
13459 else if( SCIPsetIsNegative(set, newobj) )
13460 {
13461 if( SCIPsetIsInfinity(set, -lb) )
13462 {
13463 /* old best bound was infinite while new one is not */
13464 if( !SCIPsetIsInfinity(set, ub) )
13465 {
13466 (*deltainf) = -1;
13467 (*deltaval) = ub * newobj;
13468 }
13469 }
13470 else
13471 {
13472 /* new best bound is infinite while old one was not */
13473 if( SCIPsetIsInfinity(set, ub) )
13474 {
13475 (*deltainf) = 1;
13476 (*deltaval) = -lb * oldobj;
13477 }
13478 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13479 else
13480 {
13481 (*deltaval) = (ub * newobj) - (lb * oldobj);
13482 }
13483 }
13484 }
13485 /* new objective is 0.0 */
13486 else
13487 {
13488 if( SCIPsetIsInfinity(set, -lb) )
13489 (*deltainf) = -1;
13490 else
13491 (*deltaval) = -lb * oldobj;
13492 }
13493 }
13494 else if( SCIPsetIsNegative(set, oldobj) )
13495 {
13496 /* sign of objective did not change */
13497 if( SCIPsetIsNegative(set, newobj) )
13498 {
13499 /* if the bound is finite, calculate the deltaval */
13500 if( !SCIPsetIsInfinity(set, ub) )
13501 (*deltaval) = ub * (newobj - oldobj);
13502 }
13503 /* sign of objective did change, so the best bound does change */
13504 else if( SCIPsetIsPositive(set, newobj) )
13505 {
13506 if( SCIPsetIsInfinity(set, ub) )
13507 {
13508 /* old best bound was infinite while new one is not */
13509 if( !SCIPsetIsInfinity(set, -lb) )
13510 {
13511 (*deltainf) = -1;
13512 (*deltaval) = lb * newobj;
13513 }
13514 }
13515 else
13516 {
13517 /* new best bound is infinite while old one was not */
13518 if( SCIPsetIsInfinity(set, -lb) )
13519 {
13520 (*deltainf) = 1;
13521 (*deltaval) = -ub * oldobj;
13522 }
13523 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13524 else
13525 {
13526 (*deltaval) = (lb * newobj) - (ub * oldobj);
13527 }
13528 }
13529 }
13530 /* new objective is 0.0 */
13531 else
13532 {
13533 if( SCIPsetIsInfinity(set, ub) )
13534 (*deltainf) = -1;
13535 else
13536 (*deltaval) = -ub * oldobj;
13537 }
13538 }
13539 /* old objective was 0.0 */
13540 else
13541 {
13542 if( SCIPsetIsNegative(set, newobj) )
13543 {
13544 if( SCIPsetIsInfinity(set, ub) )
13545 (*deltainf) = 1;
13546 else
13547 (*deltaval) = ub * newobj;
13548 }
13549 else if( SCIPsetIsPositive(set, newobj) )
13550 {
13551 if( SCIPsetIsInfinity(set, -lb) )
13552 (*deltainf) = 1;
13553 else
13554 (*deltaval) = lb * newobj;
13555 }
13556 }
13557}
13558
13559/** compute the objective delta due the new lower bound */
13560static
13562 SCIP_SET* set, /**< global SCIP settings */
13563 SCIP_Real obj, /**< objective value of variable */
13564 SCIP_Real oldlb, /**< old lower bound of variable */
13565 SCIP_Real newlb, /**< new lower bound of variable */
13566 SCIP_Real* deltaval, /**< pointer to store the delta value */
13567 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13568 )
13569{
13570 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13571 assert(!SCIPsetIsInfinity(set, oldlb));
13572 assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
13573 assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
13574
13575 if( SCIPsetIsInfinity(set, -oldlb) )
13576 {
13577 if( !SCIPsetIsInfinity(set, newlb) )
13578 {
13579 (*deltainf) = -1;
13580 (*deltaval) = newlb * obj;
13581 }
13582 else
13583 {
13584 (*deltainf) = 0;
13585 (*deltaval) = 0.0;
13586 }
13587 }
13588 else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
13589 {
13590 (*deltainf) = 1;
13591 (*deltaval) = -oldlb * obj;
13592 }
13593 else
13594 {
13595 (*deltainf) = 0;
13596 (*deltaval) = obj * (newlb - oldlb);
13597 }
13598}
13599
13600/** compute the objective delta due the new upper bound */
13601static
13603 SCIP_SET* set, /**< global SCIP settings */
13604 SCIP_Real obj, /**< objective value of variable */
13605 SCIP_Real oldub, /**< old upper bound of variable */
13606 SCIP_Real newub, /**< new upper bound of variable */
13607 SCIP_Real* deltaval, /**< pointer to store the delta value */
13608 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13609 )
13610{
13611 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13612 assert(!SCIPsetIsInfinity(set, -oldub));
13613 assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
13614 assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
13615
13616 if( SCIPsetIsInfinity(set, oldub) )
13617 {
13618 if( !SCIPsetIsInfinity(set, -newub) )
13619 {
13620 (*deltainf) = -1;
13621 (*deltaval) = newub * obj;
13622 }
13623 else
13624 {
13625 (*deltainf) = 0;
13626 (*deltaval) = 0.0;
13627 }
13628 }
13629 else if( SCIPsetIsInfinity(set, REALABS(newub)) )
13630 {
13631 (*deltainf) = 1;
13632 (*deltaval) = -oldub * obj;
13633 }
13634 else
13635 {
13636 (*deltainf) = 0;
13637 (*deltaval) = obj * (newub - oldub);
13638 }
13639}
13640
13641/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13642static
13644 SCIP_LP* lp, /**< current LP data */
13645 SCIP_SET* set, /**< global SCIP settings */
13646 SCIP_VAR* var, /**< problem variable that changed */
13647 SCIP_Real deltaval, /**< delta value in the objective function */
13648 int deltainf, /**< delta value for the number of variables with infinite best bound */
13649 SCIP_Bool local, /**< should the local pseudo objective value be updated? */
13650 SCIP_Bool loose, /**< should the loose objective value be updated? */
13651 SCIP_Bool global /**< should the global pseudo objective value be updated? */
13652 )
13653{
13654 assert(lp != NULL);
13655 assert(lp->looseobjvalinf >= 0);
13656 assert(lp->pseudoobjvalinf >= 0);
13657 assert(lp->glbpseudoobjvalinf >= 0);
13658
13659 /* update the pseudo objective value */
13660 if( local )
13661 {
13662 lp->pseudoobjvalinf += deltainf;
13663 if( lp->pseudoobjvalid )
13664 {
13665 lp->pseudoobjval += deltaval;
13666
13667 /* if the absolute value was increased, this is regarded as reliable,
13668 * otherwise, we check whether we can still trust the updated value
13669 */
13671 lp->relpseudoobjval = lp->pseudoobjval;
13673 lp->pseudoobjvalid = FALSE;
13674 }
13675
13676 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13678 loose = TRUE;
13679 }
13680 /* update the loose objective value */
13681 if( loose )
13682 {
13683 lp->looseobjvalinf += deltainf;
13684
13685 if( deltaval != 0.0 && lp->looseobjvalid )
13686 {
13687 lp->looseobjval += deltaval;
13688
13689 /* if the absolute value was increased, this is regarded as reliable,
13690 * otherwise, we check whether we can still trust the updated value
13691 */
13692 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13693 lp->rellooseobjval = lp->looseobjval;
13695 lp->looseobjvalid = FALSE;
13696 }
13697 }
13698 /* update the root pseudo objective values */
13699 if( global )
13700 {
13701 lp->glbpseudoobjvalinf += deltainf;
13702 if( lp->glbpseudoobjvalid )
13703 {
13704 lp->glbpseudoobjval += deltaval;
13705
13706 /* if the absolute value was increased, this is regarded as reliable,
13707 * otherwise, we check whether we can still trust the updated value
13708 */
13713 }
13714 }
13715
13716 assert(lp->looseobjvalinf >= 0);
13717 assert(lp->pseudoobjvalinf >= 0);
13718 assert(lp->glbpseudoobjvalinf >= 0);
13719}
13720
13721/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13722 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13723 */
13724static
13726 SCIP_LP* lp, /**< current LP data */
13727 SCIP_SET* set, /**< global SCIP settings */
13728 SCIP_VAR* var, /**< problem variable that changed */
13729 SCIP_Real oldobj, /**< old objective value of variable */
13730 SCIP_Real oldlb, /**< old objective value of variable */
13731 SCIP_Real oldub, /**< old objective value of variable */
13732 SCIP_Real newobj, /**< new objective value of variable */
13733 SCIP_Real newlb, /**< new objective value of variable */
13734 SCIP_Real newub /**< new objective value of variable */
13735 )
13736{
13737 SCIP_INTERVAL deltaval;
13738 SCIP_INTERVAL bd;
13739 SCIP_INTERVAL obj;
13740 SCIP_INTERVAL prod;
13741 SCIP_INTERVAL psval;
13742 int deltainf;
13743
13744 assert(lp != NULL);
13745 assert(lp->pseudoobjvalinf >= 0);
13746 assert(lp->looseobjvalinf >= 0);
13747 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13748 assert(!SCIPsetIsInfinity(set, oldlb));
13749 assert(!SCIPsetIsInfinity(set, -oldub));
13750 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13751 assert(!SCIPsetIsInfinity(set, newlb));
13752 assert(!SCIPsetIsInfinity(set, -newub));
13753 assert(var != NULL);
13754
13756 {
13757 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13758 return SCIP_INVALIDDATA;
13759 }
13760
13761 assert(SCIPvarGetProbindex(var) >= 0);
13762
13763 SCIPintervalSet(&deltaval, 0.0);
13764 deltainf = 0;
13765
13766 /* subtract old pseudo objective value */
13767 if( oldobj > 0.0 )
13768 {
13769 if( SCIPsetIsInfinity(set, -oldlb) )
13770 deltainf--;
13771 else
13772 {
13773 SCIPintervalSet(&bd, oldlb);
13774 SCIPintervalSet(&obj, oldobj);
13775 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13776 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
13777 }
13778 }
13779 else if( oldobj < 0.0 )
13780 {
13781 if( SCIPsetIsInfinity(set, oldub) )
13782 deltainf--;
13783 else
13784 {
13785 SCIPintervalSet(&bd, oldub);
13786 SCIPintervalSet(&obj, oldobj);
13787 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13788 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
13789 }
13790 }
13791
13792 /* add new pseudo objective value */
13793 if( newobj > 0.0 )
13794 {
13795 if( SCIPsetIsInfinity(set, -newlb) )
13796 deltainf++;
13797 else
13798 {
13799 SCIPintervalSet(&bd, newlb);
13800 SCIPintervalSet(&obj, newobj);
13801 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13802 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
13803 }
13804 }
13805 else if( newobj < 0.0 )
13806 {
13807 if( SCIPsetIsInfinity(set, newub) )
13808 deltainf++;
13809 else
13810 {
13811 SCIPintervalSet(&bd, newub);
13812 SCIPintervalSet(&obj, newobj);
13813 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13814 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
13815 }
13816 }
13817
13818 /* update the pseudo and loose objective values */
13819 SCIPintervalSet(&psval, lp->pseudoobjval);
13820 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13821 lp->pseudoobjval = SCIPintervalGetInf(psval);
13822 lp->pseudoobjvalinf += deltainf;
13824 {
13825 SCIPintervalSet(&psval, lp->looseobjval);
13826 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13827 lp->looseobjval = SCIPintervalGetInf(psval);
13828 lp->looseobjvalinf += deltainf;
13829 }
13830
13831 assert(lp->pseudoobjvalinf >= 0);
13832 assert(lp->looseobjvalinf >= 0);
13833
13834 return SCIP_OKAY;
13835}
13836
13837/** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13839 SCIP_LP* lp, /**< current LP data */
13840 SCIP_SET* set, /**< global SCIP settings */
13841 SCIP_VAR* var, /**< problem variable that changed */
13842 SCIP_Real oldobj, /**< old objective coefficient of variable */
13843 SCIP_Real newobj /**< new objective coefficient of variable */
13844 )
13845{
13846 assert(set != NULL);
13847 assert(var != NULL);
13848
13849 if( set->misc_exactsolve )
13850 {
13851 if( oldobj != newobj ) /*lint !e777*/
13852 {
13854 newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
13855 }
13856 }
13857 else
13858 {
13859 if( !SCIPsetIsEQ(set, oldobj, newobj) )
13860 {
13861 SCIP_Real deltaval;
13862 int deltainf;
13863
13865 assert(SCIPvarGetProbindex(var) >= 0);
13866
13867 /* the objective coefficient can only be changed during presolving, that implies that the global and local
13868 * domain of the variable are the same
13869 */
13870 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
13871 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
13872
13873 /* compute the pseudo objective delta due the new objective coefficient */
13874 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
13875
13876 /* update the local pseudo objective value */
13877 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13878
13879 /* compute the pseudo objective delta due the new objective coefficient */
13880 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
13881
13882 /* update the global pseudo objective value */
13883 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13884 }
13885 }
13886
13887 return SCIP_OKAY;
13888}
13889
13890
13891/** updates current root pseudo objective value for a global change in a variable's lower bound */
13893 SCIP_LP* lp, /**< current LP data */
13894 SCIP_SET* set, /**< global SCIP settings */
13895 SCIP_VAR* var, /**< problem variable that changed */
13896 SCIP_Real oldlb, /**< old lower bound of variable */
13897 SCIP_Real newlb /**< new lower bound of variable */
13898 )
13899{
13900 assert(set != NULL);
13901 assert(var != NULL);
13902
13903 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13904 {
13905 SCIP_Real deltaval;
13906 int deltainf;
13907
13908 /* compute the pseudo objective delta due the new lower bound */
13909 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13910
13911 /* update the root pseudo objective values */
13912 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13913 }
13914
13915 return SCIP_OKAY;
13916}
13917
13918/** updates current pseudo and loose objective value for a change in a variable's lower bound */
13920 SCIP_LP* lp, /**< current LP data */
13921 SCIP_SET* set, /**< global SCIP settings */
13922 SCIP_VAR* var, /**< problem variable that changed */
13923 SCIP_Real oldlb, /**< old lower bound of variable */
13924 SCIP_Real newlb /**< new lower bound of variable */
13925 )
13926{
13927 assert(set != NULL);
13928 assert(var != NULL);
13929
13930 if( set->misc_exactsolve )
13931 {
13932 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13933 {
13934 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
13935 SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
13936 }
13937 }
13938 else
13939 {
13940 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13941 {
13942 SCIP_Real deltaval;
13943 int deltainf;
13944
13946 assert(SCIPvarGetProbindex(var) >= 0);
13947
13948 /* compute the pseudo objective delta due the new lower bound */
13949 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13950
13951 /* update the pseudo and loose objective values */
13952 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13953 }
13954 }
13955
13956 return SCIP_OKAY;
13957}
13958
13959/** updates current root pseudo objective value for a global change in a variable's upper bound */
13961 SCIP_LP* lp, /**< current LP data */
13962 SCIP_SET* set, /**< global SCIP settings */
13963 SCIP_VAR* var, /**< problem variable that changed */
13964 SCIP_Real oldub, /**< old upper bound of variable */
13965 SCIP_Real newub /**< new upper bound of variable */
13966 )
13967{
13968 assert(set != NULL);
13969 assert(var != NULL);
13970
13971 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13972 {
13973 SCIP_Real deltaval;
13974 int deltainf;
13975
13976 /* compute the pseudo objective delta due the new upper bound */
13977 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13978
13979 /* update the root pseudo objective values */
13980 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13981 }
13982
13983 return SCIP_OKAY;
13984}
13985
13986/** updates current pseudo objective value for a change in a variable's upper bound */
13988 SCIP_LP* lp, /**< current LP data */
13989 SCIP_SET* set, /**< global SCIP settings */
13990 SCIP_VAR* var, /**< problem variable that changed */
13991 SCIP_Real oldub, /**< old upper bound of variable */
13992 SCIP_Real newub /**< new upper bound of variable */
13993 )
13994{
13995 assert(set != NULL);
13996 assert(var != NULL);
13997
13998 if( set->misc_exactsolve )
13999 {
14000 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14001 {
14002 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
14003 SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
14004 }
14005 }
14006 else
14007 {
14008 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14009 {
14010 SCIP_Real deltaval;
14011 int deltainf;
14012
14014 assert(SCIPvarGetProbindex(var) >= 0);
14015
14016 /* compute the pseudo objective delta due the new upper bound */
14017 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14018
14019 /* update the pseudo and loose objective values */
14020 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14021 }
14022 }
14023
14024 return SCIP_OKAY;
14025}
14026
14027/** informs LP, that given variable was added to the problem */
14029 SCIP_LP* lp, /**< current LP data */
14030 SCIP_SET* set, /**< global SCIP settings */
14031 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
14032 )
14033{
14034 assert(lp != NULL);
14036 assert(SCIPvarGetProbindex(var) >= 0);
14037
14038 /* add the variable to the loose objective value sum */
14039 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
14040
14041 /* update the loose variables counter */
14043 lp->nloosevars++;
14044
14045 return SCIP_OKAY;
14046}
14047
14048/** informs LP, that given variable is to be deleted from the problem */
14050 SCIP_LP* lp, /**< current LP data */
14051 SCIP_SET* set, /**< global SCIP settings */
14052 SCIP_VAR* var /**< variable that will be deleted from the problem */
14053 )
14054{
14055 assert(lp != NULL);
14057 assert(SCIPvarGetProbindex(var) >= 0);
14058
14059 /* subtract the variable from the loose objective value sum */
14060 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
14061
14062 /* update the loose variables counter */
14064 {
14066 }
14067
14068 return SCIP_OKAY;
14069}
14070
14071/** informs LP, that given formerly loose problem variable is now a column variable */
14072static
14074 SCIP_LP* lp, /**< current LP data */
14075 SCIP_SET* set, /**< global SCIP settings */
14076 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14077 )
14078{
14079 SCIP_Real obj;
14080 SCIP_Real lb;
14081 SCIP_Real ub;
14082
14083 assert(lp != NULL);
14084 assert(lp->nloosevars > 0);
14086 assert(SCIPvarGetProbindex(var) >= 0);
14087 assert(lp->looseobjvalinf >= 0);
14088
14089 obj = SCIPvarGetObj(var);
14090
14091 /* update loose objective value */
14092 if( SCIPsetIsPositive(set, obj) )
14093 {
14094 lb = SCIPvarGetLbLocal(var);
14095 if( SCIPsetIsInfinity(set, -lb) )
14096 lp->looseobjvalinf--;
14097 else
14098 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14099 }
14100 else if( SCIPsetIsNegative(set, obj) )
14101 {
14102 ub = SCIPvarGetUbLocal(var);
14103 if( SCIPsetIsInfinity(set, ub) )
14104 lp->looseobjvalinf--;
14105 else
14106 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14107 }
14108
14110
14111 assert(lp->looseobjvalinf >= 0);
14112
14113 return SCIP_OKAY;
14114}
14115
14116/** informs LP, that given formerly loose problem variable is now a column variable
14117 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14118 */
14119static
14121 SCIP_LP* lp, /**< current LP data */
14122 SCIP_SET* set, /**< global SCIP settings */
14123 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14124 )
14125{
14126 SCIP_INTERVAL bd;
14127 SCIP_INTERVAL ob;
14128 SCIP_INTERVAL prod;
14129 SCIP_INTERVAL loose;
14130 SCIP_Real obj;
14131 SCIP_Real lb;
14132 SCIP_Real ub;
14133
14134 assert(lp != NULL);
14135 assert(lp->nloosevars > 0);
14137 assert(SCIPvarGetProbindex(var) >= 0);
14138
14139 obj = SCIPvarGetObj(var);
14140
14141 SCIPintervalSet(&loose, lp->looseobjval);
14142
14143 /* update loose objective value corresponding to the deletion of variable */
14144 if( obj > 0.0 )
14145 {
14146 lb = SCIPvarGetLbLocal(var);
14147 if( SCIPsetIsInfinity(set, -lb) )
14148 lp->looseobjvalinf--;
14149 else
14150 {
14151 SCIPintervalSet(&bd, lb);
14152 SCIPintervalSet(&ob, obj);
14153 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14154 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
14155 }
14156 }
14157 else if( SCIPsetIsNegative(set, obj) )
14158 {
14159 ub = SCIPvarGetUbLocal(var);
14160 if( SCIPsetIsInfinity(set, ub) )
14161 lp->looseobjvalinf--;
14162 else
14163 {
14164 SCIPintervalSet(&bd, ub);
14165 SCIPintervalSet(&ob, obj);
14166 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14167 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
14168 }
14169 }
14170 lp->nloosevars--;
14171
14172 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14173 if( lp->nloosevars == 0 )
14174 {
14175 assert(lp->looseobjvalinf == 0);
14176 lp->looseobjval = 0.0;
14177 }
14178 else
14179 lp->looseobjval = SCIPintervalGetInf(loose);
14180
14181 return SCIP_OKAY;
14182}
14183
14184/** informs LP, that given formerly loose problem variable is now a column variable */
14186 SCIP_LP* lp, /**< current LP data */
14187 SCIP_SET* set, /**< global SCIP settings */
14188 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14189 )
14190{
14191 assert(set != NULL);
14192
14193 if( set->misc_exactsolve )
14194 {
14196 }
14197 else
14198 {
14199 SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
14200 }
14201
14202 return SCIP_OKAY;
14203}
14204
14205/** informs LP, that given formerly column problem variable is now again a loose variable */
14206static
14208 SCIP_LP* lp, /**< current LP data */
14209 SCIP_SET* set, /**< global SCIP settings */
14210 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14211 )
14212{
14213 SCIP_Real obj;
14214 SCIP_Real lb;
14215 SCIP_Real ub;
14216
14217 assert(lp != NULL);
14218 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14219 assert(SCIPvarGetProbindex(var) >= 0);
14220 assert(lp->looseobjvalinf >= 0);
14221
14222 obj = SCIPvarGetObj(var);
14223
14224 /* update loose objective value corresponding to the addition of variable */
14225 if( SCIPsetIsPositive(set, obj) )
14226 {
14227 lb = SCIPvarGetLbLocal(var);
14228 if( SCIPsetIsInfinity(set, -lb) )
14229 lp->looseobjvalinf++;
14230 else
14231 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14232 }
14233 else if( SCIPsetIsNegative(set, obj) )
14234 {
14235 ub = SCIPvarGetUbLocal(var);
14236 if( SCIPsetIsInfinity(set, ub) )
14237 lp->looseobjvalinf++;
14238 else
14239 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14240 }
14241 lp->nloosevars++;
14242
14243 assert(lp->looseobjvalinf >= 0);
14244
14245 return SCIP_OKAY;
14246}
14247
14248/** informs LP, that given formerly column problem variable is now again a loose variable
14249 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14250 */
14251static
14253 SCIP_LP* lp, /**< current LP data */
14254 SCIP_SET* set, /**< global SCIP settings */
14255 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14256 )
14257{
14258 SCIP_INTERVAL bd;
14259 SCIP_INTERVAL ob;
14260 SCIP_INTERVAL prod;
14261 SCIP_INTERVAL loose;
14262 SCIP_Real obj;
14263 SCIP_Real lb;
14264 SCIP_Real ub;
14265
14266 assert(lp != NULL);
14267 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14268 assert(SCIPvarGetProbindex(var) >= 0);
14269
14270 obj = SCIPvarGetObj(var);
14271
14272 SCIPintervalSet(&loose, lp->looseobjval);
14273
14274 /* update loose objective value corresponding to the deletion of variable */
14275 if( obj > 0.0 )
14276 {
14277 lb = SCIPvarGetLbLocal(var);
14278 if( SCIPsetIsInfinity(set, -lb) )
14279 lp->looseobjvalinf++;
14280 else
14281 {
14282 SCIPintervalSet(&bd, lb);
14283 SCIPintervalSet(&ob, obj);
14284 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14285 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
14286 }
14287 }
14288 else if( SCIPsetIsNegative(set, obj) )
14289 {
14290 ub = SCIPvarGetUbLocal(var);
14291 if( SCIPsetIsInfinity(set, ub) )
14292 lp->looseobjvalinf++;
14293 else
14294 {
14295 SCIPintervalSet(&bd, ub);
14296 SCIPintervalSet(&ob, obj);
14297 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14298 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
14299 }
14300 }
14301 lp->nloosevars++;
14302
14303 lp->looseobjval = SCIPintervalGetInf(loose);
14304
14305 return SCIP_OKAY;
14306}
14307
14308/** informs LP, that given formerly column problem variable is now again a loose variable */
14310 SCIP_LP* lp, /**< current LP data */
14311 SCIP_SET* set, /**< global SCIP settings */
14312 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14313 )
14314{
14315 assert(set != NULL);
14316
14317 if( set->misc_exactsolve )
14318 {
14320 }
14321 else
14322 {
14323 SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
14324 }
14325
14326 return SCIP_OKAY;
14327}
14328
14329/** decrease the number of loose variables by one */
14331 SCIP_LP* lp /**< current LP data */
14332 )
14333{
14334 assert(lp != NULL);
14335 assert(lp->nloosevars > 0);
14336
14337 lp->nloosevars--;
14338
14339 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14340 if( lp->nloosevars == 0 )
14341 {
14342 assert(lp->looseobjvalinf == 0);
14343 lp->looseobjval = 0.0;
14344 }
14345}
14346
14347/** stores the LP solution in the columns and rows */
14349 SCIP_LP* lp, /**< current LP data */
14350 SCIP_SET* set, /**< global SCIP settings */
14351 SCIP_STAT* stat, /**< problem statistics */
14352 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14353 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
14354 )
14355{
14356 SCIP_COL** lpicols;
14357 SCIP_ROW** lpirows;
14358 SCIP_Real* primsol;
14359 SCIP_Real* dualsol;
14360 SCIP_Real* activity = NULL;
14361 SCIP_Real* redcost;
14362 SCIP_Real primalbound;
14363 SCIP_Real dualbound;
14364 SCIP_Bool stillprimalfeasible;
14365 SCIP_Bool stilldualfeasible;
14366 int* cstat;
14367 int* rstat;
14368 SCIP_Longint lpcount;
14369 int nlpicols;
14370 int nlpirows;
14371 int c;
14372 int r;
14373
14374 assert(lp != NULL);
14375 assert(lp->flushed);
14376 assert(lp->solved);
14377 assert(set != NULL);
14378 assert(stat != NULL);
14379 assert(lp->validsollp <= stat->lpcount);
14380
14381 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
14382
14383 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14384 * corresponding flag immediately to FALSE to skip all checks
14385 */
14386 if( primalfeasible == NULL )
14387 stillprimalfeasible = FALSE;
14388 else
14389 {
14390 *primalfeasible = TRUE;
14391 stillprimalfeasible = TRUE;
14392 }
14393 if( dualfeasible == NULL )
14394 stilldualfeasible = FALSE;
14395 else
14396 {
14397 *dualfeasible = TRUE;
14398 stilldualfeasible = TRUE;
14399 }
14400
14401 /* check if the values are already calculated */
14402 if( lp->validsollp == stat->lpcount )
14403 return SCIP_OKAY;
14404 lp->validsollp = stat->lpcount;
14405
14406 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14407 stat->lpcount, SCIPlpGetSolstat(lp));
14408
14409 lpicols = lp->lpicols;
14410 lpirows = lp->lpirows;
14411 nlpicols = lp->nlpicols;
14412 nlpirows = lp->nlpirows;
14413 lpcount = stat->lpcount;
14414
14415 /* get temporary memory */
14416 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
14417 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14418#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14419 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14420#endif
14421 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14422 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14423 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14424
14425 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14426 if( lp->solisbasic )
14427 {
14428 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14429 }
14430 else
14431 {
14432 BMSclearMemoryArray(cstat, nlpicols);
14433 BMSclearMemoryArray(rstat, nlpirows);
14434 }
14435
14436 primalbound = 0.0;
14437 dualbound = 0.0;
14438
14439 /* copy primal solution and reduced costs into columns */
14440 for( c = 0; c < nlpicols; ++c )
14441 {
14442 assert( 0 <= cstat[c] && cstat[c] < 4 );
14443 lpicols[c]->primsol = primsol[c];
14444 if( !SCIPisFinite(lpicols[c]->primsol) )
14445 {
14446 /* calculating with nan or +/-inf can have many unexpected effects
14447 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14448 * this should trigger a resolve of the LP, or a stop with an LP error
14449 */
14450 stillprimalfeasible = FALSE;
14451 stilldualfeasible = FALSE;
14452 lpicols[c]->primsol = 0.0;
14453 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14454 }
14455 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14456 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14457 lpicols[c]->redcost = redcost[c];
14458 lpicols[c]->basisstatus = (unsigned int) cstat[c];
14459 lpicols[c]->validredcostlp = lpcount;
14460 if( stillprimalfeasible )
14461 {
14462 stillprimalfeasible =
14463 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14464 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14465 primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14466 }
14467 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14468 {
14469 double compslack;
14470
14471 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14472 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14473 * variables, which would magnify even the tiniest violation in the dual multiplier
14474 */
14475 if( stilldualfeasible )
14476 {
14477 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14478 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14479 }
14480 if( stilldualfeasible )
14481 {
14482 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14483 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14484 }
14485
14486 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14487 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14488 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14489 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14490 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14491 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14492 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14493 dualfeasible != NULL ? stilldualfeasible : TRUE);
14494 }
14495 else
14496 {
14497 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14498 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14499 {
14500 lpicols[c]->redcost = 0.0;
14501 }
14502
14503 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14504 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14505 * bounds, its reduced cost must be zero
14506 */
14507 if( stilldualfeasible
14508 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14509 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14510 if( stilldualfeasible
14511 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14512 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14513
14514 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14515 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14516 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14517 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14518 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14519 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14520 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14521 dualfeasible != NULL ? stilldualfeasible : TRUE);
14522 }
14523
14524 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14525 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14526 * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14527 */
14528 if( stilldualfeasible )
14529 {
14530 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14531 dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14532 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14533 dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14534 }
14535 }
14536
14537 /* copy dual solution and activities into rows */
14538 for( r = 0; r < nlpirows; ++r )
14539 {
14540 assert( 0 <= rstat[r] && rstat[r] < 4 );
14541 lpirows[r]->dualsol = dualsol[r];
14542#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14543 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14544#else
14545 /* calculate row activity if invalid */
14546 if( lpirows[r]->validactivitylp != stat->lpcount )
14547 SCIProwRecalcLPActivity(lpirows[r], stat);
14548#endif
14549 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14550 lpirows[r]->validactivitylp = lpcount;
14551 if( stillprimalfeasible )
14552 {
14553 stillprimalfeasible =
14554 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14555 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14556 }
14557 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14558 {
14559 double compslack;
14560
14561 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14562 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14563 * variables, which would magnify even the tiniest violation in the dual multiplier
14564 */
14565 if( stilldualfeasible )
14566 {
14567 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14568 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14569 }
14570 if( stilldualfeasible )
14571 {
14572 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14573 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14574 }
14575
14576 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14577 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14578 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14579 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14580 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14581 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14582 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14583 dualfeasible != NULL ? stilldualfeasible : TRUE);
14584 }
14585 else
14586 {
14587 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14588 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14589 * strictly within left-hand and right-hand side, its dual multiplier must be zero
14590 */
14591 if( stilldualfeasible &&
14592 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14593 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14594 if( stilldualfeasible &&
14595 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14596 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14597
14598 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14599 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14600 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14601 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14602 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14603 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14604 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14605 dualfeasible != NULL ? stilldualfeasible : TRUE);
14606 }
14607
14608 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14609 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14610 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14611 */
14612 if( stilldualfeasible )
14613 {
14614 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14615 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14616 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14617 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14618 }
14619 }
14620
14621 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14622 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14623 * infinity
14624 */
14625 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14626 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14627 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14628 {
14629 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14630 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14631 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14632 }
14633
14634 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14635 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14636 */
14637 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14638 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14639 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14640 {
14641 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14642 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14643 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14644 }
14645
14646 if( primalfeasible != NULL )
14647 *primalfeasible = stillprimalfeasible;
14648 if( dualfeasible != NULL )
14649 *dualfeasible = stilldualfeasible;
14650
14651 /* free temporary memory */
14652 SCIPsetFreeBufferArray(set, &rstat);
14653 SCIPsetFreeBufferArray(set, &cstat);
14654 SCIPsetFreeBufferArray(set, &redcost);
14655#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14656 SCIPsetFreeBufferArray(set, &activity);
14657#endif
14658 SCIPsetFreeBufferArray(set, &dualsol);
14659 SCIPsetFreeBufferArray(set, &primsol);
14660
14661 return SCIP_OKAY;
14662}
14663
14664/** stores LP solution with infinite objective value in the columns and rows */
14666 SCIP_LP* lp, /**< current LP data */
14667 SCIP_SET* set, /**< global SCIP settings */
14668 SCIP_STAT* stat, /**< problem statistics */
14669 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14670 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14671 )
14672{
14673 SCIP_COL** lpicols;
14674 SCIP_ROW** lpirows;
14675 SCIP_Real* primsol;
14676 SCIP_Real* activity;
14677 SCIP_Real* ray;
14678 SCIP_Real rayobjval;
14679 SCIP_Real rayscale;
14680 SCIP_Longint lpcount;
14681 SCIP_COL* col;
14682 int nlpicols;
14683 int nlpirows;
14684 int c;
14685 int r;
14686
14687 assert(lp != NULL);
14688 assert(lp->flushed);
14689 assert(lp->solved);
14691 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
14692 assert(set != NULL);
14693 assert(stat != NULL);
14694 assert(lp->validsollp <= stat->lpcount);
14695
14696 if( primalfeasible != NULL )
14697 *primalfeasible = TRUE;
14698 if( rayfeasible != NULL )
14699 *rayfeasible = TRUE;
14700
14701 /* check if the values are already calculated */
14702 if( lp->validsollp == stat->lpcount )
14703 return SCIP_OKAY;
14704 lp->validsollp = stat->lpcount;
14705
14706 /* check if the LP solver is able to provide a primal unbounded ray */
14707 if( !SCIPlpiHasPrimalRay(lp->lpi) )
14708 {
14709 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14710 return SCIP_LPERROR;
14711 }
14712
14713 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14714
14715 /* get temporary memory */
14716 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
14717 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14719
14720 /* get primal unbounded ray */
14721 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14722
14723 lpicols = lp->lpicols;
14724 lpirows = lp->lpirows;
14725 nlpicols = lp->nlpicols;
14726 nlpirows = lp->nlpirows;
14727 lpcount = stat->lpcount;
14728
14729 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14730 rayobjval = 0.0;
14731 for( c = 0; c < nlpicols; ++c )
14732 {
14733 assert(lpicols[c] != NULL);
14734 assert(lpicols[c]->var != NULL);
14735
14736 col = lpicols[c];
14737
14738 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14739 if( rayfeasible != NULL )
14740 {
14741 *rayfeasible = *rayfeasible
14742 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14743 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub));
14744 }
14745
14746 if( ! SCIPsetIsZero(set, ray[c]) )
14747 rayobjval += ray[c] * col->obj;
14748
14749 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14750 * heuristically try to construct a primal solution.
14751 */
14752 primsol[c] = 0.0;
14753 if( SCIPsetIsFeasZero(set, ray[c]) )
14754 {
14755 /* if the ray component is 0, we try to satisfy as many rows as possible */
14756 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14757 primsol[c] = col->lb;
14758 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14759 primsol[c] = col->ub;
14760 }
14761
14762 /* make sure we respect the bounds */
14763 primsol[c] = MAX(primsol[c], col->lb);
14764 primsol[c] = MIN(primsol[c], col->ub);
14765
14766 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14767 }
14768
14769 /* check feasibility of heuristic primal solution */
14770 for( r = 0; r < nlpirows; ++r )
14771 {
14772 SCIP_Real act;
14773 SCIP_ROW* row;
14774
14775 row = lpirows[r];
14776 assert( row != NULL );
14777 act = row->constant;
14778
14779 for( c = 0; c < row->nlpcols; ++c )
14780 {
14781 col = row->cols[c];
14782
14783 assert( col != NULL );
14784 assert( col->lppos >= 0 );
14785 assert( row->linkpos[c] >= 0 );
14786 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14787
14788 act += row->vals[c] * primsol[col->lppos];
14789 }
14790
14791 if( row->nunlinked > 0 )
14792 {
14793 for( c = row->nlpcols; c < row->len; ++c )
14794 {
14795 col = row->cols[c];
14796 assert( col != NULL );
14797
14798 if( col->lppos >= 0 )
14799 act += row->vals[c] * primsol[col->lppos];
14800 }
14801 }
14802
14803 /* check feasibility */
14804 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14805 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14806 break;
14807 }
14808
14809 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14810 if( r < nlpirows )
14811 {
14812 /* get primal feasible point */
14813 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
14814
14815 /* check bounds of primal solution */
14816 if( primalfeasible != NULL )
14817 {
14818 assert( *primalfeasible );
14819 for( c = 0; c < nlpicols; ++c )
14820 {
14821 assert( lpicols[c] != NULL );
14822 assert( lpicols[c]->var != NULL );
14823
14824 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14825 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14826 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14827 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14828 {
14829 *primalfeasible = FALSE;
14830 break;
14831 }
14832 }
14833 }
14834 }
14835
14836 /* compute activity and check feasibility of primal solution and ray */
14837 for( r = 0; r < nlpirows; ++r )
14838 {
14839 SCIP_Real primact;
14840 SCIP_Real rayact = 0.0;
14841 SCIP_ROW* row;
14842
14843 row = lpirows[r];
14844 assert( row != NULL );
14845
14846 primact = row->constant;
14847
14848 for( c = 0; c < row->nlpcols; ++c )
14849 {
14850 col = row->cols[c];
14851
14852 assert( col != NULL );
14853 assert( col->lppos >= 0 );
14854 assert( row->linkpos[c] >= 0 );
14855 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14856
14857 primact += row->vals[c] * primsol[col->lppos];
14858 rayact += row->vals[c] * ray[col->lppos];
14859 }
14860
14861 if( row->nunlinked > 0 )
14862 {
14863 for( c = row->nlpcols; c < row->len; ++c )
14864 {
14865 col = row->cols[c];
14866 assert( col != NULL );
14867
14868 if( col->lppos >= 0 )
14869 {
14870 primact += row->vals[c] * primsol[col->lppos];
14871 rayact += row->vals[c] * ray[col->lppos];
14872 }
14873 }
14874 }
14875
14876 /* check feasibility of primal solution */
14877 if( primalfeasible != NULL && *primalfeasible )
14878 {
14879 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14880 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14881 *primalfeasible = FALSE;
14882 }
14883
14884 /* check feasibility of ray */
14885 if( rayfeasible != NULL && *rayfeasible )
14886 {
14887 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14888 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14889 *rayfeasible = FALSE;
14890 }
14891
14892 /* store activity of primal solution */
14893 activity[r] = primact;
14894 }
14895
14896 if( primalfeasible != NULL && !(*primalfeasible) )
14897 {
14898 /* if the finite point is already infeasible, we do not have to add the ray */
14899 rayscale = 0.0;
14900 }
14901 else if( rayfeasible != NULL && !(*rayfeasible) )
14902 {
14903 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14904 rayscale = 0.0;
14905 }
14906 else if( !SCIPsetIsNegative(set, rayobjval) )
14907 {
14908 /* due to numerical problems, the objective of the ray might be nonnegative
14909 *
14910 * @todo How to check for negative objective value here?
14911 */
14912 if( rayfeasible != NULL )
14913 *rayfeasible = FALSE;
14914
14915 rayscale = 0.0;
14916 }
14917 else
14918 {
14919 assert(rayobjval != 0.0);
14920
14921 /* scale the ray, such that the resulting point has infinite objective value */
14922 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14923 assert(SCIPsetIsFeasPositive(set, rayscale));
14924
14925 /* ensure that unbounded point does not violate the bounds of the variables */
14926 for( c = 0; c < nlpicols; ++c )
14927 {
14928 if( SCIPsetIsPositive(set, ray[c]) )
14929 {
14930 if( !SCIPsetIsInfinity(set, primsol[c]) )
14931 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14932 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14933 else
14934 {
14935 assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14936 rayscale = MIN(rayscale, 1.0 / ray[c]);
14937 }
14938 }
14939 else if( SCIPsetIsNegative(set, ray[c]) )
14940 {
14941 if( !SCIPsetIsInfinity(set, -primsol[c]) )
14942 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14943 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14944 else
14945 {
14946 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14947 rayscale = MIN(rayscale, -1.0 / ray[c]);
14948 }
14949 }
14950
14951 assert(SCIPsetIsFeasPositive(set, rayscale));
14952 }
14953 }
14954
14955 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14956
14957 /* calculate the unbounded point: x' = x + rayscale * ray */
14958 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14959 * typically large values in scaling. */
14960 for( c = 0; c < nlpicols; ++c )
14961 {
14962 if( SCIPsetIsZero(set, ray[c]) )
14963 lpicols[c]->primsol = primsol[c];
14964 else
14965 {
14966 SCIP_Real primsolval;
14967 primsolval = primsol[c] + rayscale * ray[c];
14968 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14969 }
14970 lpicols[c]->redcost = SCIP_INVALID;
14971 lpicols[c]->validredcostlp = -1;
14972 }
14973
14974 /* transfer solution */
14975 for( r = 0; r < nlpirows; ++r )
14976 {
14977 lpirows[r]->dualsol = SCIP_INVALID;
14978 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14979 lpirows[r]->validactivitylp = lpcount;
14980 }
14981
14982 /* free temporary memory */
14984 SCIPsetFreeBufferArray(set, &activity);
14985 SCIPsetFreeBufferArray(set, &primsol);
14986
14987 return SCIP_OKAY;
14988}
14989
14990/** returns primal ray proving the unboundedness of the current LP */
14992 SCIP_LP* lp, /**< current LP data */
14993 SCIP_SET* set, /**< global SCIP settings */
14994 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
14995 * so the size of this array should be at least number of active variables
14996 * (all entries have to be initialized to 0 before) */
14997 )
14998{
14999 SCIP_COL** lpicols;
15000 SCIP_Real* lpiray;
15001 SCIP_VAR* var;
15002 int nlpicols;
15003 int c;
15004
15005 assert(lp != NULL);
15006 assert(set != NULL);
15007 assert(ray != NULL);
15008 assert(lp->flushed);
15009 assert(lp->solved);
15011 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
15012
15013 /* check if the LP solver is able to provide a primal unbounded ray */
15014 if( !SCIPlpiHasPrimalRay(lp->lpi) )
15015 {
15016 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15017 return SCIP_LPERROR;
15018 }
15019
15020 /* get temporary memory */
15022
15023 SCIPsetDebugMsg(set, "getting primal ray values\n");
15024
15025 /* get primal unbounded ray */
15026 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15027
15028 lpicols = lp->lpicols;
15029 nlpicols = lp->nlpicols;
15030
15031 /* store the ray values of active problem variables */
15032 for( c = 0; c < nlpicols; c++ )
15033 {
15034 assert(lpicols[c] != NULL);
15035
15036 var = lpicols[c]->var;
15037 assert(var != NULL);
15038 assert(SCIPvarGetProbindex(var) != -1);
15039 ray[SCIPvarGetProbindex(var)] = lpiray[c];
15040 }
15041
15042 SCIPsetFreeBufferArray(set, &lpiray);
15043
15044 return SCIP_OKAY;
15045}
15046
15047/** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15048 * lp/checkfarkas = TRUE.
15049 *
15050 * @note the check will not be performed if @p valid is NULL.
15051 */
15053 SCIP_LP* lp, /**< current LP data */
15054 SCIP_SET* set, /**< global SCIP settings */
15055 SCIP_STAT* stat, /**< problem statistics */
15056 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */
15057 )
15058{
15059 SCIP_COL** lpicols;
15060 SCIP_ROW** lpirows;
15061 SCIP_Real* dualfarkas;
15062 SCIP_Real* farkascoefs;
15063 SCIP_Real farkaslhs;
15064 SCIP_Real maxactivity;
15065 SCIP_Bool checkfarkas;
15066 int nlpicols;
15067 int nlpirows;
15068 int c;
15069 int r;
15070
15071 assert(lp != NULL);
15072 assert(lp->flushed);
15073 assert(lp->solved);
15074 assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
15075 assert(set != NULL);
15076 assert(stat != NULL);
15077 assert(lp->validfarkaslp <= stat->lpcount);
15078
15079 if( valid != NULL )
15080 *valid = TRUE;
15081
15082 /* check if the values are already calculated */
15083 if( lp->validfarkaslp == stat->lpcount )
15084 return SCIP_OKAY;
15085 lp->validfarkaslp = stat->lpcount;
15086
15087 farkascoefs = NULL;
15088 maxactivity = 0.0;
15089 farkaslhs = 0.0;
15090
15091 checkfarkas = (set->lp_checkfarkas && valid != NULL);
15092
15093 /* get temporary memory */
15094 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15095
15096 if( checkfarkas )
15097 {
15098 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15099 BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15100 }
15101
15102 /* get dual Farkas infeasibility proof */
15103 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15104
15105 lpicols = lp->lpicols;
15106 lpirows = lp->lpirows;
15107 nlpicols = lp->nlpicols;
15108 nlpirows = lp->nlpirows;
15109
15110 /* store infeasibility proof in rows */
15111 SCIPsetDebugMsg(set, "LP is infeasible:\n");
15112 for( r = 0; r < nlpirows; ++r )
15113 {
15114 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15115 lpirows[r]->dualfarkas = dualfarkas[r];
15116 lpirows[r]->dualsol = SCIP_INVALID;
15117 lpirows[r]->activity = 0.0;
15118 lpirows[r]->validactivitylp = -1L;
15119 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15120
15121 if( checkfarkas )
15122 {
15123 assert(farkascoefs != NULL);
15124
15125 /* the infeasibility proof would be invalid if
15126 * (i) dualfarkas[r] > 0 and lhs = -inf
15127 * (ii) dualfarkas[r] < 0 and rhs = inf
15128 * however, due to numerics we accept slightly negative / positive values
15129 */
15130 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15131 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15132 {
15133 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15134 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15135
15136 if( valid != NULL )
15137 *valid = FALSE;
15138
15139 goto TERMINATE;
15140 }
15141
15142 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15143 * within tolerances (see above) but slighty positive / negative
15144 */
15145 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15146 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15147 continue;
15148
15149 /* iterate over all columns and scale with dual solution */
15150 for( c = 0; c < lpirows[r]->len; c++ )
15151 {
15152 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15153
15154 if( pos == -1 )
15155 continue;
15156
15157 assert(pos >= 0 && pos < nlpicols);
15158
15159 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15160 }
15161
15162 /* the row contributes with its left-hand side to the proof */
15163 if( dualfarkas[r] > 0.0 )
15164 {
15165 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15166
15167 farkaslhs += dualfarkas[r] * (lpirows[r]->lhs - lpirows[r]->constant);
15168 }
15169 /* the row contributes with its right-hand side to the proof */
15170 else if( dualfarkas[r] < 0.0 )
15171 {
15172 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15173
15174 farkaslhs += dualfarkas[r] * (lpirows[r]->rhs - lpirows[r]->constant);
15175 }
15176 }
15177 }
15178
15179 /* set columns as invalid */
15180 for( c = 0; c < nlpicols; ++c )
15181 {
15182 lpicols[c]->primsol = SCIP_INVALID;
15183 lpicols[c]->redcost = SCIP_INVALID;
15184 lpicols[c]->validredcostlp = -1L;
15185 lpicols[c]->validfarkaslp = -1L;
15186
15187 if( checkfarkas )
15188 {
15189 assert(farkascoefs != NULL);
15190 assert(SCIPcolGetLPPos(lpicols[c]) == c);
15191
15192 /* skip coefficients that are too close to zero */
15193 if( SCIPsetIsFeasZero(set, farkascoefs[c]) )
15194 continue;
15195
15196 /* calculate the maximal activity */
15197 if( farkascoefs[c] > 0.0 )
15198 maxactivity += farkascoefs[c] * SCIPcolGetUb(lpicols[c]);
15199 else
15200 maxactivity += farkascoefs[c] * SCIPcolGetLb(lpicols[c]);
15201 }
15202 }
15203
15204 /* check whether the farkasproof is valid
15205 * due to numerics, it might happen that the left-hand side of the aggregation is larger/smaller or equal than +/- infinity.
15206 * in that case, we declare the Farkas proof to be invalid.
15207 */
15208 if( checkfarkas && (SCIPsetIsInfinity(set, REALABS(farkaslhs)) || SCIPsetIsGE(set, maxactivity, farkaslhs)) )
15209 {
15210 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15211
15212 if( valid != NULL )
15213 *valid = FALSE;
15214 }
15215
15216 TERMINATE:
15217 /* free temporary memory */
15218 if( checkfarkas )
15219 SCIPsetFreeBufferArray(set, &farkascoefs);
15220
15221 SCIPsetFreeBufferArray(set, &dualfarkas);
15222
15223 return SCIP_OKAY;
15224}
15225
15226/** get number of iterations used in last LP solve */
15228 SCIP_LP* lp, /**< current LP data */
15229 int* iterations /**< pointer to store the iteration count */
15230 )
15231{
15232 assert(lp != NULL);
15233
15234 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15235
15236 return SCIP_OKAY;
15237}
15238
15239/** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15240 * resets age of non-zero columns and sharp rows
15241 */
15243 SCIP_LP* lp, /**< current LP data */
15244 SCIP_STAT* stat /**< problem statistics */
15245 )
15246{
15247 SCIP_COL** lpicols;
15248 SCIP_ROW** lpirows;
15249 int nlpicols;
15250 int nlpirows;
15251 int c;
15252 int r;
15253
15254 assert(lp != NULL);
15255 assert(lp->flushed);
15256 assert(lp->solved);
15257 assert(lp->nlpicols == lp->ncols);
15258 assert(lp->nlpirows == lp->nrows);
15259 assert(stat != NULL);
15260 assert(lp->validsollp == stat->lpcount);
15261
15262 SCIPdebugMessage("updating LP ages\n");
15263
15264 lpicols = lp->lpicols;
15265 lpirows = lp->lpirows;
15266 nlpicols = lp->nlpicols;
15267 nlpirows = lp->nlpirows;
15268
15269 for( c = 0; c < nlpicols; ++c )
15270 {
15271 assert(lpicols[c] == lp->cols[c]);
15272 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
15273 lpicols[c]->age++;
15274 else
15275 lpicols[c]->age = 0;
15276 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15277 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15278 }
15279
15280 for( r = 0; r < nlpirows; ++r )
15281 {
15282 lpirows[r]->nlpsaftercreation++;
15283 assert(lpirows[r] == lp->rows[r]);
15284
15285 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15286 {
15287 lpirows[r]->age++;
15288 }
15289 else
15290 {
15291 lpirows[r]->activeinlpcounter++;
15292 lpirows[r]->age = 0;
15293 }
15294 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15295 }
15296
15297 return SCIP_OKAY;
15298}
15299
15300/* deletes the marked columns from the LP and the LP interface */
15301static
15303 SCIP_LP* lp, /**< current LP data */
15304 SCIP_SET* set, /**< global SCIP settings */
15305 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
15306 )
15307{
15308 SCIP_COL* col;
15309 int ncols;
15310 int c;
15311
15312 assert(lp != NULL);
15313 assert(lp->flushed);
15314 assert(lp->ncols == lp->nlpicols);
15315 assert(!lp->diving);
15316 assert(coldstat != NULL);
15317 assert(lp->nlazycols <= lp->ncols);
15318
15319 ncols = lp->ncols;
15320
15321 /* delete columns in LP solver */
15322 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15323
15324 /* update LP data respectively */
15325 for( c = 0; c < ncols; ++c )
15326 {
15327 col = lp->cols[c];
15328 assert(col != NULL);
15329 assert(col == lp->lpicols[c]);
15330 assert(coldstat[c] <= c);
15331 col->lppos = coldstat[c];
15332 if( coldstat[c] == -1 )
15333 {
15334 assert(col->removable);
15335
15336 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15337 * function vector norms
15338 */
15339 markColDeleted(col);
15340 colUpdateDelLP(col, set);
15341 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15342 col->lpdepth = -1;
15343
15344 lp->cols[c] = NULL;
15345 lp->lpicols[c] = NULL;
15346 lp->ncols--;
15347 lp->nremovablecols--;
15348 lp->nlpicols--;
15349 }
15350 else if( coldstat[c] < c )
15351 {
15352 assert(lp->cols[coldstat[c]] == NULL);
15353 assert(lp->lpicols[coldstat[c]] == NULL);
15354 lp->cols[coldstat[c]] = col;
15355 lp->lpicols[coldstat[c]] = col;
15356 lp->cols[coldstat[c]]->lppos = coldstat[c];
15357 lp->cols[coldstat[c]]->lpipos = coldstat[c];
15358 lp->cols[c] = NULL;
15359 lp->lpicols[c] = NULL;
15360 }
15361 }
15362
15363 /* remove columns which are deleted from the lazy column array */
15364 c = 0;
15365 while( c < lp->nlazycols )
15366 {
15367 if( lp->lazycols[c]->lpipos < 0 )
15368 {
15369 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15370 lp->nlazycols--;
15371 }
15372 else
15373 c++;
15374 }
15375
15376 /* mark LP to be unsolved */
15377 if( lp->ncols < ncols )
15378 {
15379 assert(lp->ncols == lp->nlpicols);
15380 assert(lp->nchgcols == 0);
15381 assert(lp->flushed);
15382
15383 lp->lpifirstchgcol = lp->nlpicols;
15384
15385 /* mark the current solution invalid */
15386 lp->solved = FALSE;
15387 lp->primalfeasible = FALSE;
15388 lp->primalchecked = FALSE;
15389 lp->lpobjval = SCIP_INVALID;
15391 }
15392
15394 checkLinks(lp);
15395
15396 return SCIP_OKAY;
15397}
15398
15399/* deletes the marked rows from the LP and the LP interface */
15400static
15402 SCIP_LP* lp, /**< current LP data */
15403 BMS_BLKMEM* blkmem, /**< block memory buffers */
15404 SCIP_SET* set, /**< global SCIP settings */
15405 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15406 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15407 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
15408 )
15409{
15410 SCIP_ROW* row;
15411 int nrows;
15412 int r;
15413
15414 assert(lp != NULL);
15415 assert(lp->flushed);
15416 assert(lp->nrows == lp->nlpirows);
15417 assert(!lp->diving);
15418 assert(rowdstat != NULL);
15419
15420 nrows = lp->nrows;
15421
15422 /* delete rows in LP solver */
15423 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15424
15425 /* update LP data respectively */
15426 for( r = 0; r < nrows; ++r )
15427 {
15428 row = lp->rows[r];
15429 assert(row == lp->lpirows[r]);
15430 assert(rowdstat[r] <= r);
15431 assert(row != NULL);
15432 row->lppos = rowdstat[r];
15433 if( rowdstat[r] == -1 )
15434 {
15435 if( row->removable )
15436 lp->nremovablerows--;
15437
15438 /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15439 markRowDeleted(row);
15440 rowUpdateDelLP(row);
15441 row->lpdepth = -1;
15442
15443 /* check, if row deletion events are tracked
15444 * if so, issue ROWDELETEDLP event
15445 */
15446 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15447 {
15448 SCIP_EVENT* event;
15449
15450 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15451 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15452 }
15453
15454 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15455 SCIProwUnlock(lp->rows[r]);
15456 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15457 assert(lp->lpirows[r] == NULL);
15458 assert(lp->rows[r] == NULL);
15459 lp->nrows--;
15460 lp->nlpirows--;
15461 }
15462 else if( rowdstat[r] < r )
15463 {
15464 assert(lp->rows[rowdstat[r]] == NULL);
15465 assert(lp->lpirows[rowdstat[r]] == NULL);
15466 lp->rows[rowdstat[r]] = row;
15467 lp->lpirows[rowdstat[r]] = row;
15468 lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15469 lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15470 lp->rows[r] = NULL;
15471 lp->lpirows[r] = NULL;
15472 }
15473 }
15474
15475 /* mark LP to be unsolved */
15476 if( lp->nrows < nrows )
15477 {
15478 assert(lp->nrows == lp->nlpirows);
15479 assert(lp->nchgrows == 0);
15480 assert(lp->flushed);
15481
15482 lp->lpifirstchgrow = lp->nlpirows;
15483
15484 /* mark the current solution invalid */
15485 lp->solved = FALSE;
15486 lp->dualfeasible = FALSE;
15487 lp->dualchecked = FALSE;
15488 lp->lpobjval = SCIP_INVALID;
15490 }
15491
15492 checkLinks(lp);
15493
15494 return SCIP_OKAY;
15495}
15496
15497/** removes all non-basic columns, that are too old, beginning with the given firstcol */
15498static
15500 SCIP_LP* lp, /**< current LP data */
15501 SCIP_SET* set, /**< global SCIP settings */
15502 SCIP_STAT* stat, /**< problem statistics */
15503 int firstcol /**< first column to check for clean up */
15504 )
15505{
15506 SCIP_COL** cols;
15507#ifndef NDEBUG
15508 SCIP_COL** lpicols;
15509#endif
15510 int* coldstat;
15511 int ncols;
15512 int ndelcols;
15513 int c;
15514
15515 assert(lp != NULL);
15516 assert(lp->flushed);
15517 assert(lp->ncols == lp->nlpicols);
15518 assert(lp->nremovablecols <= lp->ncols);
15519 assert(!lp->diving);
15520 assert(set != NULL);
15521 assert(stat != NULL);
15522
15523 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15524 return SCIP_OKAY;
15525
15526 ncols = lp->ncols;
15527 cols = lp->cols;
15528#ifndef NDEBUG
15529 lpicols = lp->lpicols;
15530#endif
15531
15532 /* get temporary memory */
15533 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15534
15535 /* mark obsolete columns to be deleted */
15536 ndelcols = 0;
15537 BMSclearMemoryArray(coldstat, ncols);
15538 for( c = firstcol; c < ncols; ++c )
15539 {
15540 assert(cols[c] == lpicols[c]);
15541 assert(cols[c]->lppos == c);
15542 assert(cols[c]->lpipos == c);
15543 if( cols[c]->removable
15544 && cols[c]->obsoletenode != stat->nnodes /* don't remove column a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15545 && cols[c]->age > set->lp_colagelimit
15547 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15548 {
15549 assert(cols[c]->primsol == 0.0);
15550 coldstat[c] = 1;
15551 ndelcols++;
15552 cols[c]->obsoletenode = stat->nnodes;
15553 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15554 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15555 }
15556 }
15557
15558 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15559
15560 /* delete the marked columns in the LP solver interface, update the LP respectively */
15561 if( ndelcols > 0 )
15562 {
15563 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15564 }
15565 assert(lp->ncols == ncols - ndelcols);
15566
15567 /* release temporary memory */
15568 SCIPsetFreeBufferArray(set, &coldstat);
15569
15570 return SCIP_OKAY;
15571}
15572
15573/** removes all basic rows, that are too old, beginning with the given firstrow */
15574static
15576 SCIP_LP* lp, /**< current LP data */
15577 BMS_BLKMEM* blkmem, /**< block memory buffers */
15578 SCIP_SET* set, /**< global SCIP settings */
15579 SCIP_STAT* stat, /**< problem statistics */
15580 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15581 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15582 int firstrow /**< first row to check for clean up */
15583 )
15584{
15585 SCIP_ROW** rows;
15586#ifndef NDEBUG
15587 SCIP_ROW** lpirows;
15588#endif
15589 int* rowdstat;
15590 int nrows;
15591 int ndelrows;
15592 int r;
15593
15594 assert(lp != NULL);
15595 assert(lp->flushed);
15596 assert(lp->nrows == lp->nlpirows);
15597 assert(lp->nremovablerows <= lp->nrows);
15598 assert(!lp->diving);
15599 assert(set != NULL);
15600 assert(stat != NULL);
15601
15602 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15603 return SCIP_OKAY;
15604
15605 nrows = lp->nrows;
15606 rows = lp->rows;
15607#ifndef NDEBUG
15608 lpirows = lp->lpirows;
15609#endif
15610
15611 /* get temporary memory */
15612 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15613
15614 /* mark obsolete rows to be deleted */
15615 ndelrows = 0;
15616 BMSclearMemoryArray(rowdstat, nrows);
15617 for( r = firstrow; r < nrows; ++r )
15618 {
15619 assert(rows[r] == lpirows[r]);
15620 assert(rows[r]->lppos == r);
15621 assert(rows[r]->lpipos == r);
15622 if( rows[r]->removable
15623 && rows[r]->obsoletenode != stat->nnodes /* don't remove row a second time from same node (avoid cycling), or a first time if marked nonremovable locally */
15624 && rows[r]->age > set->lp_rowagelimit
15626 {
15627 rowdstat[r] = 1;
15628 ndelrows++;
15629 rows[r]->obsoletenode = stat->nnodes;
15630 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15631 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15632 }
15633 }
15634
15635 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15636
15637 /* delete the marked rows in the LP solver interface, update the LP respectively */
15638 if( ndelrows > 0 )
15639 {
15640 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15641 }
15642 assert(lp->nrows == nrows - ndelrows);
15643
15644 /* release temporary memory */
15645 SCIPsetFreeBufferArray(set, &rowdstat);
15646
15647 return SCIP_OKAY;
15648}
15649
15650/** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15652 SCIP_LP* lp, /**< current LP data */
15653 BMS_BLKMEM* blkmem, /**< block memory buffers */
15654 SCIP_SET* set, /**< global SCIP settings */
15655 SCIP_STAT* stat, /**< problem statistics */
15656 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15657 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15658 )
15659{
15660 assert(lp != NULL);
15661 assert(lp->solved);
15662 assert(!lp->diving);
15664 assert(set != NULL);
15665
15666 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15667 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15668
15669 if( lp->firstnewcol < lp->ncols )
15670 {
15671 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15672 }
15673 if( lp->firstnewrow < lp->nrows )
15674 {
15675 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15676 }
15677
15678 return SCIP_OKAY;
15679}
15680
15681/** removes all non-basic columns and basic rows in whole LP, that are too old */
15683 SCIP_LP* lp, /**< current LP data */
15684 BMS_BLKMEM* blkmem, /**< block memory buffers */
15685 SCIP_SET* set, /**< global SCIP settings */
15686 SCIP_STAT* stat, /**< problem statistics */
15687 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15688 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15689 )
15690{
15691 assert(lp != NULL);
15692 assert(lp->solved);
15693 assert(!lp->diving);
15695 assert(set != NULL);
15696
15697 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15698
15699 if( 0 < lp->ncols )
15700 {
15701 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15702 }
15703 if( 0 < lp->nrows )
15704 {
15705 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15706 }
15707
15708 return SCIP_OKAY;
15709}
15710
15711/** removes all non-basic columns at 0.0 beginning with the given firstcol */
15712static
15714 SCIP_LP* lp, /**< current LP data */
15715 SCIP_SET* set, /**< global SCIP settings */
15716 SCIP_STAT* stat, /**< problem statistics */
15717 int firstcol /**< first column to check for clean up */
15718 )
15719{
15720 SCIP_COL** cols;
15721 SCIP_COL** lpicols;
15722 int* coldstat;
15723 int ncols;
15724 int ndelcols;
15725 int c;
15726
15727 assert(lp != NULL);
15728 assert(lp->flushed);
15729 assert(lp->ncols == lp->nlpicols);
15730 assert(!lp->diving);
15731 assert(stat != NULL);
15732 assert(lp->validsollp == stat->lpcount);
15733 assert(0 <= firstcol && firstcol < lp->ncols);
15734
15735 if( lp->nremovablecols == 0 || !lp->solisbasic )
15736 return SCIP_OKAY;
15737
15738 ncols = lp->ncols;
15739 cols = lp->cols;
15740 lpicols = lp->lpicols;
15741
15742 /* get temporary memory */
15743 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15744
15745 /* mark unused columns to be deleted */
15746 ndelcols = 0;
15747 BMSclearMemoryArray(coldstat, ncols);
15748 for( c = firstcol; c < ncols; ++c )
15749 {
15750 assert(cols[c] == lpicols[c]);
15751 assert(cols[c]->lppos == c);
15752 assert(cols[c]->lpipos == c);
15753 if( lpicols[c]->removable
15754 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15755 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15756 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15757 {
15758 coldstat[c] = 1;
15759 ndelcols++;
15760 }
15761 }
15762
15763 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15764
15765 /* delete the marked columns in the LP solver interface, update the LP respectively */
15766 if( ndelcols > 0 )
15767 {
15768 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15769 }
15770 assert(lp->ncols == ncols - ndelcols);
15771
15772 /* release temporary memory */
15773 SCIPsetFreeBufferArray(set, &coldstat);
15774
15775 return SCIP_OKAY;
15776}
15777
15778/** removes all basic rows beginning with the given firstrow */
15779static
15781 SCIP_LP* lp, /**< current LP data */
15782 BMS_BLKMEM* blkmem, /**< block memory buffers */
15783 SCIP_SET* set, /**< global SCIP settings */
15784 SCIP_STAT* stat, /**< problem statistics */
15785 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15786 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15787 int firstrow /**< first row to check for clean up */
15788 )
15789{
15790#ifndef NDEBUG
15791 SCIP_ROW** rows;
15792#endif
15793 SCIP_ROW** lpirows;
15794 int* rowdstat;
15795 int nrows;
15796 int ndelrows;
15797 int r;
15798
15799 assert(lp != NULL);
15800 assert(lp->flushed);
15801 assert(lp->ncols == lp->nlpicols);
15802 assert(lp->nrows == lp->nlpirows);
15803 assert(!lp->diving);
15804 assert(stat != NULL);
15805 assert(lp->validsollp == stat->lpcount);
15806 assert(0 <= firstrow && firstrow < lp->nrows);
15807
15808 if( lp->nremovablerows == 0 || !lp->solisbasic )
15809 return SCIP_OKAY;
15810
15811#ifndef NDEBUG
15812 rows = lp->rows;
15813#endif
15814 nrows = lp->nrows;
15815 lpirows = lp->lpirows;
15816
15817 /* get temporary memory */
15818 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15819
15820 /* mark unused rows to be deleted */
15821 ndelrows = 0;
15822 BMSclearMemoryArray(rowdstat, nrows);
15823 for( r = firstrow; r < nrows; ++r )
15824 {
15825 assert(rows[r] == lpirows[r]);
15826 assert(rows[r]->lppos == r);
15827 assert(rows[r]->lpipos == r);
15828 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15829 {
15830 rowdstat[r] = 1;
15831 ndelrows++;
15832 }
15833 }
15834
15835 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15836
15837 /* delete the marked rows in the LP solver interface, update the LP respectively */
15838 if( ndelrows > 0 )
15839 {
15840 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15841 }
15842 assert(lp->nrows == nrows - ndelrows);
15843
15844 /* release temporary memory */
15845 SCIPsetFreeBufferArray(set, &rowdstat);
15846
15847 return SCIP_OKAY;
15848}
15849
15850/** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15852 SCIP_LP* lp, /**< current LP data */
15853 BMS_BLKMEM* blkmem, /**< block memory buffers */
15854 SCIP_SET* set, /**< global SCIP settings */
15855 SCIP_STAT* stat, /**< problem statistics */
15856 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15857 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15858 SCIP_Bool root /**< are we at the root node? */
15859 )
15860{
15861 SCIP_Bool cleanupcols;
15862 SCIP_Bool cleanuprows;
15863
15864 assert(lp != NULL);
15865 assert(lp->solved);
15866 assert(!lp->diving);
15868 assert(set != NULL);
15869
15870 /* check, if we want to clean up the columns and rows */
15871 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15872 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15873
15874 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15875 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15876
15877 if( cleanupcols && lp->firstnewcol < lp->ncols )
15878 {
15879 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15880 }
15881 if( cleanuprows && lp->firstnewrow < lp->nrows )
15882 {
15883 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15884 }
15885
15886 return SCIP_OKAY;
15887}
15888
15889/** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15891 SCIP_LP* lp, /**< current LP data */
15892 BMS_BLKMEM* blkmem, /**< block memory buffers */
15893 SCIP_SET* set, /**< global SCIP settings */
15894 SCIP_STAT* stat, /**< problem statistics */
15895 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15896 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15897 SCIP_Bool root /**< are we at the root node? */
15898 )
15899{
15900 SCIP_Bool cleanupcols;
15901 SCIP_Bool cleanuprows;
15902
15903 assert(lp != NULL);
15904 assert(lp->solved);
15905 assert(!lp->diving);
15907 assert(set != NULL);
15908
15909 /* check, if we want to clean up the columns and rows */
15910 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15911 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15912
15913 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15914 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15915
15916 if( cleanupcols && 0 < lp->ncols )
15917 {
15918 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15919 }
15920 if( cleanuprows && 0 < lp->nrows )
15921 {
15922 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15923 }
15924
15925 return SCIP_OKAY;
15926}
15927
15928/** removes all redundant rows that were added at the current node */
15930 SCIP_LP* lp, /**< current LP data */
15931 BMS_BLKMEM* blkmem, /**< block memory buffers */
15932 SCIP_SET* set, /**< global SCIP settings */
15933 SCIP_STAT* stat, /**< problem statistics */
15934 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15935 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15936 )
15937{
15938#ifndef NDEBUG
15939 SCIP_ROW** rows;
15940#endif
15941 SCIP_ROW** lpirows;
15942 int* rowdstat;
15943 int nrows;
15944 int ndelrows;
15945 int r;
15946
15947 assert(lp != NULL);
15948 assert(lp->flushed);
15949 assert(lp->ncols == lp->nlpicols);
15950 assert(lp->nrows == lp->nlpirows);
15951 assert(!lp->diving);
15952 assert(stat != NULL);
15953 assert(lp->validsollp == stat->lpcount);
15954 assert(lp->firstnewrow <= lp->nrows);
15955
15956 if( lp->firstnewrow == lp->nrows )
15957 return SCIP_OKAY;
15958
15959#ifndef NDEBUG
15960 rows = lp->rows;
15961#endif
15962 nrows = lp->nrows;
15963 lpirows = lp->lpirows;
15964
15965 /* get temporary memory */
15966 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15967
15968 /* mark redundant rows to be deleted (only delete basic rows!) */
15969 ndelrows = 0;
15970 BMSclearMemoryArray(rowdstat, nrows);
15971 for( r = lp->firstnewrow; r < nrows; ++r )
15972 {
15973 assert(rows[r] == lpirows[r]);
15974 assert(rows[r]->lppos == r);
15975 assert(rows[r]->lpipos == r);
15976 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
15977 && SCIProwIsRedundant(lpirows[r], set, stat) )
15978 {
15979 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
15980 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
15981 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
15982 rowdstat[r] = 1;
15983 ndelrows++;
15984 }
15985 }
15986
15987 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
15988
15989 /* delete the marked rows in the LP solver interface, update the LP respectively */
15990 if( ndelrows > 0 )
15991 {
15992 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15993 }
15994 assert(lp->nrows == nrows - ndelrows);
15995
15996 /* release temporary memory */
15997 SCIPsetFreeBufferArray(set, &rowdstat);
15998
15999 return SCIP_OKAY;
16000}
16001
16002/** initiates LP diving */
16004 SCIP_LP* lp, /**< current LP data */
16005 BMS_BLKMEM* blkmem, /**< block memory */
16006 SCIP_SET* set, /**< global SCIP settings */
16007 SCIP_STAT* stat /**< problem statistics */
16008 )
16009{
16010 int c;
16011 int r;
16012
16013 assert(lp != NULL);
16014 assert(lp->flushed || !lp->solved);
16015 assert(!lp->diving);
16016 assert(!lp->probing);
16017 assert(lp->divelpistate == NULL);
16018 assert(lp->divelpwasprimfeas);
16019 assert(lp->divelpwasdualfeas);
16020 assert(lp->validsollp <= stat->lpcount);
16021 assert(blkmem != NULL);
16022 assert(set != NULL);
16023 assert(lp->ndivechgsides == 0);
16024
16025 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16026 lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16027
16028#ifndef NDEBUG
16029 for( c = 0; c < lp->ncols; ++c )
16030 {
16031 assert(lp->cols[c] != NULL);
16032 assert(lp->cols[c]->var != NULL);
16033 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16034 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16035 assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16036 assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16037 assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16038 }
16039#endif
16040
16041 /* save current LPI state (basis information) */
16042 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16047
16048 /* save current LP values dependent on the solution */
16049 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16050 assert(lp->storedsolvals != NULL);
16051 if( !set->lp_resolverestore && lp->solved )
16052 {
16053 SCIP_Bool store = TRUE;
16054
16055 switch ( lp->lpsolstat )
16056 {
16058 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16059 assert(lp->validsollp == stat->lpcount);
16060 break;
16063 assert(lp->validsollp == stat->lpcount);
16064 break;
16068 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16069 assert(lp->validsollp == stat->lpcount);
16070 break;
16072 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, NULL) );
16073 break;
16076 default:
16077 store = FALSE;
16078 }
16079
16080 if ( store )
16081 {
16082 for( c = 0; c < lp->ncols; ++c )
16083 {
16084 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16085 }
16086 for( r = 0; r < lp->nrows; ++r )
16087 {
16089 }
16090 }
16091 }
16092
16093 /* store LPI iteration limit */
16095
16096 /* remember the number of domain changes */
16097 lp->divenolddomchgs = stat->domchgcount;
16098
16099 /* store current number of rows */
16100 lp->ndivingrows = lp->nrows;
16101
16102 /* switch to diving mode */
16103 lp->diving = TRUE;
16104
16105 return SCIP_OKAY;
16106}
16107
16108/** quits LP diving and resets bounds and objective values of columns to the current node's values */
16110 SCIP_LP* lp, /**< current LP data */
16111 BMS_BLKMEM* blkmem, /**< block memory */
16112 SCIP_SET* set, /**< global SCIP settings */
16113 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16114 SCIP_STAT* stat, /**< problem statistics */
16115 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16116 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16117 SCIP_PROB* prob, /**< problem data */
16118 SCIP_VAR** vars, /**< array with all active variables */
16119 int nvars /**< number of active variables */
16120 )
16121{
16122 SCIP_VAR* var;
16123 int v;
16124
16125 assert(lp != NULL);
16126 assert(lp->diving);
16127 assert(blkmem != NULL);
16128 assert(nvars == 0 || vars != NULL);
16129
16130 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16131
16132 /* reset all columns' objective values and bounds to its original values */
16133 for( v = 0; v < nvars; ++v )
16134 {
16135 var = vars[v];
16136 assert(var != NULL);
16138 {
16142 }
16143 }
16144
16145 /* remove rows which were added in diving mode */
16146 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16147
16148 /* undo changes to left hand sides and right hand sides */
16149 while( lp->ndivechgsides > 0 )
16150 {
16151 SCIP_Real oldside;
16152 SCIP_SIDETYPE sidetype;
16153 SCIP_ROW* row;
16154
16155 lp->ndivechgsides--;
16156 oldside = lp->divechgsides[lp->ndivechgsides];
16157 sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16158 row = lp->divechgrows[lp->ndivechgsides];
16159
16160 if( sidetype == SCIP_SIDETYPE_LEFT )
16161 {
16162 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16163 }
16164 else
16165 {
16166 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16167 }
16168 }
16169
16170 /* restore LPI iteration limit */
16172
16173 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16174 * happens
16175 */
16176 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16178 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16179 lp->divelpwasprimfeas = TRUE;
16180 lp->divelpwasdualfeas = TRUE;
16183 assert(lp->divelpistate == NULL);
16184
16185 /* switch to standard (non-diving) mode */
16186 lp->diving = FALSE;
16187 lp->divingobjchg = FALSE;
16188
16189 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16190 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16191 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16192 * the parameter resolverestore to TRUE
16193 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16194 */
16195 assert(lp->storedsolvals != NULL);
16196 if( lp->storedsolvals->lpissolved
16197 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16198 {
16199 SCIP_Bool lperror;
16200
16201 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, &lperror) );
16202 if( lperror )
16203 {
16204 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16205 lp->resolvelperror = TRUE;
16206 }
16211 {
16212 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16213 "LP was not resolved to a sufficient status after diving\n");
16214 lp->resolvelperror = TRUE;
16215 }
16216 }
16217 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16218 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16219 * re-solve as above can lead to a different LP status
16220 */
16221 else
16222 {
16223 int c;
16224 int r;
16225
16226 /* if there are lazy bounds, remove them from the LP */
16227 if( lp->nlazycols > 0 )
16228 {
16229 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16230 * first resolve LP?
16231 */
16233 assert(lp->diving == lp->divinglazyapplied);
16234
16235 /* flush changes to the LP solver */
16236 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16237 }
16238
16239 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16240 SCIPstatIncrement(stat, set, lpcount);
16241
16242 /* restore LP solution values in lp data, columns and rows */
16243 if( lp->storedsolvals->lpissolved &&
16250 )
16251 {
16252 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16253
16254 for( c = 0; c < lp->ncols; ++c )
16255 {
16256 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16257 }
16258 for( r = 0; r < lp->nrows; ++r )
16259 {
16260 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16261 }
16262 }
16263 else
16264 {
16265 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16266 }
16267 }
16268
16269#ifndef NDEBUG
16270 {
16271 int c;
16272 for( c = 0; c < lp->ncols; ++c )
16273 {
16274 assert(lp->cols[c] != NULL);
16275 assert(lp->cols[c]->var != NULL);
16276 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16277 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16278 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16279 assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16280 assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16281 }
16282 }
16283#endif
16284
16285 return SCIP_OKAY;
16286}
16287
16288#define DIVESTACKGROWFACT 1.5
16289
16290/** records a current row side such that any change will be undone after diving */
16292 SCIP_LP* lp, /**< LP data object */
16293 SCIP_ROW* row, /**< row affected by the change */
16294 SCIP_SIDETYPE sidetype /**< side type */
16295 )
16296{
16297 assert(lp != NULL);
16298 assert(row != NULL);
16299
16300 if( lp->ndivechgsides == lp->divechgsidessize )
16301 {
16303 }
16304 assert(lp->ndivechgsides < lp->divechgsidessize);
16305
16306 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16307 lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16308 lp->divechgrows[lp->ndivechgsides] = row;
16309 lp->ndivechgsides++;
16310
16311 return SCIP_OKAY;
16312}
16313
16314/** informs the LP that probing mode was initiated */
16316 SCIP_LP* lp /**< current LP data */
16317 )
16318{
16319 assert(lp != NULL);
16320 assert(!lp->probing);
16321 assert(!lp->strongbranching);
16322 assert(!lp->strongbranchprobing);
16323
16324 lp->probing = TRUE;
16325
16326 return SCIP_OKAY;
16327}
16328
16329/** informs the LP that probing mode was finished */
16331 SCIP_LP* lp /**< current LP data */
16332 )
16333{
16334 assert(lp != NULL);
16335 assert(lp->probing);
16336 assert(!lp->strongbranching);
16337 assert(!lp->strongbranchprobing);
16338
16339 lp->probing = FALSE;
16340
16341 return SCIP_OKAY;
16342}
16343
16344/** informs the LP that the probing mode is now used for strongbranching */
16346 SCIP_LP* lp /**< current LP data */
16347 )
16348{
16349 assert(lp != NULL);
16350 assert(lp->probing);
16351 assert(!lp->strongbranching);
16352 assert(!lp->strongbranchprobing);
16353
16355}
16356
16357/** informs the LP that the probing mode is not used for strongbranching anymore */
16359 SCIP_LP* lp /**< current LP data */
16360 )
16361{
16362 assert(lp != NULL);
16363 assert(lp->probing);
16364 assert(!lp->strongbranching);
16365 assert(lp->strongbranchprobing);
16366
16368}
16369
16370/** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16371 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16372 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16373 * we have only left hand sides):
16374 * min{cx | b <= Ax, lb <= x <= ub}
16375 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
16376 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
16377 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
16378 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
16379 */
16380static
16382 SCIP_LP* lp, /**< current LP data */
16383 SCIP_SET* set, /**< global SCIP settings */
16384 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16385 SCIP_Real* bound /**< result of interval arithmetic minimization */
16386 )
16387{
16388 SCIP_INTERVAL* yinter;
16390 SCIP_INTERVAL ytb;
16391 SCIP_INTERVAL prod;
16392 SCIP_INTERVAL diff;
16394 SCIP_INTERVAL minprod;
16396 SCIP_ROW* row;
16397 SCIP_COL* col;
16398 SCIP_Real y;
16399 SCIP_Real c;
16400 int i;
16401 int j;
16402
16403 assert(lp != NULL);
16404 assert(lp->solved);
16405 assert(set != NULL);
16406 assert(bound != NULL);
16407
16408 /* allocate buffer for storing y in interval arithmetic */
16409 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16410
16411 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16412 SCIPintervalSet(&ytb, 0.0);
16413 for( j = 0; j < lp->nrows; ++j )
16414 {
16415 row = lp->rows[j];
16416 assert(row != NULL);
16417
16418 y = (usefarkas ? row->dualfarkas : row->dualsol);
16419
16421 {
16422 SCIPintervalSet(&yinter[j], y);
16423 SCIPintervalSet(&b, row->lhs - row->constant);
16424 }
16425 else if( SCIPsetIsFeasNegative(set, y) )
16426 {
16427 SCIPintervalSet(&yinter[j], y);
16428 SCIPintervalSet(&b, row->rhs - row->constant);
16429 }
16430 else
16431 {
16432 SCIPintervalSet(&yinter[j], 0.0);
16433 SCIPintervalSet(&b, 0.0);
16434 }
16435
16436 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16437 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16438 }
16439
16440 /* calculate min{(c^T - y^TA)x} */
16441 SCIPintervalSet(&minprod, 0.0);
16442 for( j = 0; j < lp->ncols; ++j )
16443 {
16444 col = lp->cols[j];
16445 assert(col != NULL);
16446 assert(col->nunlinked == 0);
16447
16449
16450 c = usefarkas ? 0.0 : col->obj;
16451 SCIPintervalSet(&diff, c);
16452
16453 for( i = 0; i < col->nlprows; ++i )
16454 {
16455 assert(col->rows[i] != NULL);
16456 assert(col->rows[i]->lppos >= 0);
16457 assert(col->linkpos[i] >= 0);
16458 SCIPintervalSet(&a, col->vals[i]);
16459 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16460 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16461 }
16462
16463#ifndef NDEBUG
16464 for( i = col->nlprows; i < col->len; ++i )
16465 {
16466 assert(col->rows[i] != NULL);
16467 assert(col->rows[i]->lppos == -1);
16468 assert(col->rows[i]->dualsol == 0.0);
16469 assert(col->rows[i]->dualfarkas == 0.0);
16470 assert(col->linkpos[i] >= 0);
16471 }
16472#endif
16473
16474 SCIPintervalSetBounds(&x, col->lb, col->ub);
16475 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16476 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16477 }
16478
16479 /* add y^Tb */
16480 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16481
16482 /* free buffer for storing y in interval arithmetic */
16483 SCIPsetFreeBufferArray(set, &yinter);
16484
16485 *bound = SCIPintervalGetInf(minprod);
16486
16487 return SCIP_OKAY;
16488}
16489
16490/** gets proven lower (dual) bound of last LP solution */
16492 SCIP_LP* lp, /**< current LP data */
16493 SCIP_SET* set, /**< global SCIP settings */
16494 SCIP_Real* bound /**< pointer to store proven dual bound */
16495 )
16496{
16498
16499 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16500
16501 return SCIP_OKAY;
16502}
16503
16504/** gets proven dual bound of last LP solution */
16506 SCIP_LP* lp, /**< current LP data */
16507 SCIP_SET* set, /**< global SCIP settings */
16508 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
16509 )
16510{
16512
16513 assert(proved != NULL);
16514
16515 SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16516
16517 *proved = (bound > 0.0);
16518
16519 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16520
16521 return SCIP_OKAY;
16522}
16523
16524
16525
16526/** writes LP to a file */
16528 SCIP_LP* lp, /**< current LP data */
16529 const char* fname /**< file name */
16530 )
16531{
16532 assert(lp != NULL);
16533 assert(lp->flushed);
16534 assert(fname != NULL);
16535
16536 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16537
16538 return SCIP_OKAY;
16539}
16540
16541/** writes MIP relaxation of the current B&B node to a file */
16543 SCIP_LP* lp, /**< current LP data */
16544 SCIP_SET* set, /**< global SCIP settings */
16545 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16546 const char* fname, /**< file name */
16547 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
16548 * troubles with reserved symbols? */
16549 SCIP_Bool origobj, /**< should the original objective function be used? */
16550 SCIP_OBJSENSE objsense, /**< objective sense */
16551 SCIP_Real objscale, /**< objective scaling factor */
16552 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
16553 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
16554 )
16555{
16556 FILE* file;
16557 int i;
16558 int j;
16559 char rowname[SCIP_MAXSTRLEN];
16560 SCIP_Real coeff;
16561
16562 assert(lp != NULL);
16563 assert(lp->flushed);
16564 assert(fname != NULL);
16565
16566 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16567 file = fopen(fname, "w");
16568 if( file == NULL )
16569 {
16570 SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16571 SCIPprintSysError(fname);
16572 return SCIP_FILECREATEERROR;
16573 }
16574
16575 /* print comments */
16576 if( genericnames )
16577 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16578 else
16579 {
16580 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16581 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16582 }
16583
16584 if( origobj && objoffset != 0.0 )
16585 {
16586 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16587 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16588 }
16589
16590 /* print objective function */
16591 /**@note the transformed problem in SCIP is always a minimization problem */
16592 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16593 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16594 else
16595 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16596
16597 /* print objective */
16598 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16599 j = 0;
16600 for( i = 0; i < lp->ncols; ++i )
16601 {
16602 if( lp->cols[i]->obj != 0.0 )
16603 {
16604 coeff = lp->cols[i]->obj;
16605 if( origobj )
16606 {
16607 coeff *= (SCIP_Real) objsense;
16608 coeff *= objscale;
16609 }
16610
16611 if( genericnames )
16612 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16613 else
16614 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16615
16616 ++j;
16617 if( j % 10 == 0 )
16618 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16619 }
16620 }
16621 /* add artificial variable 'objoffset' to transfer objective offset */
16622 if( origobj && objoffset != 0.0 )
16623 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16624
16625 /* print constraint section */
16626 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16627 for( i = 0; i < lp->nrows; i++ )
16628 {
16629 char type = 'i';
16630
16631 /* skip removable rows if we want to write them as lazy constraints */
16632 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16633 continue;
16634
16635 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16636 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16637 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16638 * type 'i' means: lhs and rhs are both infinite */
16639 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16640 type = 'r';
16641 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16642 type = 'l';
16643 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16644 type = 'e';
16645 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16646 type = 'b';
16647
16648 /* print name of row */
16649 if( genericnames )
16650 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16651 else
16652 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16653
16654 WRITEROW:
16655 switch( type )
16656 {
16657 case 'r':
16658 case 'l':
16659 case 'e':
16660 if( strlen(rowname) > 0 )
16661 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16662 break;
16663 case 'i':
16664 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16665 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16666 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16667 type = 'b';
16668 /*lint -fallthrough*/
16669 case 'b':
16670 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16671 break;
16672 default:
16673 assert(type == 'B');
16674 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16675 break;
16676 }
16677
16678 /* print coefficients and variables */
16679 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16680 {
16681 if( genericnames )
16682 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16683 else
16684 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16685
16686 if( (j+1) % 10 == 0 )
16687 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16688 }
16689
16690 /* print right hand side */
16691 switch( type )
16692 {
16693 case 'b':
16694 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16695 type = 'B';
16696 goto WRITEROW;
16697 case 'l':
16698 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16699 break;
16700 case 'B':
16701 case 'r':
16702 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16703 break;
16704 case 'e':
16705 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16706 break;
16707 default:
16708 SCIPerrorMessage("Undefined row type!\n");
16709 fclose(file);
16710 return SCIP_ERROR;
16711 }
16712 }
16713
16714 if ( lazyconss )
16715 {
16716 /* print lazy constraint section */
16717 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16718 for( i = 0; i < lp->nrows; i++ )
16719 {
16720 char type = 'i';
16721
16722 /* skip non-removable rows if we want to write lazy constraints */
16723 if ( ! SCIProwIsRemovable(lp->rows[i]) )
16724 continue;
16725
16726 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16727 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16728 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16729 * type 'i' means: lhs and rhs are both infinite */
16730 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16731 type = 'r';
16732 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16733 type = 'l';
16734 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16735 type = 'e';
16736 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16737 type = 'b';
16738
16739 /* print name of row */
16740 if( genericnames )
16741 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16742 else
16743 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16744
16745 WRITELAZYROW:
16746 switch( type )
16747 {
16748 case 'r':
16749 case 'l':
16750 case 'e':
16751 if( strlen(rowname) > 0 )
16752 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16753 break;
16754 case 'i':
16755 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16756 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16757 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16758 type = 'b';
16759 /*lint -fallthrough*/
16760 case 'b':
16761 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16762 break;
16763 default:
16764 assert(type == 'B');
16765 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16766 break;
16767 }
16768
16769 /* print coefficients and variables */
16770 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16771 {
16772 if( genericnames )
16773 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16774 else
16775 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16776
16777 if( (j+1) % 10 == 0 )
16778 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16779 }
16780
16781 /* print right hand side */
16782 switch( type )
16783 {
16784 case 'b':
16785 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16786 type = 'B';
16787 goto WRITELAZYROW;
16788 case 'l':
16789 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16790 break;
16791 case 'B':
16792 case 'r':
16793 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16794 break;
16795 case 'e':
16796 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16797 break;
16798 default:
16799 SCIPerrorMessage("Undefined row type!\n");
16800 fclose(file);
16801 return SCIP_ERROR;
16802 }
16803 }
16804 }
16805
16806 /* print variable bounds */
16807 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16808 for( i = 0; i < lp->ncols; ++i )
16809 {
16810 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16811 {
16812 /* print lower bound as far this one is not infinity */
16813 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16814 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16815
16816 /* print variable name */
16817 if( genericnames )
16818 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16819 else
16820 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16821
16822 /* print upper bound as far this one is not infinity */
16823 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16824 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16825 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16826 }
16827 }
16828 if( origobj && objoffset != 0.0 )
16829 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16830
16831 /* print integer variables */
16832 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16833 j = 0;
16834 for( i = 0; i < lp->ncols; ++i )
16835 {
16836 if( SCIPvarIsIntegral(lp->cols[i]->var) )
16837 {
16838 /* print variable name */
16839 if( genericnames )
16840 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16841 else
16842 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16843
16844 j++;
16845 if( j % 10 == 0 )
16846 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16847 }
16848 }
16849
16850 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16851 fclose(file);
16852
16853 return SCIP_OKAY;
16854}
16855
16856/*
16857 * simple functions implemented as defines
16858 */
16859
16860/* In debug mode, the following methods are implemented as function calls to ensure
16861 * type validity.
16862 * In optimized mode, the methods are implemented as defines to improve performance.
16863 * However, we want to have them in the library anyways, so we have to undef the defines.
16864 */
16865
16866#undef SCIPcolGetObj
16867#undef SCIPcolGetLb
16868#undef SCIPcolGetUb
16869#undef SCIPcolGetBestBound
16870#undef SCIPcolGetPrimsol
16871#undef SCIPcolGetMinPrimsol
16872#undef SCIPcolGetMaxPrimsol
16873#undef SCIPcolGetBasisStatus
16874#undef SCIPcolGetVar
16875#undef SCIPcolGetIndex
16876#undef SCIPcolGetVarProbindex
16877#undef SCIPcolIsIntegral
16878#undef SCIPcolIsRemovable
16879#undef SCIPcolGetLPPos
16880#undef SCIPcolGetLPDepth
16881#undef SCIPcolIsInLP
16882#undef SCIPcolGetNNonz
16883#undef SCIPcolGetNLPNonz
16884#undef SCIPcolGetRows
16885#undef SCIPcolGetVals
16886#undef SCIPcolGetStrongbranchNode
16887#undef SCIPcolGetNStrongbranchs
16888#undef SCIPcolGetAge
16889#undef SCIPboundtypeOpposite
16890#undef SCIProwGetNNonz
16891#undef SCIProwGetNLPNonz
16892#undef SCIProwGetCols
16893#undef SCIProwGetVals
16894#undef SCIProwGetConstant
16895#undef SCIProwGetNorm
16896#undef SCIProwGetSumNorm
16897#undef SCIProwGetLhs
16898#undef SCIProwGetRhs
16899#undef SCIProwGetDualsol
16900#undef SCIProwGetDualfarkas
16901#undef SCIProwGetBasisStatus
16902#undef SCIProwGetName
16903#undef SCIProwGetIndex
16904#undef SCIProwGetAge
16905#undef SCIProwGetRank
16906#undef SCIProwIsIntegral
16907#undef SCIProwIsLocal
16908#undef SCIProwIsModifiable
16909#undef SCIProwIsRemovable
16910#undef SCIProwGetOrigintype
16911#undef SCIProwGetOriginCons
16912#undef SCIProwGetOriginConshdlr
16913#undef SCIProwGetOriginSepa
16914#undef SCIProwIsInGlobalCutpool
16915#undef SCIProwGetLPPos
16916#undef SCIProwGetLPDepth
16917#undef SCIProwIsInLP
16918#undef SCIProwGetActiveLPCount
16919#undef SCIProwGetNLPsAfterCreation
16920#undef SCIProwChgRank
16921#undef SCIPlpGetCols
16922#undef SCIPlpGetNCols
16923#undef SCIPlpGetRows
16924#undef SCIPlpGetNRows
16925#undef SCIPlpGetNewcols
16926#undef SCIPlpGetNNewcols
16927#undef SCIPlpGetNewrows
16928#undef SCIPlpGetNNewrows
16929#undef SCIPlpGetObjNorm
16930#undef SCIPlpGetRootObjval
16931#undef SCIPlpGetRootColumnObjval
16932#undef SCIPlpGetRootLooseObjval
16933#undef SCIPlpGetLPI
16934#undef SCIPlpSetIsRelax
16935#undef SCIPlpIsRelax
16936#undef SCIPlpIsSolved
16937#undef SCIPlpIsSolBasic
16938#undef SCIPlpDiving
16939#undef SCIPlpDivingObjChanged
16940#undef SCIPlpMarkDivingObjChanged
16941#undef SCIPlpUnmarkDivingObjChanged
16942#undef SCIPlpDivingRowsChanged
16943#undef SCIPlpIsFeasEQ
16944#undef SCIPlpIsFeasLT
16945#undef SCIPlpIsFeasLE
16946#undef SCIPlpIsFeasGT
16947#undef SCIPlpIsFeasGE
16948#undef SCIPlpIsFeasZero
16949#undef SCIPlpIsFeasPositive
16950#undef SCIPlpIsFeasNegative
16951
16952/** gets objective value of column */
16954 SCIP_COL* col /**< LP column */
16955 )
16956{
16957 assert(col != NULL);
16958
16959 return col->obj;
16960}
16961
16962/** gets lower bound of column */
16964 SCIP_COL* col /**< LP column */
16965 )
16966{
16967 assert(col != NULL);
16968
16969 return col->lb;
16970}
16971
16972/** gets upper bound of column */
16974 SCIP_COL* col /**< LP column */
16975 )
16976{
16977 assert(col != NULL);
16978
16979 return col->ub;
16980}
16981
16982/** gets best bound of column with respect to the objective function */
16984 SCIP_COL* col /**< LP column */
16985 )
16986{
16987 assert(col != NULL);
16988
16989 if( col->obj >= 0.0 )
16990 return col->lb;
16991 else
16992 return col->ub;
16993}
16994
16995/** gets the primal LP solution of a column */
16997 SCIP_COL* col /**< LP column */
16998 )
16999{
17000 assert(col != NULL);
17001
17002 if( col->lppos >= 0 )
17003 return col->primsol;
17004 else
17005 return 0.0;
17006}
17007
17008/** gets the minimal LP solution value, this column ever assumed */
17010 SCIP_COL* col /**< LP column */
17011 )
17012{
17013 assert(col != NULL);
17014
17015 return col->minprimsol;
17016}
17017
17018/** gets the maximal LP solution value, this column ever assumed */
17020 SCIP_COL* col /**< LP column */
17021 )
17022{
17023 assert(col != NULL);
17024
17025 return col->maxprimsol;
17026}
17027
17028/** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17029 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17030 */
17032 SCIP_COL* col /**< LP column */
17033 )
17034{
17035 assert(col != NULL);
17036 assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
17037
17038 return (SCIP_BASESTAT)col->basisstatus;
17039}
17040
17041/** gets variable this column represents */
17043 SCIP_COL* col /**< LP column */
17044 )
17045{
17046 assert(col != NULL);
17047
17048 return col->var;
17049}
17050
17051/** gets unique index of col */
17053 SCIP_COL* col /**< LP col */
17054 )
17055{
17056 assert(col != NULL);
17057
17058 return col->index;
17059}
17060
17061/** gets probindex of corresponding variable */
17063 SCIP_COL* col /**< LP col */
17064 )
17065{
17066 assert(col != NULL);
17067
17068 return col->var_probindex;
17069}
17070
17071/** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17073 SCIP_COL* col /**< LP column */
17074 )
17075{
17076 assert(col != NULL);
17077 assert(SCIPvarIsIntegral(col->var) == col->integral);
17078
17079 return col->integral;
17080}
17081
17082/** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17084 SCIP_COL* col /**< LP column */
17085 )
17086{
17087 assert(col != NULL);
17088
17089 return col->removable;
17090}
17091
17092/** gets position of column in current LP, or -1 if it is not in LP */
17094 SCIP_COL* col /**< LP column */
17095 )
17096{
17097 assert(col != NULL);
17098 assert((col->lppos == -1) == (col->lpdepth == -1));
17099
17100 return col->lppos;
17101}
17102
17103/** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17105 SCIP_COL* col /**< LP column */
17106 )
17107{
17108 assert(col != NULL);
17109 assert((col->lppos == -1) == (col->lpdepth == -1));
17110
17111 return col->lpdepth;
17112}
17113
17114/** returns TRUE iff column is member of current LP */
17116 SCIP_COL* col /**< LP column */
17117 )
17118{
17119 assert(col != NULL);
17120 assert((col->lppos == -1) == (col->lpdepth == -1));
17121
17122 return (col->lppos >= 0);
17123}
17124
17125/** get number of nonzero entries in column vector */
17127 SCIP_COL* col /**< LP column */
17128 )
17129{
17130 assert(col != NULL);
17131
17132 return col->len;
17133}
17134
17135/** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17136 *
17137 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17138 * that is in the current LP and the LP was solved, or a column that was in a solved LP and didn't change afterwards
17139 */
17141 SCIP_COL* col /**< LP column */
17142 )
17143{
17144 assert(col != NULL);
17145 assert(col->nunlinked == 0);
17146
17147 return col->nlprows;
17148}
17149
17150/** gets array with rows of nonzero entries */
17152 SCIP_COL* col /**< LP column */
17153 )
17154{
17155 assert(col != NULL);
17156
17157 return col->rows;
17158}
17159
17160/** gets array with coefficients of nonzero entries */
17162 SCIP_COL* col /**< LP column */
17163 )
17164{
17165 assert(col != NULL);
17166
17167 return col->vals;
17168}
17169
17170/** gets node number of the last node in current branch and bound run, where strong branching was used on the
17171 * given column, or -1 if strong branching was never applied to the column in current run
17172 */
17174 SCIP_COL* col /**< LP column */
17175 )
17176{
17177 assert(col != NULL);
17178
17179 return col->sbnode;
17180}
17181
17182/** gets number of times, strong branching was applied in current run on the given column */
17184 SCIP_COL* col /**< LP column */
17185 )
17186{
17187 assert(col != NULL);
17188
17189 return col->nsbcalls;
17190}
17191
17192/** gets the age of a column, i.e., the total number of successive times a column was in the LP and was 0.0 in the solution */
17194 SCIP_COL* col /**< LP column */
17195 )
17196{
17197 assert(col != NULL);
17198
17199 return col->age;
17200}
17201
17202/** gets opposite bound type of given bound type */
17204 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
17205 )
17206{
17207 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17208
17210}
17211
17212/** get number of nonzero entries in row vector */
17214 SCIP_ROW* row /**< LP row */
17215 )
17216{
17217 assert(row != NULL);
17218
17219 return row->len;
17220}
17221
17222/** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17223 *
17224 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17225 * that is in the current LP and the LP was solved, or a row that was in a solved LP and didn't change afterwards
17226 */
17228 SCIP_ROW* row /**< LP row */
17229 )
17230{
17231 assert(row != NULL);
17232 assert(row->nunlinked == 0);
17233
17234 return row->nlpcols;
17235}
17236
17237/** gets array with columns of nonzero entries */
17239 SCIP_ROW* row /**< LP row */
17240 )
17241{
17242 assert(row != NULL);
17243
17244 return row->cols;
17245}
17246
17247/** gets array with coefficients of nonzero entries */
17249 SCIP_ROW* row /**< LP row */
17250 )
17251{
17252 assert(row != NULL);
17253
17254 return row->vals;
17255}
17256
17257/** gets constant shift of row */
17259 SCIP_ROW* row /**< LP row */
17260 )
17261{
17262 assert(row != NULL);
17263
17264 return row->constant;
17265}
17266
17267/** gets Euclidean norm of row vector */
17269 SCIP_ROW* row /**< LP row */
17270 )
17271{
17272 assert(row != NULL);
17273
17274 checkRowSqrnorm(row);
17275
17276 return sqrt(row->sqrnorm);
17277}
17278
17279/** gets sum norm of row vector (sum of absolute values of coefficients) */
17281 SCIP_ROW* row /**< LP row */
17282 )
17283{
17284 assert(row != NULL);
17285
17286 checkRowSumnorm(row);
17287
17288 return row->sumnorm;
17289}
17290
17291/** returns the left hand side of the row */
17293 SCIP_ROW* row /**< LP row */
17294 )
17295{
17296 assert(row != NULL);
17297
17298 return row->lhs;
17299}
17300
17301/** returns the right hand side of the row */
17303 SCIP_ROW* row /**< LP row */
17304 )
17305{
17306 assert(row != NULL);
17307
17308 return row->rhs;
17309}
17310
17311/** gets the dual LP solution of a row */
17313 SCIP_ROW* row /**< LP row */
17314 )
17315{
17316 assert(row != NULL);
17317
17318 if( row->lppos >= 0 )
17319 return row->dualsol;
17320 else
17321 return 0.0;
17322}
17323
17324/** gets the dual Farkas coefficient of a row in an infeasible LP */
17326 SCIP_ROW* row /**< LP row */
17327 )
17328{
17329 assert(row != NULL);
17330
17331 if( row->lppos >= 0 )
17332 return row->dualfarkas;
17333 else
17334 return 0.0;
17335}
17336
17337/** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17338 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17339 */
17341 SCIP_ROW* row /**< LP row */
17342 )
17343{
17344 assert(row != NULL);
17345 assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
17346
17347 return (SCIP_BASESTAT)row->basisstatus;
17348}
17349
17350/** returns the name of the row */
17351const char* SCIProwGetName(
17352 SCIP_ROW* row /**< LP row */
17353 )
17354{
17355 assert(row != NULL);
17356
17357 return row->name;
17358}
17359
17360/** gets unique index of row */
17362 SCIP_ROW* row /**< LP row */
17363 )
17364{
17365 assert(row != NULL);
17366
17367 return row->index;
17368}
17369
17370/** gets age of row */
17372 SCIP_ROW* row /**< LP row */
17373 )
17374{
17375 assert(row != NULL);
17376
17377 return row->age;
17378}
17379
17380/** gets rank of row */
17382 SCIP_ROW* row /**< LP row */
17383 )
17384{
17385 assert(row != NULL);
17386
17387 return row->rank;
17388}
17389
17390/** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17392 SCIP_ROW* row /**< LP row */
17393 )
17394{
17395 assert(row != NULL);
17396
17397 return row->integral;
17398}
17399
17400/** returns TRUE iff row is only valid locally */
17402 SCIP_ROW* row /**< LP row */
17403 )
17404{
17405 assert(row != NULL);
17406
17407 return row->local;
17408}
17409
17410/** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17412 SCIP_ROW* row /**< LP row */
17413 )
17414{
17415 assert(row != NULL);
17416
17417 return row->modifiable;
17418}
17419
17420/** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17422 SCIP_ROW* row /**< LP row */
17423 )
17424{
17425 assert(row != NULL);
17426
17427 return row->removable;
17428}
17429
17430/** returns type of origin that created the row */
17432 SCIP_ROW* row /**< LP row */
17433 )
17434{
17435 assert( row != NULL );
17436
17437 return (SCIP_ROWORIGINTYPE) row->origintype;
17438}
17439
17440/** returns origin constraint that created the row (NULL if not available) */
17442 SCIP_ROW* row /**< LP row */
17443 )
17444{
17445 assert( row != NULL );
17446
17448 {
17449 assert( row->origin != NULL );
17450 return (SCIP_CONS*) row->origin;
17451 }
17452 return NULL;
17453}
17454
17455/** returns origin constraint handler that created the row (NULL if not available) */
17457 SCIP_ROW* row /**< LP row */
17458 )
17459{
17460 assert( row != NULL );
17461
17463 {
17464 assert( row->origin != NULL );
17465 return (SCIP_CONSHDLR*) row->origin;
17466 }
17468 {
17469 assert(row->origin != NULL);
17470 return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17471 }
17472 return NULL;
17473}
17474
17475/** returns origin separator that created the row (NULL if not available) */
17477 SCIP_ROW* row /**< LP row */
17478 )
17479{
17480 assert( row != NULL );
17481
17483 {
17484 assert( row->origin != NULL );
17485 return (SCIP_SEPA*) row->origin;
17486 }
17487 return NULL;
17488}
17489
17490/** returns TRUE iff row is member of the global cut pool */
17492 SCIP_ROW* row /**< LP row */
17493 )
17494{
17495 assert(row != NULL);
17496
17497 return row->inglobalcutpool;
17498}
17499
17500/** gets position of row in current LP, or -1 if it is not in LP */
17502 SCIP_ROW* row /**< LP row */
17503 )
17504{
17505 assert(row != NULL);
17506 assert((row->lppos == -1) == (row->lpdepth == -1));
17507
17508 return row->lppos;
17509}
17510
17511/** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17513 SCIP_ROW* row /**< LP row */
17514 )
17515{
17516 assert(row != NULL);
17517 assert((row->lppos == -1) == (row->lpdepth == -1));
17518
17519 return row->lpdepth;
17520}
17521
17522/** returns TRUE iff row is member of current LP */
17524 SCIP_ROW* row /**< LP row */
17525 )
17526{
17527 assert(row != NULL);
17528 assert((row->lppos == -1) == (row->lpdepth == -1));
17529
17530 return (row->lppos >= 0);
17531}
17532
17533/** changes the rank of LP row */
17535 SCIP_ROW* row, /**< LP row */
17536 int rank /**< new value for rank */
17537 )
17538{
17539 assert(row != NULL);
17540
17541 row->rank = rank;
17542}
17543
17544/** returns the number of times that this row has been sharp in an optimal LP solution */
17546 SCIP_ROW* row /**< row */
17547 )
17548{
17549 assert(row != NULL);
17550
17551 return row->activeinlpcounter;
17552}
17553
17554/** returns the number of LPs since this row has been created */
17556 SCIP_ROW* row /**< row */
17557 )
17558{
17559 assert(row != NULL);
17560
17561 return row->nlpsaftercreation;
17562}
17563
17564/** gets array with columns of the LP */
17566 SCIP_LP* lp /**< current LP data */
17567 )
17568{
17569 assert(lp != NULL);
17570
17571 return lp->cols;
17572}
17573
17574/** gets current number of columns in LP */
17576 SCIP_LP* lp /**< current LP data */
17577 )
17578{
17579 assert(lp != NULL);
17580
17581 return lp->ncols;
17582}
17583
17584/** gets current number of unfixed columns in LP */
17586 SCIP_LP* lp, /**< current LP data */
17587 SCIP_Real eps /**< numerical tolerance */
17588 )
17589{
17590 SCIP_COL** lpcols;
17591 int nlpcols;
17592 int nunfixedcols;
17593 int c;
17594
17595 assert(lp != NULL);
17596 assert(eps > 0.0);
17597
17598 lpcols = lp->cols;
17599 nlpcols = lp->ncols;
17600
17601 nunfixedcols = 0;
17602 for( c = 0; c < nlpcols; ++c )
17603 {
17604 if( lpcols[c]->ub - lpcols[c]->lb > eps )
17605 ++nunfixedcols;
17606 }
17607
17608 return nunfixedcols;
17609}
17610
17611/** gets array with rows of the LP */
17613 SCIP_LP* lp /**< current LP data */
17614 )
17615{
17616 assert(lp != NULL);
17617
17618 return lp->rows;
17619}
17620
17621/** gets current number of rows in LP */
17623 SCIP_LP* lp /**< current LP data */
17624 )
17625{
17626 assert(lp != NULL);
17627
17628 return lp->nrows;
17629}
17630
17631/** gets array with newly added columns after the last mark */
17633 SCIP_LP* lp /**< current LP data */
17634 )
17635{
17636 assert(lp != NULL);
17637 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17638
17639 return &(lp->cols[lp->firstnewcol]);
17640}
17641
17642/** gets number of newly added columns after the last mark */
17644 SCIP_LP* lp /**< current LP data */
17645 )
17646{
17647 assert(lp != NULL);
17648 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17649
17650 return lp->ncols - lp->firstnewcol;
17651}
17652
17653/** gets array with newly added rows after the last mark */
17655 SCIP_LP* lp /**< current LP data */
17656 )
17657{
17658 assert(lp != NULL);
17659 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17660
17661 return &(lp->rows[lp->firstnewrow]);
17662}
17663
17664/** gets number of newly added rows after the last mark */
17666 SCIP_LP* lp /**< current LP data */
17667 )
17668{
17669 assert(lp != NULL);
17670 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17671
17672 return lp->nrows - lp->firstnewrow;
17673}
17674
17675/** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17677 SCIP_SET* set, /**< global SCIP settings */
17678 SCIP_LP* lp /**< LP data */
17679 )
17680{
17681 if( lp->objsqrnormunreliable )
17682 {
17683 SCIP_COL** cols;
17684 int c;
17685
17686 cols = lp->cols;
17687 assert(cols != NULL || lp->ncols == 0);
17688
17689 lp->objsqrnorm = 0.0;
17690
17691 for( c = lp->ncols - 1; c >= 0; --c )
17692 {
17693 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
17694 }
17695 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17696
17697 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17698 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17699
17701 }
17702 return;
17703}
17704
17705/** gets Euclidean norm of objective function vector of column variables, only use this method if
17706 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17708 SCIP_LP* lp /**< LP data */
17709 )
17710{
17711 assert(lp != NULL);
17712 assert(!lp->objsqrnormunreliable);
17713 assert(lp->objsqrnorm >= 0.0);
17714
17715 return sqrt(lp->objsqrnorm);
17716}
17717
17718/** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17720 SCIP_LP* lp, /**< LP data */
17721 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
17722 )
17723{
17724 assert(lp != NULL);
17725
17726 lp->rootlpisrelax = isrelax;
17727}
17728
17729/** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17731 SCIP_LP* lp /**< LP data */
17732 )
17733{
17734 assert(lp != NULL);
17735
17736 return lp->rootlpisrelax;
17737}
17738
17739/** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17741 SCIP_LP* lp /**< LP data */
17742 )
17743{
17744 assert(lp != NULL);
17745
17746 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17747}
17748
17749/** gets part of the objective value of the root node LP that results from COLUMN variables only;
17750 * returns SCIP_INVALID if the root node LP was not (yet) solved
17751 */
17753 SCIP_LP* lp /**< LP data */
17754 )
17755{
17756 assert(lp != NULL);
17757
17758 return lp->rootlpobjval;
17759}
17760
17761/** gets part of the objective value of the root node LP that results from LOOSE variables only;
17762 * returns SCIP_INVALID if the root node LP was not (yet) solved
17763 */
17765 SCIP_LP* lp /**< LP data */
17766 )
17767{
17768 assert(lp != NULL);
17769
17770 return lp->rootlooseobjval;
17771}
17772
17773/** gets the LP solver interface */
17775 SCIP_LP* lp /**< current LP data */
17776 )
17777{
17778 assert(lp != NULL);
17779
17780 return lp->lpi;
17781}
17782
17783/** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17785 SCIP_LP* lp, /**< LP data */
17786 SCIP_Bool relax /**< is the current lp a relaxation? */
17787 )
17788{
17789 assert(lp != NULL);
17790
17791 lp->isrelax = relax;
17792}
17793
17794/** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17795 * solution value a valid local lower bound?
17796 */
17798 SCIP_LP* lp /**< LP data */
17799 )
17800{
17801 assert(lp != NULL);
17802
17803 return lp->isrelax;
17804}
17805
17806/** returns whether the current LP is flushed and solved */
17808 SCIP_LP* lp /**< current LP data */
17809 )
17810{
17811 assert(lp != NULL);
17812
17813 return lp->flushed && lp->solved;
17814}
17815
17816/** return whether the current LP solution passed the primal feasibility check */
17818 SCIP_LP* lp /**< current LP data */
17819 )
17820{
17821 assert(lp != NULL);
17822
17823 return (lp->primalchecked && lp->primalfeasible);
17824}
17825
17826/** return whether the current LP solution passed the dual feasibility check */
17828 SCIP_LP* lp /**< current LP data */
17829 )
17830{
17831 assert(lp != NULL);
17832
17833 return (lp->dualchecked && lp->dualfeasible);
17834}
17835
17836/** returns whether the current LP solution is a basic solution */
17838 SCIP_LP* lp /**< current LP data */
17839 )
17840{
17841 assert(lp != NULL);
17842
17843 return lp->solisbasic;
17844}
17845
17846/** returns whether the LP is in diving mode */
17848 SCIP_LP* lp /**< current LP data */
17849 )
17850{
17851 assert(lp != NULL);
17852
17853 return lp->diving;
17854}
17855
17856/** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17858 SCIP_LP* lp /**< current LP data */
17859 )
17860{
17861 assert(lp != NULL);
17862
17863 return lp->divingobjchg;
17864}
17865
17866/** marks the diving LP to have a changed objective function */
17868 SCIP_LP* lp /**< current LP data */
17869 )
17870{
17871 assert(lp != NULL);
17872 assert(lp->diving || lp->probing);
17873
17874 lp->divingobjchg = TRUE;
17875}
17876
17877/** marks the diving LP to not have a changed objective function anymore */
17879 SCIP_LP* lp /**< current LP data */
17880 )
17881{
17882 assert(lp != NULL);
17883 assert(lp->diving || lp->probing);
17884
17885 lp->divingobjchg = FALSE;
17886}
17887
17888/* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17890 SCIP_LP* lp /**< current LP data */
17891 )
17892{
17893 assert(lp != NULL);
17894 assert(lp->diving || lp->ndivechgsides == 0);
17895
17896 return (lp->ndivechgsides > 0);
17897}
17898
17899/** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17900static
17902 SCIP_LPI* lpi, /**< auxiliary LP interface */
17903 SCIP_SET* set, /**< global SCIP settings */
17904 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17905 SCIP_LP* lp, /**< LP data */
17906 SCIP_PROB* prob, /**< problem data */
17907 SCIP_Bool relaxrows, /**< should the rows be relaxed */
17908 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
17909 SCIP_Real timelimit, /**< time limit for LP solver */
17910 int iterlimit, /**< iteration limit for LP solver */
17911 SCIP_Real* point, /**< array to store relative interior point on exit */
17912 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
17913 )
17914{
17915 SCIP_RETCODE retcode;
17916 SCIP_Real* primal;
17917 SCIP_Real* obj;
17918 SCIP_Real* lb;
17919 SCIP_Real* ub;
17920 SCIP_Real* matvals;
17921 SCIP_Real* matlhs;
17922 SCIP_Real* matrhs;
17923 SCIP_Real objval;
17924 SCIP_Real alpha;
17925 int* matinds;
17926 int* matbeg;
17927#ifndef NDEBUG
17928 int nslacks;
17929#endif
17930 int nnewcols;
17931 int ntotnonz = 0;
17932 int ntotrows = 0;
17933 int matrowidx;
17934 int matidx;
17935 int cnt;
17936 int j;
17937 int i;
17938
17939 assert(lpi != NULL);
17940
17941 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17942 if( retcode != SCIP_OKAY )
17943 {
17944 /* stop execution on error, since result is likely to be unsuable */
17945 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17946 return SCIP_LPERROR;
17947 }
17948
17950 if( retcode != SCIP_OKAY )
17951 {
17952 /* stop execution on error, since result is likely to be unsuable */
17953 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17954 return SCIP_LPERROR;
17955 }
17956
17957 /* get storage */
17958 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17959 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17960 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17961 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17962
17963 /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17964 for( j = 0; j < lp->ncols; ++j )
17965 {
17966 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
17967 obj[j] = 0.0;
17968 lb[j] = -SCIPlpiInfinity(lpi);
17969 ub[j] = SCIPlpiInfinity(lpi);
17970 /* note: we could also use the original bounds - free variables seem to be faster. */
17971 }
17972
17973 /* add artificial alpha variable */
17974 nnewcols = lp->ncols;
17975 obj[nnewcols] = 0.0;
17976 lb[nnewcols] = 1.0;
17977 ub[nnewcols] = SCIPlpiInfinity(lpi);
17978 ++nnewcols;
17979
17980 /* create slacks for rows */
17981 for( i = 0; i < lp->nrows; ++i )
17982 {
17983 SCIP_ROW* row;
17984
17985 row = lp->rows[i];
17986 assert( row != NULL );
17987
17988 if( SCIProwIsModifiable(row) )
17989 continue;
17990
17991 /* make sure row is sorted */
17992 rowSortLP(row);
17993 assert( row->lpcolssorted );
17994
17995 /* check whether we have an equation */
17996 if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
17997 {
17998 assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
17999 assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
18000 ntotnonz += row->nlpcols + 1;
18001 ++ntotrows;
18002 }
18003 else
18004 {
18005 /* otherwise add slacks for each side if necessary */
18006 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18007 {
18008 if ( relaxrows )
18009 {
18010 lb[nnewcols] = 0.0;
18011 ub[nnewcols] = 1.0;
18012 obj[nnewcols++] = 1.0;
18013 ntotnonz += row->nlpcols + 2;
18014 }
18015 else
18016 ntotnonz += row->nlpcols + 1;
18017 ++ntotrows;
18018 }
18019 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18020 {
18021 if ( relaxrows )
18022 {
18023 lb[nnewcols] = 0.0;
18024 ub[nnewcols] = 1.0;
18025 obj[nnewcols++] = 1.0;
18026 ntotnonz += row->nlpcols + 2;
18027 }
18028 else
18029 ntotnonz += row->nlpcols + 1;
18030 ++ntotrows;
18031 }
18032 }
18033 }
18034
18035 /* create slacks for objective cutoff row */
18036 if( inclobjcutoff && relaxrows )
18037 {
18038 /* add slacks for right hand side */
18039 lb[nnewcols] = 0.0;
18040 ub[nnewcols] = 1.0;
18041 obj[nnewcols++] = 1.0;
18042 ntotnonz += lp->ncols + 2;
18043 ++ntotrows;
18044 }
18045
18046 /* create slacks for bounds */
18047 for( j = 0; j < lp->ncols; ++j )
18048 {
18049 SCIP_COL* col;
18050
18051 col = lp->cols[j];
18052 assert( col != NULL );
18053
18054 /* no slacks for fixed variables */
18055 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18056 {
18057 ++ntotrows;
18058 ntotnonz += 2;
18059 }
18060 else
18061 {
18062 /* add slacks for each bound if necessary */
18063 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18064 {
18065 lb[nnewcols] = 0.0;
18066 ub[nnewcols] = 1.0;
18067 obj[nnewcols++] = 1.0;
18068 ntotnonz += 3;
18069 ++ntotrows;
18070 }
18071 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18072 {
18073 lb[nnewcols] = 0.0;
18074 ub[nnewcols] = 1.0;
18075 obj[nnewcols++] = 1.0;
18076 ntotnonz += 3;
18077 ++ntotrows;
18078 }
18079 }
18080 }
18081#ifndef NDEBUG
18082 nslacks = nnewcols - lp->ncols - 1;
18083 assert( nslacks >= 0 );
18084 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18085#endif
18086
18087 /* add columns */
18088 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18089
18090 /* free storage */
18094
18095 /* prepare storage for rows */
18096 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18097 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18098 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18099 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18100 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18101
18102 /* create rows arising from original rows */
18103 cnt = 0;
18104 matrowidx = 0;
18105 matidx = 0;
18106 for( i = 0; i < lp->nrows; ++i )
18107 {
18108 SCIP_ROW* row;
18109 SCIP_COL** rowcols;
18110 SCIP_Real* rowvals;
18111 SCIP_Real lhs;
18112 SCIP_Real rhs;
18113 int nnonz;
18114
18115 row = lp->rows[i];
18116 assert( row != NULL );
18117
18118 if( SCIProwIsModifiable(row) )
18119 continue;
18120 assert( row->lpcolssorted );
18121
18122 /* get row data */
18123 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18124 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18125 nnonz = row->nlpcols;
18126 assert( nnonz <= lp->ncols );
18127 rowcols = row->cols;
18128 rowvals = row->vals;
18129
18130 /* if we have an equation */
18131 if( SCIPsetIsEQ(set, lhs, rhs) )
18132 {
18133 /* set up indices */
18134 matbeg[matrowidx] = matidx;
18135 for( j = 0; j < nnonz; ++j )
18136 {
18137 assert( rowcols[j] != NULL );
18138 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18139 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18140 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18141 matinds[matidx] = rowcols[j]->lppos;
18142 matvals[matidx++] = rowvals[j];
18143 assert( matidx <= ntotnonz );
18144 }
18145
18146 /* add artificial variable */
18147 if ( ! SCIPsetIsZero(set, rhs) )
18148 {
18149 matinds[matidx] = lp->ncols;
18150 matvals[matidx++] = -rhs;
18151 assert( matidx <= ntotnonz );
18152 }
18153
18154 matlhs[matrowidx] = 0.0;
18155 matrhs[matrowidx++] = 0.0;
18156 assert( matrowidx <= ntotrows );
18157 }
18158 else
18159 {
18160 SCIP_Real abslhs = REALABS(lhs);
18161 SCIP_Real absrhs = REALABS(rhs);
18162
18163 assert(!SCIPsetIsEQ(set, lhs, rhs));
18164
18165 /* treat lhs */
18166 if( !SCIPsetIsInfinity(set, abslhs) )
18167 {
18168 /* set up indices */
18169 matbeg[matrowidx] = matidx;
18170 for( j = 0; j < nnonz; ++j )
18171 {
18172 assert( rowcols[j] != NULL );
18173 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18174 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18175 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18176 matinds[matidx] = rowcols[j]->lppos;
18177 matvals[matidx++] = rowvals[j];
18178 assert( matidx <= ntotnonz );
18179 }
18180
18181 /* add artificial variable */
18182 if ( ! SCIPsetIsZero(set, lhs) )
18183 {
18184 matinds[matidx] = lp->ncols;
18185 matvals[matidx++] = -lhs;
18186 assert( matidx <= ntotnonz );
18187 }
18188
18189 if( relaxrows )
18190 {
18191 /* add slack variable */
18192 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/
18193 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18194 assert( matidx <= ntotnonz );
18195 ++cnt;
18196 }
18197
18198 matlhs[matrowidx] = 0.0;
18199 matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18200 assert( matrowidx <= ntotrows );
18201 }
18202
18203 /* treat rhs */
18204 if( !SCIPsetIsInfinity(set, absrhs) )
18205 {
18206 /* set up indices */
18207 matbeg[matrowidx] = matidx;
18208 for( j = 0; j < nnonz; ++j )
18209 {
18210 assert( rowcols[j] != NULL );
18211 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18212 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18213 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18214 matinds[matidx] = rowcols[j]->lppos;
18215 matvals[matidx++] = rowvals[j];
18216 assert( matidx <= ntotnonz );
18217 }
18218
18219 /* add artificial variable */
18220 if ( ! SCIPsetIsZero(set, rhs) )
18221 {
18222 matinds[matidx] = lp->ncols;
18223 matvals[matidx++] = -rhs;
18224 assert( matidx <= ntotnonz );
18225 }
18226
18227 if( relaxrows )
18228 {
18229 /* add slack variable */
18230 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/
18231 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18232 ++cnt;
18233 }
18234
18235 matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18236 matrhs[matrowidx++] = 0.0;
18237 assert( matrowidx <= ntotrows );
18238 }
18239 }
18240 }
18241
18242 /* create row arising from objective cutoff */
18243 if( inclobjcutoff )
18244 {
18245 SCIP_Real rhs;
18246
18247 /* get row data */
18248 assert(lp->looseobjvalinf == 0);
18249 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18250
18251 /* set up indices and coefficients */
18252 matbeg[matrowidx] = matidx;
18253 for( j = 0; j < lp->ncols; ++j )
18254 {
18255 assert( lp->cols[j] != NULL );
18256 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18257 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18258
18259 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18260 {
18261 matinds[matidx] = lp->cols[j]->lppos;
18262 matvals[matidx++] = lp->cols[j]->obj;
18263 assert( matidx <= ntotnonz );
18264 }
18265 }
18266
18267 /* treat rhs */
18268
18269 /* add artificial variable */
18270 if ( ! SCIPsetIsZero(set, rhs) )
18271 {
18272 matinds[matidx] = lp->ncols;
18273 matvals[matidx++] = -rhs;
18274 assert( matidx <= ntotnonz );
18275 }
18276
18277 if( relaxrows )
18278 {
18279 SCIP_Real absrhs = REALABS(rhs);
18280
18281 /* add slack variable */
18282 matvals[matidx] = MAX(1.0, absrhs);
18283 matinds[matidx++] = lp->ncols + 1 + cnt;
18284 assert( matidx <= ntotnonz );
18285 ++cnt;
18286 }
18287 matlhs[matrowidx] = -SCIPsetInfinity(set);
18288 matrhs[matrowidx++] = 0.0;
18289 assert( matrowidx <= ntotrows );
18290 }
18291
18292 /* create rows arising from bounds */
18293 for( j = 0; j < lp->ncols; ++j )
18294 {
18295 SCIP_COL* col;
18296 SCIP_Real abscollb;
18297 SCIP_Real abscolub;
18298
18299 col = lp->cols[j];
18300 assert( col != NULL );
18301 assert( col->lppos == j );
18302
18303 /* fixed variable */
18304 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18305 {
18306 /* set up index of column */
18307 matbeg[matrowidx] = matidx;
18308
18309 matinds[matidx] = j;
18310 matvals[matidx++] = 1.0;
18311 assert( matidx <= ntotnonz );
18312
18313 /* add artificial variable */
18314 if ( ! SCIPsetIsZero(set, col->ub) )
18315 {
18316 matinds[matidx] = lp->ncols;
18317 matvals[matidx++] = -col->ub;
18318 assert( matidx <= ntotnonz );
18319 }
18320
18321 matlhs[matrowidx] = 0.0;
18322 matrhs[matrowidx++] = 0.0;
18323 assert( matrowidx <= ntotrows );
18324
18325 continue;
18326 }
18327
18328 abscollb = REALABS(col->lb);
18329 abscolub = REALABS(col->ub);
18330
18331 /* lower bound */
18332 if ( ! SCIPsetIsInfinity(set, abscollb) )
18333 {
18334 /* set up index of column */
18335 matbeg[matrowidx] = matidx;
18336
18337 matinds[matidx] = j;
18338 matvals[matidx++] = 1.0;
18339 assert( matidx <= ntotnonz );
18340
18341 /* add artificial variable */
18342 if ( ! SCIPsetIsZero(set, col->lb) )
18343 {
18344 matinds[matidx] = lp->ncols;
18345 matvals[matidx++] = -col->lb;
18346 assert( matidx <= ntotnonz );
18347 }
18348
18349 /* add slack variable */
18350 matvals[matidx] = -MAX(1.0, abscollb);
18351 matinds[matidx++] = lp->ncols + 1 + cnt;
18352 assert( matidx <= ntotnonz );
18353 ++cnt;
18354
18355 matlhs[matrowidx] = 0.0;
18356 matrhs[matrowidx++] = SCIPsetInfinity(set);
18357 assert( matrowidx <= ntotrows );
18358 }
18359
18360 /* upper bound */
18361 if ( ! SCIPsetIsInfinity(set, abscolub) )
18362 {
18363 /* set up index of column */
18364 matbeg[matrowidx] = matidx;
18365
18366 matinds[matidx] = j;
18367 matvals[matidx++] = 1.0;
18368 assert( matidx <= ntotnonz );
18369
18370 /* add artificial variable */
18371 if ( ! SCIPsetIsZero(set, col->ub) )
18372 {
18373 matinds[matidx] = lp->ncols;
18374 matvals[matidx++] = -col->ub;
18375 assert( matidx <= ntotnonz );
18376 }
18377
18378 /* add slack variable */
18379 matvals[matidx] = MAX(1.0, abscolub);
18380 matinds[matidx++] = lp->ncols + 1 + cnt;
18381 assert( matidx <= ntotnonz );
18382 ++cnt;
18383
18384 matlhs[matrowidx] = -SCIPsetInfinity(set);
18385 matrhs[matrowidx++] = 0.0;
18386 assert( matrowidx <= ntotrows );
18387 }
18388 }
18389 assert( cnt == nslacks );
18390 assert( matrowidx == ntotrows );
18391
18392 /* add rows */
18393 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18394
18395 SCIPsetFreeBufferArray(set, &matrhs);
18396 SCIPsetFreeBufferArray(set, &matlhs);
18397 SCIPsetFreeBufferArray(set, &matbeg);
18398 SCIPsetFreeBufferArray(set, &matvals);
18399 SCIPsetFreeBufferArray(set, &matinds);
18400
18401#ifdef SCIP_OUTPUT
18402 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18403#endif
18404
18405#ifndef NDEBUG
18406 {
18407 int ncols;
18408 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18409 assert( ncols == nnewcols );
18410 }
18411#endif
18412
18413 /* set time limit */
18414 if( SCIPsetIsInfinity(set, timelimit) )
18415 timelimit = SCIPlpiInfinity(lpi);
18416 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18417
18418 /* check, if parameter is unknown */
18419 if( retcode == SCIP_PARAMETERUNKNOWN )
18420 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18421 else if ( retcode != SCIP_OKAY )
18422 return retcode;
18423
18424 /* set iteration limit */
18425 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18426
18427 /* check, if parameter is unknown */
18428 if( retcode == SCIP_PARAMETERUNKNOWN )
18429 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18430 else if ( retcode != SCIP_OKAY )
18431 return retcode;
18432
18433 /* solve and store point */
18434 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18435 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */
18436
18437#ifndef NDEBUG
18438 if ( SCIPlpiIsIterlimExc(lpi) )
18439 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18440 if ( SCIPlpiIsTimelimExc(lpi) )
18441 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18442#endif
18443
18444 if( SCIPlpiIsOptimal(lpi) )
18445 {
18446 /* get primal solution */
18447 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18448 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18449 alpha = primal[lp->ncols];
18450 assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18451
18452 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18453
18454 /* construct relative interior point */
18455 for( j = 0; j < lp->ncols; ++j )
18456 point[j] = primal[j]/alpha;
18457
18458#ifdef SCIP_DEBUG
18459 /* check whether the point is a relative interior point */
18460 cnt = 0;
18461 if( relaxrows )
18462 {
18463 for( i = 0; i < lp->nrows; ++i )
18464 {
18465 SCIP_ROW* row;
18466 SCIP_COL** rowcols;
18467 SCIP_Real* rowvals;
18468 SCIP_Real lhs;
18469 SCIP_Real rhs;
18470 SCIP_Real sum;
18471 int nnonz;
18472
18473 row = lp->rows[i];
18474 assert( row != NULL );
18475
18476 /* get row data */
18477 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18478 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18479 nnonz = row->nlpcols;
18480 assert( nnonz <= lp->ncols );
18481 rowcols = row->cols;
18482 rowvals = row->vals;
18483
18484 sum = 0.0;
18485 for( j = 0; j < nnonz; ++j )
18486 sum += rowvals[j] * primal[rowcols[j]->lppos];
18487 sum /= alpha;
18488
18489 /* if we have an equation */
18490 if( SCIPsetIsEQ(set, lhs, rhs) )
18491 {
18492 assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18493 }
18494 else
18495 {
18496 /* treat lhs */
18497 if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18498 {
18499 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18500 ++cnt;
18501 }
18502 /* treat rhs */
18503 if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18504 {
18505 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18506 ++cnt;
18507 }
18508 }
18509 }
18510 if( inclobjcutoff )
18511 {
18512 SCIP_Real sum;
18513#ifndef NDEBUG
18514 SCIP_Real rhs;
18515
18516 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18517#endif
18518 sum = 0.0;
18519 for( j = 0; j < lp->ncols; ++j )
18520 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18521 sum /= alpha;
18522
18523 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18524 ++cnt;
18525 }
18526 }
18527 /* check bounds */
18528 for( j = 0; j < lp->ncols; ++j )
18529 {
18530 SCIP_COL* col;
18531#ifndef NDEBUG
18532 SCIP_Real val;
18533#endif
18534
18535 col = lp->cols[j];
18536 assert( col != NULL );
18537#ifndef NDEBUG
18538 val = primal[col->lppos] / alpha;
18539#endif
18540 /* if the variable is not fixed */
18541 if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18542 {
18543 /* treat lb */
18544 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18545 {
18546 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18547 ++cnt;
18548 }
18549 /* treat rhs */
18550 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18551 {
18552 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18553 ++cnt;
18554 }
18555 }
18556 }
18557#endif
18558
18559 /* free */
18560 SCIPsetFreeBufferArray(set, &primal);
18561
18562 *success = TRUE;
18563 }
18564
18565 return SCIP_OKAY;
18566}
18567
18568/** compute relative interior point
18569 *
18570 * We use the approach of@par
18571 * R. Freund, R. Roundy, M. J. Todd@par
18572 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18573 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18574 *
18575 * to compute a relative interior point for the current LP.
18576 *
18577 * Assume the original LP looks as follows:
18578 * \f[
18579 * \begin{array}{rrl}
18580 * \min & c^T x &\\
18581 * & A x & \geq a\\
18582 * & B x & \leq b\\
18583 * & D x & = d.
18584 * \end{array}
18585 * \f]
18586 * Note that bounds should be included in the system.
18587 *
18588 * To find an interior point the following LP does the job:
18589 * \f[
18590 * \begin{array}{rrl}
18591 * \max & 1^T y &\\
18592 * & A x - y - \alpha a & \geq 0\\
18593 * & B x + y - \alpha b & \leq 0\\
18594 * & D x - \alpha d & = 0\\
18595 * & 0 \leq y & \leq 1\\
18596 * & \alpha & \geq 1.
18597 * \end{array}
18598 * \f]
18599 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18600 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18601 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18602 */
18604 SCIP_SET* set, /**< global SCIP settings */
18605 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18606 SCIP_LP* lp, /**< LP data */
18607 SCIP_PROB* prob, /**< problem data */
18608 SCIP_Bool relaxrows, /**< should the rows be relaxed */
18609 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
18610 SCIP_Real timelimit, /**< time limit for LP solver */
18611 int iterlimit, /**< iteration limit for LP solver */
18612 SCIP_Real* point, /**< array to store relative interior point on exit */
18613 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
18614 )
18615{
18616 SCIP_LPI* lpi;
18617 SCIP_RETCODE retcode;
18618
18619 assert(set != NULL);
18620 assert(lp != NULL);
18621 assert(point != NULL);
18622 assert(success != NULL);
18623
18624 *success = FALSE;
18625
18626 /* check time and iteration limits */
18627 if ( timelimit <= 0.0 || iterlimit <= 0 )
18628 return SCIP_OKAY;
18629
18630 /* exit if there are no columns */
18631 assert(lp->nrows >= 0);
18632 assert(lp->ncols >= 0);
18633 if( lp->ncols == 0 )
18634 return SCIP_OKAY;
18635
18636 /* disable objective cutoff if we have none */
18637 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18638 inclobjcutoff = FALSE;
18639
18640 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18641
18642 /* if there are no rows, we return the zero point */
18643 if( lp->nrows == 0 && !inclobjcutoff )
18644 {
18645 /* create zero point */
18646 BMSclearMemoryArray(point, lp->ncols);
18647 *success = TRUE;
18648
18649 return SCIP_OKAY;
18650 }
18651
18652 /* create auxiliary LP */
18653 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18654
18655 /* catch return code and ensure that lpi is freed, anyway */
18656 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18657
18658 SCIP_CALL( SCIPlpiFree(&lpi) );
18659
18660 /* return error, unless we obtained an LP error */
18661 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18662 {
18663 SCIP_CALL( retcode );
18664 }
18665
18666 return SCIP_OKAY;
18667}
18668
18669/** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18670 * based on the changes applied when reducing the problem to the optimal face
18671 *
18672 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18673 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18674 */
18676 SCIP_LP* lp, /**< LP data */
18677 SCIP_SET* set, /**< global SCIP settings */
18678 SCIP_STAT* stat, /**< problem statistics */
18679 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */
18680 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */
18681 )
18682{
18683 assert(lp != NULL);
18684 assert(lp->solved);
18685 assert(lp->flushed);
18686
18687 if( lp->validdegeneracylp != stat->nlps )
18688 {
18689 lp->validdegeneracylp = stat->nlps;
18690
18691 /* if the LP was solved to optimality, we determine the dual degeneracy */
18693 {
18694 SCIP_COL** cols;
18695 SCIP_ROW** rows;
18696 SCIP_COL* col;
18697 int ncols;
18698 int nrows;
18699 int nfixedcols = 0;
18700 int nalreadyfixedcols = 0;
18701 int nfixedrows = 0;
18702#ifndef NDEBUG
18703 int nimplicitfixedrows = 0;
18704#endif
18705 int nineq = 0;
18706 int c;
18707 int r;
18708 int nbasicequalities = 0;
18709
18710 cols = lp->cols;
18711 rows = lp->rows;
18712 ncols = lp->ncols;
18713 nrows = lp->nrows;
18714
18715 /* count number of columns that will be fixed when reducing the LP to the optimal face */
18716 for( c = ncols - 1 ; c >= 0; --c )
18717 {
18718 col = cols[c];
18719 assert(SCIPcolIsInLP(col));
18720
18721 /* column is not basic and not fixed already */
18723 {
18724 /* variable with nonzero reduced costs are fixed */
18725 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18726 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18727 ++nfixedcols;
18728 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18729 ++nalreadyfixedcols;
18730 }
18731 }
18732
18733 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18734 for( r = nrows - 1; r >= 0; --r )
18735 {
18736 SCIP_ROW* row = rows[r];
18737
18738 assert(SCIProwIsInLP(row));
18739
18740 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18741 {
18742 SCIP_Real dualsol = SCIProwGetDualsol(row);
18743
18744 ++nineq;
18745
18747 {
18748 /* rows with nonzero dual solution are turned into equations */
18749 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18750 if( !SCIPsetIsZero(set, dualsol) )
18751 {
18752 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18753 {
18754 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol));
18755 ++nfixedrows;
18756 }
18757 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18758 {
18759 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol));
18760 ++nfixedrows;
18761 }
18762 }
18763#ifndef NDEBUG
18764 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18765 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18766 {
18767 ++nimplicitfixedrows;
18768 }
18769#endif
18770 }
18771 }
18773 ++nbasicequalities;
18774 }
18775 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18776
18777 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18778 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18779 else
18780 lp->degeneracy = 0.0;
18781
18782 if( nrows > 0 )
18783 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18784 else
18785 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18786 assert(lp->degeneracy >= 0);
18787 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18788 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18789 }
18790 else
18791 {
18792 lp->degeneracy = 0.0;
18793 lp->varconsratio = 0.0;
18794 }
18795 }
18796
18797 *degeneracy = lp->degeneracy;
18798 *varconsratio = lp->varconsratio;
18799
18800 return SCIP_OKAY;
18801}
18802
18803/** checks, if absolute difference of values is in range of LP primal feastol */
18805 SCIP_SET* set, /**< global SCIP settings */
18806 SCIP_LP* lp, /**< current LP data */
18807 SCIP_Real val1, /**< first value to be compared */
18808 SCIP_Real val2 /**< second value to be compared */
18809 )
18810{
18811 assert(set != NULL);
18812 assert(lp != NULL);
18813
18814 /* avoid to compare two different infinities; the reason for that is
18815 * that such a comparison can lead to unexpected results */
18816 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18817 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18818 || val1 == val2 ); /*lint !e777*/
18819
18820 return EPSEQ(val1, val2, lp->feastol);
18821}
18822
18823/** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18825 SCIP_SET* set, /**< global SCIP settings */
18826 SCIP_LP* lp, /**< current LP data */
18827 SCIP_Real val1, /**< first value to be compared */
18828 SCIP_Real val2 /**< second value to be compared */
18829 )
18830{
18831 assert(set != NULL);
18832 assert(lp != NULL);
18833
18834 /* avoid to compare two different infinities; the reason for that is
18835 * that such a comparison can lead to unexpected results */
18836 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18837 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18838 || val1 == val2 ); /*lint !e777*/
18839
18840 return EPSLT(val1, val2, lp->feastol);
18841}
18842
18843/** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18845 SCIP_SET* set, /**< global SCIP settings */
18846 SCIP_LP* lp, /**< current LP data */
18847 SCIP_Real val1, /**< first value to be compared */
18848 SCIP_Real val2 /**< second value to be compared */
18849 )
18850{
18851 assert(set != NULL);
18852 assert(lp != NULL);
18853
18854 /* avoid to compare two different infinities; the reason for that is
18855 * that such a comparison can lead to unexpected results */
18856 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18857 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18858 || val1 == val2 ); /*lint !e777*/
18859
18860 return EPSLE(val1, val2, lp->feastol);
18861}
18862
18863/** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18865 SCIP_SET* set, /**< global SCIP settings */
18866 SCIP_LP* lp, /**< current LP data */
18867 SCIP_Real val1, /**< first value to be compared */
18868 SCIP_Real val2 /**< second value to be compared */
18869 )
18870{
18871 assert(set != NULL);
18872 assert(lp != NULL);
18873
18874 /* avoid to compare two different infinities; the reason for that is
18875 * that such a comparison can lead to unexpected results */
18876 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18877 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18878 || val1 == val2 ); /*lint !e777*/
18879
18880 return EPSGT(val1, val2, lp->feastol);
18881}
18882
18883/** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18885 SCIP_SET* set, /**< global SCIP settings */
18886 SCIP_LP* lp, /**< current LP data */
18887 SCIP_Real val1, /**< first value to be compared */
18888 SCIP_Real val2 /**< second value to be compared */
18889 )
18890{
18891 assert(set != NULL);
18892 assert(lp != NULL);
18893
18894 /* avoid to compare two different infinities; the reason for that is
18895 * that such a comparison can lead to unexpected results */
18896 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18897 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18898 || val1 == val2 ); /*lint !e777*/
18899
18900 return EPSGE(val1, val2, lp->feastol);
18901}
18902
18903/** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18905 SCIP_LP* lp, /**< current LP data */
18906 SCIP_Real val /**< value to process */
18907 )
18908{
18909 assert(lp != NULL);
18910
18911 return EPSZ(val, lp->feastol);
18912}
18913
18914/** checks, if value is greater than LP primal feasibility tolerance */
18916 SCIP_LP* lp, /**< current LP data */
18917 SCIP_Real val /**< value to process */
18918 )
18919{
18920 assert(lp != NULL);
18921
18922 return EPSP(val, lp->feastol);
18923}
18924
18925/** checks, if value is lower than -LP primal feasibility tolerance */
18927 SCIP_LP* lp, /**< current LP data */
18928 SCIP_Real val /**< value to process */
18929 )
18930{
18931 assert(lp != NULL);
18932
18933 return EPSN(val, lp->feastol);
18934}
static long bound
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
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
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6254
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6266
internal methods for constraints and constraint handlers
#define NULL
Definition: def.h:267
#define SCIP_MAXSTRLEN
Definition: def.h:288
#define EPSGE(x, y, eps)
Definition: def.h:202
#define SCIP_Longint
Definition: def.h:158
#define SCIP_UNUSED(x)
Definition: def.h:428
#define EPSISINT(x, eps)
Definition: def.h:210
#define SCIP_DEFAULT_SUMEPSILON
Definition: def.h:180
#define EPSP(x, eps)
Definition: def.h:204
#define SCIP_REAL_MAX
Definition: def.h:174
#define SCIP_INVALID
Definition: def.h:193
#define SCIP_Bool
Definition: def.h:91
#define SCIP_DEFAULT_EPSILON
Definition: def.h:179
#define EPSLE(x, y, eps)
Definition: def.h:200
#define MIN(x, y)
Definition: def.h:243
#define SCIP_ALLOC(x)
Definition: def.h:385
#define SCIP_Real
Definition: def.h:173
#define SCIP_UNKNOWN
Definition: def.h:194
#define EPSLT(x, y, eps)
Definition: def.h:199
#define ABS(x)
Definition: def.h:235
#define SQR(x)
Definition: def.h:214
#define EPSEQ(x, y, eps)
Definition: def.h:198
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:239
#define SCIP_CALL_ABORT(x)
Definition: def.h:353
#define EPSN(x, eps)
Definition: def.h:205
#define SCIP_LONGINT_FORMAT
Definition: def.h:165
#define SCIPABORT()
Definition: def.h:346
#define REALABS(x)
Definition: def.h:197
#define EPSGT(x, y, eps)
Definition: def.h:201
#define SCIP_LONGINT_MAX
Definition: def.h:159
#define EPSZ(x, eps)
Definition: def.h:203
#define SCIP_CALL(x)
Definition: def.h:374
SCIP_RETCODE SCIPeventCreateRowDeletedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:913
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2240
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1846
SCIP_RETCODE SCIPeventCreateRowSideChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:980
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1979
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1821
SCIP_RETCODE SCIPeventCreateRowConstChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:957
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1886
SCIP_RETCODE SCIPeventCreateRowCoefChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:932
SCIP_RETCODE SCIPeventCreateRowAddedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:894
internal methods for managing events
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_clp.cpp:1167
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3429
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3349
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_clp.cpp:3796
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3919
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2690
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2450
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_clp.cpp:2967
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:914
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_clp.cpp:2832
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_clp.cpp:3648
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_clp.cpp:4001
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_clp.cpp:480
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_clp.cpp:3833
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2283
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_clp.cpp:3610
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2329
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_clp.cpp:1709
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_clp.cpp:2857
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_clp.cpp:2766
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2752
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2006
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_clp.cpp:2405
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3623
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2720
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_clp.cpp:1084
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2488
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_clp.cpp:1647
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_clp.cpp:643
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2304
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2521
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2609
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3592
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2736
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3522
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_clp.cpp:3692
const char * SCIPlpiGetSolverName(void)
Definition: lpi_clp.cpp:454
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2468
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3241
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_clp.cpp:986
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3276
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3314
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_clp.cpp:1957
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2623
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2018
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_clp.cpp:1740
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2350
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_clp.cpp:2788
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2556
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:868
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_clp.cpp:1686
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3503
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2502
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1880
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:758
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1805
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_clp.cpp:2921
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_clp.cpp:3189
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_clp.cpp:531
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_clp.cpp:1240
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2647
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_clp.cpp:1435
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_clp.cpp:3895
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_clp.cpp:837
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:1018
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_clp.cpp:1417
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3389
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9121
#define SCIPisFinite(x)
Definition: pub_misc.h:1933
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9394
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11184
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10396
SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
Definition: lp.c:17009
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:17093
int SCIPcolGetVarProbindex(SCIP_COL *col)
Definition: lp.c:17062
SCIP_Bool SCIPcolIsRemovable(SCIP_COL *col)
Definition: lp.c:17083
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17042
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:17072
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16953
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17126
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17161
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17151
void SCIPcolSort(SCIP_COL *col)
Definition: lp.c:3435
int SCIPcolGetIndex(SCIP_COL *col)
Definition: lp.c:17052
SCIP_Real SCIPcolGetBestBound(SCIP_COL *col)
Definition: lp.c:16983
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16963
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16996
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16973
SCIP_Longint SCIPcolGetStrongbranchNode(SCIP_COL *col)
Definition: lp.c:17173
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:17140
int SCIPcolGetNStrongbranchs(SCIP_COL *col)
Definition: lp.c:17183
int SCIPcolGetAge(SCIP_COL *col)
Definition: lp.c:17193
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17115
int SCIPcolGetLPDepth(SCIP_COL *col)
Definition: lp.c:17104
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17031
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17203
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition: lp.c:17019
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
void SCIPintervalSub(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Bool SCIProwIsIntegral(SCIP_ROW *row)
Definition: lp.c:17391
void SCIProwSort(SCIP_ROW *row)
Definition: lp.c:6016
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17292
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17411
SCIP_Longint SCIProwGetActiveLPCount(SCIP_ROW *row)
Definition: lp.c:17545
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7788
SCIP_Real SCIProwGetScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7008
int SCIProwGetLPDepth(SCIP_ROW *row)
Definition: lp.c:17512
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7724
SCIP_CONS * SCIProwGetOriginCons(SCIP_ROW *row)
Definition: lp.c:17441
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17213
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17238
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:17491
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17302
int SCIProwGetAge(SCIP_ROW *row)
Definition: lp.c:17371
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:17227
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition: lp.c:17268
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17501
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17401
SCIP_CONSHDLR * SCIProwGetOriginConshdlr(SCIP_ROW *row)
Definition: lp.c:17456
SCIP_Longint SCIProwGetNLPsAfterCreation(SCIP_ROW *row)
Definition: lp.c:17555
void SCIProwLock(SCIP_ROW *row)
Definition: lp.c:5378
SCIP_Bool SCIProwIsRemovable(SCIP_ROW *row)
Definition: lp.c:17421
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17351
SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
Definition: lp.c:17476
void SCIProwUnlock(SCIP_ROW *row)
Definition: lp.c:5393
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition: lp.c:17280
SCIP_DECL_SORTPTRCOMP(SCIProwComp)
Definition: lp.c:950
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:17381
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17325
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17361
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:17534
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17258
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17523
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17312
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17248
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17431
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:17340
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17789
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18190
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17599
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17538
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18144
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3416
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17926
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18088
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17768
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17419
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17610
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18226
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18134
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18078
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3429
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18465
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17936
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18216
void SCIPsortPtrRealInt(void **ptrarray, SCIP_Real *realarray, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
void SCIPsortIntPtrIntReal(int *intarray1, void **ptrarray, int *intarray2, SCIP_Real *realarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10877
void SCIPprintSysError(const char *message)
Definition: misc.c:10769
interval arithmetics for provable bounds
static SCIP_RETCODE lpFlushDelRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: lp.c:8179
static void rowCalcIdxsAndVals(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4830
SCIP_RETCODE SCIPlpCleanupNew(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:15851
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17837
#define debugColPrint(x, y)
Definition: lp.c:159
static void getObjvalDeltaObj(SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj, SCIP_Real lb, SCIP_Real ub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13430
static SCIP_RETCODE lpSetObjlim(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real objlim, SCIP_Bool *success)
Definition: lp.c:2653
static SCIP_RETCODE insertColChgcols(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:3619
SCIP_Real SCIProwGetMaxval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6671
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6924
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3802
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6254
SCIP_Real SCIPcolCalcRedcost(SCIP_COL *col, SCIP_Real *dualsol)
Definition: lp.c:3847
#define lpCutoffDisabled(set, prob)
Definition: lp.c:2646
SCIP_RETCODE SCIPlpGetBInvRow(SCIP_LP *lp, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9850
static SCIP_RETCODE lpSetRefactorInterval(SCIP_LP *lp, int refactor, SCIP_Bool *success)
Definition: lp.c:3252
SCIP_Real SCIProwGetNLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6336
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3377
static SCIP_RETCODE lpSolveStable(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LPALGO lpalgo, int itlim, int harditlim, SCIP_Bool resolve, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, int scaling, SCIP_Bool keepsol, SCIP_Bool *timelimit, SCIP_Bool *lperror)
Definition: lp.c:11579
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:13372
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5339
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10100
SCIP_Real SCIProwGetPseudoFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6450
SCIP_RETCODE SCIPlpUpdateAges(SCIP_LP *lp, SCIP_STAT *stat)
Definition: lp.c:15242
SCIP_RETCODE SCIPlpGetBInvCol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9872
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3757
#define DIVESTACKGROWFACT
Definition: lp.c:16288
static SCIP_RETCODE lpSetTiming(SCIP_LP *lp, SCIP_CLOCKTYPE timing, SCIP_Bool enabled, SCIP_Bool *success)
Definition: lp.c:3165
SCIP_RETCODE SCIPlpInterrupt(SCIP_LP *lp, SCIP_Bool interrupt)
Definition: lp.c:10117
static SCIP_RETCODE lpLexDualSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:10670
static void rowDelNorms(SCIP_ROW *row, SCIP_SET *set, SCIP_COL *col, SCIP_Real val, SCIP_Bool forcenormupdate, SCIP_Bool updateindex, SCIP_Bool updateval)
Definition: lp.c:1985
SCIP_RETCODE SCIProwChgCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val)
Definition: lp.c:5476
static SCIP_RETCODE lpSetFromscratch(SCIP_LP *lp, SCIP_Bool fromscratch, SCIP_Bool *success)
Definition: lp.c:2835
static void colSortNonLP(SCIP_COL *col)
Definition: lp.c:1002
static SCIP_RETCODE ensureLpicolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:214
SCIP_Real SCIPcolCalcFarkasCoef(SCIP_COL *col, SCIP_Real *dualfarkas)
Definition: lp.c:4030
static void rowMoveCoef(SCIP_ROW *row, int oldpos, int newpos)
Definition: lp.c:1364
static SCIP_RETCODE lpSetFastmip(SCIP_LP *lp, int fastmip, SCIP_Bool *success)
Definition: lp.c:2860
SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:10133
static SCIP_RETCODE lpSetRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value, SCIP_Bool *success)
Definition: lp.c:2553
static SCIP_RETCODE lpCopyIntegrality(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8623
static SCIP_RETCODE lpStoreSolVals(SCIP_LP *lp, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: lp.c:376
void SCIPlpMarkSize(SCIP_LP *lp)
Definition: lp.c:9790
int SCIProwGetNumIntCols(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6735
static SCIP_RETCODE lpSetLPInfo(SCIP_LP *lp, SCIP_Bool lpinfo)
Definition: lp.c:3092
SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10033
void SCIPlpRecalculateObjSqrNorm(SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:17676
static void lpUpdateObjNorms(SCIP_LP *lp, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:3662
static SCIP_RETCODE lpRemoveObsoleteRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int firstrow)
Definition: lp.c:15575
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition: lp.c:17643
SCIP_Real SCIProwGetSolFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6508
void SCIProwRecalcPseudoActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6395
SCIP_RETCODE SCIProwEnsureSize(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:629
SCIP_Bool SCIPlpIsFeasPositive(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18915
SCIP_Bool SCIPlpIsFeasGT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18864
SCIP_RETCODE SCIPlpIsInfeasibilityProved(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool *proved)
Definition: lp.c:16505
SCIP_Real SCIProwGetRelaxFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6274
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition: lp.c:9450
#define MAXNUMTROUBLELPMSGS
Definition: lp.c:11488
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13158
SCIP_RETCODE SCIPlpSetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, SCIP_LPISTATE *lpistate, SCIP_Bool wasprimfeas, SCIP_Bool wasprimchecked, SCIP_Bool wasdualfeas, SCIP_Bool wasdualchecked)
Definition: lp.c:10057
static SCIP_RETCODE colDelCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos)
Definition: lp.c:1819
static void colSwapCoefs(SCIP_COL *col, int pos1, int pos2)
Definition: lp.c:1304
static void rowCalcActivityBounds(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6526
static SCIP_RETCODE lpUpdateVarProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real oldlb, SCIP_Real oldub, SCIP_Real newobj, SCIP_Real newlb, SCIP_Real newub)
Definition: lp.c:13725
SCIP_Real SCIPlpGetObjNorm(SCIP_LP *lp)
Definition: lp.c:17707
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6619
SCIP_RETCODE SCIProwMakeIntegral(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Bool *success)
Definition: lp.c:5981
static SCIP_RETCODE lpSetPresolving(SCIP_LP *lp, SCIP_Bool presolving, SCIP_Bool *success)
Definition: lp.c:2941
SCIP_RETCODE SCIPlpRemoveNewObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15651
SCIP_Bool SCIProwIsLPEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool root)
Definition: lp.c:6849
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6865
static int colSearchCoefPart(SCIP_COL *col, const SCIP_ROW *row, int minpos, int maxpos)
Definition: lp.c:1101
SCIP_RETCODE SCIPlpStartStrongbranch(SCIP_LP *lp)
Definition: lp.c:4180
static int rowSearchCoefPart(SCIP_ROW *row, const SCIP_COL *col, int minpos, int maxpos)
Definition: lp.c:1176
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17857
#define checkRowSumnorm(row)
Definition: lp.c:769
static int colSearchCoef(SCIP_COL *col, const SCIP_ROW *row)
Definition: lp.c:1137
SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8671
static SCIP_RETCODE rowDelCoefPos(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos)
Definition: lp.c:2184
SCIP_RETCODE SCIPlpUpdateVarLb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:13919
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14330
static void rowSwapCoefs(SCIP_ROW *row, int pos1, int pos2)
Definition: lp.c:1401
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition: lp.c:5640
static SCIP_RETCODE rowChgCoefPos(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos, SCIP_Real val)
Definition: lp.c:2244
static SCIP_RETCODE rowEventCoefChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1466
static void recomputePseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:821
void SCIPlpSetFeastol(SCIP_LP *lp, SCIP_SET *set, SCIP_Real newfeastol)
Definition: lp.c:10256
SCIP_RETCODE SCIPcolChgCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: lp.c:3513
SCIP_RETCODE rowUnlink(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:2475
SCIP_RETCODE SCIPlpWrite(SCIP_LP *lp, const char *fname)
Definition: lp.c:16527
int SCIProwGetMaxidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6703
static void colSortLP(SCIP_COL *col)
Definition: lp.c:969
static void adjustLPobjval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr)
Definition: lp.c:11995
static SCIP_RETCODE lpFlushAddRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8228
SCIP_Real SCIPlpGetModifiedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:13332
static int rowSearchCoef(SCIP_ROW *row, const SCIP_COL *col)
Definition: lp.c:1215
SCIP_Real SCIProwGetLPActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6224
void SCIProwMarkNotRemovableLocal(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:7878
static SCIP_RETCODE lpSetPricing(SCIP_LP *lp, SCIP_PRICING pricing)
Definition: lp.c:3027
SCIP_RETCODE SCIPlpUpdateVarLbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:13892
static SCIP_RETCODE colRestoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer)
Definition: lp.c:497
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13103
SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
Definition: lp.c:9633
void SCIPlpStoreRootObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13178
static SCIP_RETCODE lpSetPricingChar(SCIP_LP *lp, char pricingchar)
Definition: lp.c:3050
SCIP_RETCODE SCIProwCreate(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, int len, SCIP_COL **cols, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_ROWORIGINTYPE origintype, void *origin, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: lp.c:5110
static SCIP_RETCODE colStoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem)
Definition: lp.c:470
static SCIP_RETCODE rowAddCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val, int linkpos)
Definition: lp.c:2043
SCIP_ROW ** SCIPlpGetNewrows(SCIP_LP *lp)
Definition: lp.c:17654
static SCIP_RETCODE ensureSoldirectionSize(SCIP_LP *lp, int num)
Definition: lp.c:283
void SCIPlpRecomputeLocalAndGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13202
static SCIP_RETCODE lpSetMarkowitz(SCIP_LP *lp, SCIP_Real threshhold, SCIP_Bool *success)
Definition: lp.c:3140
static void rowUpdateAddLP(SCIP_ROW *row)
Definition: lp.c:8902
static SCIP_RETCODE lpCheckIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value)
Definition: lp.c:2581
SCIP_Real SCIPlpGetColumnObjval(SCIP_LP *lp)
Definition: lp.c:13147
SCIP_RETCODE SCIPlpUpdateAddVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14028
SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9771
SCIP_Bool SCIPlpIsPrimalReliable(SCIP_LP *lp)
Definition: lp.c:17817
static SCIP_RETCODE colEnsureSize(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:349
static void rowSortNonLP(SCIP_ROW *row)
Definition: lp.c:1066
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:17784
static SCIP_RETCODE ensureChgcolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:168
SCIP_RETCODE SCIProwDelCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col)
Definition: lp.c:5430
SCIP_RETCODE SCIPlpGetBase(SCIP_LP *lp, int *cstat, int *rstat)
Definition: lp.c:9833
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:17797
#define FEASTOLTIGHTFAC
Definition: lp.c:11576
static SCIP_RETCODE rowEventConstantChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1496
void SCIPcolInvalidateStrongbranchData(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4264
static SCIP_RETCODE lpSolve(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LPALGO lpalgo, int resolveitlim, int harditlim, SCIP_Bool needprimalray, SCIP_Bool needdualray, SCIP_Bool resolve, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, int scaling, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12026
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition: lp.c:12393
SCIP_RETCODE SCIPcolGetStrongbranch(SCIP_COL *col, SCIP_Bool integral, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp, int itlim, SCIP_Bool updatecol, SCIP_Bool updatestat, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *lperror)
Definition: lp.c:4299
static SCIP_RETCODE lpCheckRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value)
Definition: lp.c:2617
SCIP_RETCODE SCIPcolDelCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row)
Definition: lp.c:3468
static void rowMerge(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6049
static void colMoveCoef(SCIP_COL *col, int oldpos, int newpos)
Definition: lp.c:1268
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Real *intval)
Definition: lp.c:4900
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13119
static void computeLPBounds(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, SCIP_Real lpiinf, SCIP_Real *lb, SCIP_Real *ub)
Definition: lp.c:7970
SCIP_RETCODE SCIPlpCleanupAll(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_Bool root)
Definition: lp.c:15890
void SCIProwRecalcLPActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6172
static SCIP_Bool isNewValueUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: lp.c:3644
static SCIP_RETCODE provedBound(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool usefarkas, SCIP_Real *bound)
Definition: lp.c:16381
SCIP_Real SCIProwGetMinval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6687
SCIP_RETCODE SCIPlpEndStrongbranch(SCIP_LP *lp)
Definition: lp.c:4195
SCIP_Longint SCIPcolGetStrongbranchLPAge(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4739
static SCIP_RETCODE lpDelColset(SCIP_LP *lp, SCIP_SET *set, int *coldstat)
Definition: lp.c:15302
static SCIP_RETCODE lpRemoveObsoleteCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15499
SCIP_Real SCIPlpGetRootObjval(SCIP_LP *lp)
Definition: lp.c:17740
static SCIP_RETCODE rowScale(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real scaleval, SCIP_Bool integralcontvars, SCIP_Real minrounddelta, SCIP_Real maxrounddelta)
Definition: lp.c:4940
static SCIP_RETCODE ensureLazycolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:303
SCIP_Bool SCIPlpIsFeasGE(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18884
static SCIP_RETCODE ignoreInstability(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_LPALGO lpalgo, SCIP_Bool *success)
Definition: lp.c:11550
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:16491
static void checkLazyColArray(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:9580
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3698
static void colUpdateAddLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8862
SCIP_Real SCIProwGetLPSolCutoffDistance(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_LP *lp)
Definition: lp.c:6751
static SCIP_RETCODE lpSetRandomseed(SCIP_LP *lp, int randomseed, SCIP_Bool *success)
Definition: lp.c:3199
static SCIP_RETCODE rowRestoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer, SCIP_Bool infeasible)
Definition: lp.c:581
static SCIP_RETCODE ensureChgrowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:191
SCIP_Real SCIProwGetSolActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6466
static SCIP_RETCODE lpSetScaling(SCIP_LP *lp, int scaling, SCIP_Bool *success)
Definition: lp.c:2891
static SCIP_RETCODE colChgCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos, SCIP_Real val)
Definition: lp.c:1864
SCIP_RETCODE SCIPlpFree(SCIP_LP **lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9370
static SCIP_RETCODE lpSetIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value, SCIP_Bool *success)
Definition: lp.c:2514
void SCIPlpMarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17867
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition: lp.c:17632
SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:10177
static SCIP_RETCODE lpBarrier(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool crossover, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:11268
SCIP_RETCODE SCIProwAddCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real val)
Definition: lp.c:5409
static void freeDiveChgSideArrays(SCIP_LP *lp)
Definition: lp.c:9058
SCIP_RETCODE SCIPlpGetBInvARow(SCIP_LP *lp, int r, SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9898
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:17774
SCIP_Bool SCIPlpIsFeasLT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18824
static SCIP_RETCODE rowStoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Bool infeasible)
Definition: lp.c:544
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition: lp.c:5528
static SCIP_RETCODE lpUpdateVarColumnProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14120
#define debugRowPrint(x, y)
Definition: lp.c:126
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15929
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17847
static void rowUpdateDelLP(SCIP_ROW *row)
Definition: lp.c:8976
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17878
SCIP_RETCODE SCIPlpGetBasisInd(SCIP_LP *lp, int *basisind)
Definition: lp.c:9816
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6964
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lp.c:10157
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5730
SCIP_RETCODE SCIPlpComputeRelIntPoint(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_LP *lp, SCIP_PROB *prob, SCIP_Bool relaxrows, SCIP_Bool inclobjcutoff, SCIP_Real timelimit, int iterlimit, SCIP_Real *point, SCIP_Bool *success)
Definition: lp.c:18603
#define DIVESTACKINITSIZE
Definition: lp.c:9075
SCIP_RETCODE SCIPlpGetDualDegeneracy(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *degeneracy, SCIP_Real *varconsratio)
Definition: lp.c:18675
static SCIP_RETCODE lpSetBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value, SCIP_Bool *success)
Definition: lp.c:2541
static SCIP_RETCODE ensureColsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:260
static void rowCalcNorms(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4771
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6808
SCIP_RETCODE SCIPlpGetSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lp.c:14348
static void markRowDeleted(SCIP_ROW *row)
Definition: lp.c:8163
static void rowAddNorms(SCIP_ROW *row, SCIP_SET *set, SCIP_COL *col, SCIP_Real val, SCIP_Bool updateidxvals)
Definition: lp.c:1908
static void lpUpdateObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real deltaval, int deltainf, SCIP_Bool local, SCIP_Bool loose, SCIP_Bool global)
Definition: lp.c:13643
static const int nscalars
Definition: lp.c:5744
void SCIPcolGetStrongbranchLast(SCIP_COL *col, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Real *solval, SCIP_Real *lpobjval)
Definition: lp.c:4707
SCIP_RETCODE SCIPcolAddCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: lp.c:3447
static SCIP_RETCODE computeRelIntPoint(SCIP_LPI *lpi, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_LP *lp, SCIP_PROB *prob, SCIP_Bool relaxrows, SCIP_Bool inclobjcutoff, SCIP_Real timelimit, int iterlimit, SCIP_Real *point, SCIP_Bool *success)
Definition: lp.c:17901
SCIP_RETCODE SCIPcolIncCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real incval)
Definition: lp.c:3564
SCIP_Real SCIPlpGetRootLooseObjval(SCIP_LP *lp)
Definition: lp.c:17764
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:5299
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:10201
SCIP_RETCODE SCIPlpRecordOldRowSideDive(SCIP_LP *lp, SCIP_ROW *row, SCIP_SIDETYPE sidetype)
Definition: lp.c:16291
static SCIP_RETCODE lpCleanupCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15713
SCIP_RETCODE SCIPlpMarkFlushed(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8734
static SCIP_RETCODE lpAlgorithm(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_LPALGO lpalgo, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool instable, SCIP_Bool *timelimit, SCIP_Bool *lperror)
Definition: lp.c:11405
SCIP_Real SCIPcolGetFeasibility(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3976
#define checkRowSqrnorm(row)
Definition: lp.c:768
SCIP_RETCODE SCIPlpShrinkRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int newnrows)
Definition: lp.c:9705
SCIP_Bool SCIProwIsRedundant(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6640
void SCIPlpStartStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16345
static SCIP_RETCODE lpFlushDelCols(SCIP_LP *lp)
Definition: lp.c:7919
static SCIP_RETCODE lpSetRowrepswitch(SCIP_LP *lp, SCIP_Real rowrepswitch, SCIP_Bool *success)
Definition: lp.c:2966
SCIP_RETCODE SCIPlpGetIterations(SCIP_LP *lp, int *iterations)
Definition: lp.c:15227
static void recomputeLooseObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:779
static void colUpdateDelLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8937
SCIP_RETCODE SCIProwChgConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real constant)
Definition: lp.c:5585
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition: lp.c:16315
SCIP_Real SCIPlpGetFeastol(SCIP_LP *lp)
Definition: lp.c:10246
static SCIP_RETCODE lpSetFeastol(SCIP_LP *lp, SCIP_Real feastol, SCIP_Bool *success)
Definition: lp.c:2705
SCIP_Bool SCIProwIsSolEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Bool root)
Definition: lp.c:6908
static SCIP_RETCODE lpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14073
SCIP_RETCODE SCIPlpUpdateDelVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14049
void SCIPlpEndStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16358
SCIP_RETCODE SCIPlpGetBInvACol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9923
SCIP_Bool SCIPlpIsFeasZero(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18904
static SCIP_RETCODE lpSetThreads(SCIP_LP *lp, int threads, SCIP_Bool *success)
Definition: lp.c:2916
SCIP_RETCODE SCIPlpRemoveAllObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15682
static SCIP_RETCODE lpFlushChgCols(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8376
static SCIP_RETCODE lpUpdateVarLooseProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14252
SCIP_RETCODE SCIProwCatchEvent(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: lp.c:7833
SCIP_RETCODE colLink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2352
SCIP_RETCODE SCIProwFree(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5259
static SCIP_Real getFiniteLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:905
SCIP_Real SCIPcolGetFarkasValue(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4161
static SCIP_RETCODE lpDualSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool instable, SCIP_Bool *lperror)
Definition: lp.c:10479
static const char * lpalgoName(SCIP_LPALGO lpalgo)
Definition: lp.c:10298
static void coefChanged(SCIP_ROW *row, SCIP_COL *col, SCIP_LP *lp)
Definition: lp.c:1633
static SCIP_RETCODE lpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14207
static void getObjvalDeltaUb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldub, SCIP_Real newub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13602
static SCIP_RETCODE lpRestoreSolVals(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_Longint validlp)
Definition: lp.c:410
static SCIP_RETCODE rowSideChanged(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp, SCIP_SIDETYPE sidetype)
Definition: lp.c:2300
static void rowSortLP(SCIP_ROW *row)
Definition: lp.c:1033
static SCIP_Real colCalcInternalFarkasCoef(SCIP_COL *col)
Definition: lp.c:4082
SCIP_RETCODE colUnlink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2395
SCIP_RETCODE SCIPlpCreate(SCIP_LP **lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *name)
Definition: lp.c:9078
SCIP_Bool SCIPlpDivingRowsChanged(SCIP_LP *lp)
Definition: lp.c:17889
SCIP_RETCODE SCIPlpUpdateVarUbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13960
static SCIP_RETCODE lpFlushAndSolve(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, int resolveitlim, int harditlim, SCIP_Bool needprimalray, SCIP_Bool needdualray, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, int scaling, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12214
SCIP_RETCODE SCIPlpReset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9415
static SCIP_RETCODE lpCheckBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value)
Definition: lp.c:2606
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3952
SCIP_RETCODE SCIPlpEndProbing(SCIP_LP *lp)
Definition: lp.c:16330
SCIP_RETCODE SCIProwDropEvent(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: lp.c:7857
static SCIP_RETCODE colAddCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val, int linkpos)
Definition: lp.c:1698
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3279
SCIP_Bool SCIPlpIsRootLPRelax(SCIP_LP *lp)
Definition: lp.c:17730
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:17807
SCIP_RETCODE SCIPlpUpdateVarUb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13987
static SCIP_RETCODE lpSetConditionLimit(SCIP_LP *lp, SCIP_Real condlimit, SCIP_Bool *success)
Definition: lp.c:3115
SCIP_RETCODE SCIPlpUpdateVarObj(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:13838
static void lpNumericalTroubleMessage(SCIP_MESSAGEHDLR *messagehdlr, SCIP_SET *set, SCIP_STAT *stat, SCIP_VERBLEVEL verblevel, const char *formatstr,...)
Definition: lp.c:11497
SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4135
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14309
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13270
static SCIP_RETCODE reallocDiveChgSideArrays(SCIP_LP *lp, int minsize, SCIP_Real growfact)
Definition: lp.c:9032
SCIP_Bool SCIPlpIsDualReliable(SCIP_LP *lp)
Definition: lp.c:17827
SCIP_RETCODE SCIPlpAddRow(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_ROW *row, int depth)
Definition: lp.c:9509
SCIP_RETCODE SCIPlpWriteMip(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *fname, SCIP_Bool genericnames, SCIP_Bool origobj, SCIP_OBJSENSE objsense, SCIP_Real objscale, SCIP_Real objoffset, SCIP_Bool lazyconss)
Definition: lp.c:16542
static void getObjvalDeltaLb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13561
int SCIProwGetMinidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6719
static SCIP_Real colCalcInternalRedcost(SCIP_COL *col)
Definition: lp.c:3899
SCIP_RETCODE SCIPlpStartDive(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:16003
SCIP_Bool SCIPlpIsFeasNegative(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18926
SCIP_RETCODE SCIPlpEndDive(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_VAR **vars, int nvars)
Definition: lp.c:16109
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:17565
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17575
static SCIP_RETCODE lpSetBarrierconvtol(SCIP_LP *lp, SCIP_Real barrierconvtol, SCIP_Bool *success)
Definition: lp.c:2791
SCIP_RETCODE SCIProwChgRhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real rhs)
Definition: lp.c:5698
SCIP_Real SCIPlpGetRootColumnObjval(SCIP_LP *lp)
Definition: lp.c:17752
static SCIP_RETCODE rowEventSideChanged(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition: lp.c:1524
SCIP_RETCODE SCIPlpGetUnboundedSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *rayfeasible)
Definition: lp.c:14665
static SCIP_RETCODE lpSetDualfeastol(SCIP_LP *lp, SCIP_Real dualfeastol, SCIP_Bool *success)
Definition: lp.c:2748
SCIP_RETCODE SCIPlpGetDualfarkas(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *valid)
Definition: lp.c:15052
SCIP_RETCODE SCIProwCalcIntegralScalar(SCIP_ROW *row, SCIP_SET *set, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: lp.c:5747
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition: lp.c:10191
SCIP_Bool SCIPlpIsFeasEQ(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18804
static void markColDeleted(SCIP_COL *col)
Definition: lp.c:7897
SCIP_Real SCIProwGetPseudoActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6422
static void checkLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12304
static SCIP_RETCODE lpSetIterationLimit(SCIP_LP *lp, int itlim)
Definition: lp.c:2991
static SCIP_RETCODE ensureRowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:326
static SCIP_Real getFinitePseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:927
static SCIP_RETCODE allocDiveChgSideArrays(SCIP_LP *lp, int initsize)
Definition: lp.c:9010
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:17612
void SCIPlpSetRootLPIsRelax(SCIP_LP *lp, SCIP_Bool isrelax)
Definition: lp.c:17719
static SCIP_RETCODE ensureLpirowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:237
SCIP_RETCODE SCIProwChgLhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real lhs)
Definition: lp.c:5666
void SCIProwForceSort(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6159
void SCIPcolMarkNotRemovableLocal(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4751
static SCIP_RETCODE updateLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12331
SCIP_RETCODE rowLink(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2433
int SCIPlpGetNUnfixedCols(SCIP_LP *lp, SCIP_Real eps)
Definition: lp.c:17585
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6598
#define checkRowObjprod(row)
Definition: lp.c:770
SCIP_RETCODE SCIPlpSolveAndEval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_Longint itlim, SCIP_Bool limitresolveiters, SCIP_Bool aging, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12413
static const SCIP_Real scalars[]
Definition: lp.c:5743
void SCIPcolSetStrongbranchData(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Real lpobjval, SCIP_Real primsol, SCIP_Real sbdown, SCIP_Real sbup, SCIP_Bool sbdownvalid, SCIP_Bool sbupvalid, SCIP_Longint iter, int itlim)
Definition: lp.c:4210
SCIP_Bool SCIPlpIsFeasLE(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18844
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition: lp.c:17665
void SCIPlpResetFeastol(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:10281
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14991
#define checkRow(row)
Definition: lp.c:695
void SCIProwDelaySort(SCIP_ROW *row)
Definition: lp.c:6148
static SCIP_RETCODE lpSetSolutionPolishing(SCIP_LP *lp, SCIP_Bool polishing, SCIP_Bool *success)
Definition: lp.c:3229
void SCIPlpInvalidateRootObjval(SCIP_LP *lp)
Definition: lp.c:13191
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17622
static SCIP_RETCODE lpFlushChgRows(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8524
static SCIP_RETCODE lpPrimalSimplex(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool resolve, SCIP_Bool keepsol, SCIP_Bool instable, SCIP_Bool *lperror)
Definition: lp.c:10321
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7800
static void recomputeGlbPseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:863
SCIP_RETCODE SCIPlpSumRows(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real *weights, SCIP_REALARRAY *sumcoef, SCIP_Real *sumlhs, SCIP_Real *sumrhs)
Definition: lp.c:9947
SCIP_RETCODE SCIPcolGetStrongbranches(SCIP_COL **cols, int ncols, SCIP_Bool integral, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, SCIP_Bool *lperror)
Definition: lp.c:4484
static SCIP_RETCODE lpCleanupRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int firstrow)
Definition: lp.c:15780
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13302
static SCIP_RETCODE lpDelRowset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int *rowdstat)
Definition: lp.c:15401
void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
Definition: lp.c:9802
static int SCIProwGetDiscreteScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7365
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14185
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5352
#define checkLinks(lp)
Definition: lp.c:1624
static SCIP_RETCODE lpFlushAddCols(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8005
void SCIPcolPrint(SCIP_COL *col, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:3407
internal methods for LP management
interface methods for specific LP solvers
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:462
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:465
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:451
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:127
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:468
#define BMSfreeMemoryNull(ptr)
Definition: memory.h:146
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:454
#define BMSfreeBlockMemoryNull(mem, ptr)
Definition: memory.h:466
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:467
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:458
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:437
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:148
#define BMSallocMemory(ptr)
Definition: memory.h:118
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPmessageVFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr, va_list ap)
Definition: message.c:633
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:594
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:427
void SCIPmessagePrintVerbInfo(SCIP_MESSAGEHDLR *messagehdlr, SCIP_VERBLEVEL verblevel, SCIP_VERBLEVEL msgverblevel, const char *formatstr,...)
Definition: message.c:678
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4088
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4364
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4243
internal miscellaneous methods
real eps
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2350
internal methods for storing and manipulating the main problem
public methods for LP management
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
methods for sorting joint arrays of various types
public methods for problem variables
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6918
SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
Definition: set.c:7061
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6718
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6293
SCIP_RETCODE SCIPsetGetCharParam(SCIP_SET *set, const char *name, char *value)
Definition: set.c:3179
SCIP_Real SCIPsetSumFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6553
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6729
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:6106
SCIP_Bool SCIPsetIsDualfeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6830
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6663
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6641
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6597
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6322
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6257
SCIP_Real SCIPsetRelaxfeastol(SCIP_SET *set)
Definition: set.c:6178
SCIP_Bool SCIPsetIsSumLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6466
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6940
SCIP_Real SCIPsetDualfeastol(SCIP_SET *set)
Definition: set.c:6116
SCIP_Bool SCIPsetIsSumGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6502
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6221
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6707
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6619
SCIP_RETCODE SCIPsetSetCharParam(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *name, char value)
Definition: set.c:3424
SCIP_Real SCIPsetLPFeastolFactor(SCIP_SET *set)
Definition: set.c:6126
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:6064
SCIP_Real SCIPsetSumepsilon(SCIP_SET *set)
Definition: set.c:6096
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6239
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6199
SCIP_Bool SCIPsetIsSumZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6520
SCIP_Bool SCIPsetIsRelGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:7164
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6929
SCIP_Bool SCIPsetIsDualfeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6874
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6275
SCIP_Bool SCIPsetIsSumEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6430
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6344
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6311
SCIP_Bool SCIPsetIsUpdateUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: set.c:7316
SCIP_Real SCIPsetSumCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6564
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6685
SCIP_Real SCIPsetBarrierconvtol(SCIP_SET *set)
Definition: set.c:6134
SCIP_Real SCIPsetRound(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6408
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5764
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6740
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6333
unsigned int SCIPsetInitializeRandomSeed(SCIP_SET *set, unsigned int initialseedvalue)
Definition: set.c:7393
internal methods for global SCIP settings
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1755
#define SCIPsetDebugMsgPrint
Definition: set.h:1785
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1748
#define SCIPsetDebugMsg
Definition: set.h:1784
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1372
internal methods for storing primal CIP solutions
SCIP_Bool SCIPsolveIsStopped(SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool checknodelimits)
Definition: solve.c:102
internal methods for main solving loop and node processing
internal methods for problem statistics
#define SCIPstatAdd(stat, set, field, val)
Definition: stat.h:280
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:260
#define SCIPstatUpdate(stat, set, field, val)
Definition: stat.h:239
SCIP_Real primsol
Definition: struct_lp.h:95
unsigned int basisstatus
Definition: struct_lp.h:97
SCIP_Real redcost
Definition: struct_lp.h:96
SCIP_Real lb
Definition: struct_lp.h:138
SCIP_Real maxprimsol
Definition: struct_lp.h:152
SCIP_Real ub
Definition: struct_lp.h:139
unsigned int lbchanged
Definition: struct_lp.h:183
SCIP_ROW ** rows
Definition: struct_lp.h:161
unsigned int objchanged
Definition: struct_lp.h:182
int lpdepth
Definition: struct_lp.h:174
int nlprows
Definition: struct_lp.h:170
SCIP_Real sbsolval
Definition: struct_lp.h:155
SCIP_Real sbdown
Definition: struct_lp.h:153
SCIP_Real sbup
Definition: struct_lp.h:154
SCIP_Real lazylb
Definition: struct_lp.h:141
SCIP_COLSOLVALS * storedsolvals
Definition: struct_lp.h:159
unsigned int basisstatus
Definition: struct_lp.h:179
SCIP_Real redcost
Definition: struct_lp.h:149
SCIP_Real lazyub
Definition: struct_lp.h:143
SCIP_Real minprimsol
Definition: struct_lp.h:151
SCIP_Real sblpobjval
Definition: struct_lp.h:156
SCIP_Real flushedobj
Definition: struct_lp.h:145
int len
Definition: struct_lp.h:169
unsigned int coefchanged
Definition: struct_lp.h:185
SCIP_Real flushedlb
Definition: struct_lp.h:146
unsigned int removable
Definition: struct_lp.h:187
SCIP_Real farkascoef
Definition: struct_lp.h:150
unsigned int sbupvalid
Definition: struct_lp.h:190
SCIP_Longint obsoletenode
Definition: struct_lp.h:158
unsigned int lprowssorted
Definition: struct_lp.h:180
SCIP_Longint validredcostlp
Definition: struct_lp.h:163
int lppos
Definition: struct_lp.h:172
int age
Definition: struct_lp.h:177
SCIP_Real flushedub
Definition: struct_lp.h:147
unsigned int nonlprowssorted
Definition: struct_lp.h:181
int nsbcalls
Definition: struct_lp.h:176
int * linkpos
Definition: struct_lp.h:166
SCIP_Real * vals
Definition: struct_lp.h:162
unsigned int ubchanged
Definition: struct_lp.h:184
SCIP_Real primsol
Definition: struct_lp.h:148
SCIP_Longint validfarkaslp
Definition: struct_lp.h:164
int nunlinked
Definition: struct_lp.h:171
int lpipos
Definition: struct_lp.h:173
unsigned int integral
Definition: struct_lp.h:186
SCIP_Longint validsblp
Definition: struct_lp.h:165
int size
Definition: struct_lp.h:168
int sbitlim
Definition: struct_lp.h:175
SCIP_Longint sbnode
Definition: struct_lp.h:157
SCIP_Real obj
Definition: struct_lp.h:137
int index
Definition: struct_lp.h:167
unsigned int sbdownvalid
Definition: struct_lp.h:188
SCIP_Real unchangedobj
Definition: struct_lp.h:140
SCIP_VAR * var
Definition: struct_lp.h:160
int var_probindex
Definition: struct_lp.h:178
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:198
SCIP_Bool dualchecked
Definition: struct_lp.h:123
SCIP_Bool solisbasic
Definition: struct_lp.h:124
SCIP_Bool dualfeasible
Definition: struct_lp.h:122
SCIP_Bool primalfeasible
Definition: struct_lp.h:120
SCIP_Bool primalchecked
Definition: struct_lp.h:121
SCIP_Real lpobjval
Definition: struct_lp.h:119
SCIP_Bool lpissolved
Definition: struct_lp.h:125
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:118
SCIP_Bool glbpseudoobjvalid
Definition: struct_lp.h:359
SCIP_Real * divechgsides
Definition: struct_lp.h:306
SCIP_ROW ** rows
Definition: struct_lp.h:303
SCIP_Real feastol
Definition: struct_lp.h:285
SCIP_Real lpirowrepswitch
Definition: struct_lp.h:397
SCIP_Real objsumnorm
Definition: struct_lp.h:293
SCIP_Longint validsoldirlp
Definition: struct_lp.h:313
SCIP_Real pseudoobjval
Definition: struct_lp.h:279
SCIP_Real relglbpseudoobjval
Definition: struct_lp.h:278
int glbpseudoobjvalinf
Definition: struct_lp.h:339
SCIP_Real objsqrnorm
Definition: struct_lp.h:292
SCIP_Bool flushaddedcols
Definition: struct_lp.h:362
SCIP_ROW ** lpirows
Definition: struct_lp.h:298
SCIP_SIDETYPE * divechgsidetypes
Definition: struct_lp.h:307
int lpicolssize
Definition: struct_lp.h:316
int lpiitlim
Definition: struct_lp.h:345
SCIP_Bool strongbranching
Definition: struct_lp.h:377
SCIP_Bool probing
Definition: struct_lp.h:378
SCIP_Real rellooseobjval
Definition: struct_lp.h:274
SCIP_Bool updateintegrality
Definition: struct_lp.h:365
SCIP_Bool isrelax
Definition: struct_lp.h:374
SCIP_Bool lpipresolving
Definition: struct_lp.h:386
int lpirefactorinterval
Definition: struct_lp.h:351
SCIP_Real varconsratio
Definition: struct_lp.h:295
int lpifirstchgrow
Definition: struct_lp.h:321
SCIP_Bool lpifromscratch
Definition: struct_lp.h:385
SCIP_Bool objsqrnormunreliable
Definition: struct_lp.h:355
SCIP_Bool primalfeasible
Definition: struct_lp.h:368
SCIP_Real lpiconditionlimit
Definition: struct_lp.h:290
SCIP_COL ** cols
Definition: struct_lp.h:301
SCIP_LPALGO lastlpalgo
Definition: struct_lp.h:354
int lpifirstchgcol
Definition: struct_lp.h:318
int divinglpiitlim
Definition: struct_lp.h:344
int nlazycols
Definition: struct_lp.h:330
SCIP_Real rootlpobjval
Definition: struct_lp.h:282
SCIP_Real * soldirection
Definition: struct_lp.h:304
int rowssize
Definition: struct_lp.h:333
int ncols
Definition: struct_lp.h:328
SCIP_Real cutoffbound
Definition: struct_lp.h:284
SCIP_Bool strongbranchprobing
Definition: struct_lp.h:379
int nremovablerows
Definition: struct_lp.h:335
SCIP_Real lpidualfeastol
Definition: struct_lp.h:288
SCIP_Bool installing
Definition: struct_lp.h:376
SCIP_Real rootlooseobjval
Definition: struct_lp.h:283
SCIP_Bool dualfeasible
Definition: struct_lp.h:370
int nchgrows
Definition: struct_lp.h:325
int firstnewcol
Definition: struct_lp.h:332
int lpithreads
Definition: struct_lp.h:347
SCIP_Bool solisbasic
Definition: struct_lp.h:372
SCIP_Bool divelpwasdualfeas
Definition: struct_lp.h:401
SCIP_Bool rootlpisrelax
Definition: struct_lp.h:373
SCIP_Bool lpisolutionpolishing
Definition: struct_lp.h:357
SCIP_PRICING lpipricing
Definition: struct_lp.h:352
SCIP_Real looseobjval
Definition: struct_lp.h:272
SCIP_Bool divelpwasprimchecked
Definition: struct_lp.h:400
SCIP_Bool flushaddedrows
Definition: struct_lp.h:364
SCIP_COL ** chgcols
Definition: struct_lp.h:299
int nrows
Definition: struct_lp.h:334
SCIP_Bool primalchecked
Definition: struct_lp.h:369
SCIP_LPSOLVALS * storedsolvals
Definition: struct_lp.h:309
int lpiscaling
Definition: struct_lp.h:350
int lpirandomseed
Definition: struct_lp.h:349
int lpifastmip
Definition: struct_lp.h:346
SCIP_LPISTATE * divelpistate
Definition: struct_lp.h:305
SCIP_Real lpifeastol
Definition: struct_lp.h:287
SCIP_Longint validsollp
Definition: struct_lp.h:311
SCIP_Bool lpihasfastmip
Definition: struct_lp.h:391
SCIP_SOL * validsoldirsol
Definition: struct_lp.h:310
SCIP_Bool divingobjchg
Definition: struct_lp.h:381
int ndivechgsides
Definition: struct_lp.h:342
int lazycolssize
Definition: struct_lp.h:329
SCIP_ROW ** chgrows
Definition: struct_lp.h:300
SCIP_Real lpimarkowitz
Definition: struct_lp.h:291
int firstnewrow
Definition: struct_lp.h:336
int ndivingrows
Definition: struct_lp.h:341
SCIP_Bool lpilpinfo
Definition: struct_lp.h:387
SCIP_Real relpseudoobjval
Definition: struct_lp.h:281
SCIP_LPSOLSTAT lpsolstat
Definition: struct_lp.h:353
int colssize
Definition: struct_lp.h:326
SCIP_Real lpibarrierconvtol
Definition: struct_lp.h:289
SCIP_ROW ** divechgrows
Definition: struct_lp.h:308
int nloosevars
Definition: struct_lp.h:338
int chgrowssize
Definition: struct_lp.h:324
SCIP_Longint validdegeneracylp
Definition: struct_lp.h:314
int nlpicols
Definition: struct_lp.h:317
SCIP_Real lpobjval
Definition: struct_lp.h:271
int nlpirows
Definition: struct_lp.h:320
int chgcolssize
Definition: struct_lp.h:322
SCIP_Longint divenolddomchgs
Definition: struct_lp.h:315
int pseudoobjvalinf
Definition: struct_lp.h:340
SCIP_Bool solved
Definition: struct_lp.h:367
SCIP_Bool divinglazyapplied
Definition: struct_lp.h:382
int lpitiming
Definition: struct_lp.h:348
SCIP_Bool resolvelperror
Definition: struct_lp.h:383
SCIP_Bool dualchecked
Definition: struct_lp.h:371
SCIP_Bool divelpwasdualchecked
Definition: struct_lp.h:402
SCIP_Bool pseudoobjvalid
Definition: struct_lp.h:360
int nchgcols
Definition: struct_lp.h:323
SCIP_Longint validfarkaslp
Definition: struct_lp.h:312
SCIP_Bool looseobjvalid
Definition: struct_lp.h:358
SCIP_Bool adjustlpval
Definition: struct_lp.h:384
SCIP_Bool diving
Definition: struct_lp.h:380
SCIP_Real glbpseudoobjval
Definition: struct_lp.h:276
int divechgsidessize
Definition: struct_lp.h:343
SCIP_Bool lpihaspolishing
Definition: struct_lp.h:395
SCIP_COL ** lpicols
Definition: struct_lp.h:297
int lpirowssize
Definition: struct_lp.h:319
int nremovablecols
Definition: struct_lp.h:331
SCIP_LPI * lpi
Definition: struct_lp.h:296
SCIP_Bool flushdeletedrows
Definition: struct_lp.h:363
int looseobjvalinf
Definition: struct_lp.h:337
int soldirectionsize
Definition: struct_lp.h:327
SCIP_COL ** lazycols
Definition: struct_lp.h:302
SCIP_Real degeneracy
Definition: struct_lp.h:294
SCIP_Bool flushed
Definition: struct_lp.h:366
SCIP_Bool divelpwasprimfeas
Definition: struct_lp.h:399
SCIP_Real lpiobjlim
Definition: struct_lp.h:286
SCIP_Bool flushdeletedcols
Definition: struct_lp.h:361
SCIP_VAR ** vars
Definition: struct_prob.h:64
SCIP_Real activity
Definition: struct_lp.h:108
unsigned int basisstatus
Definition: struct_lp.h:109
SCIP_Real dualsol
Definition: struct_lp.h:107
SCIP_Longint nlpsaftercreation
Definition: struct_lp.h:223
int rank
Definition: struct_lp.h:248
unsigned int basisstatus
Definition: struct_lp.h:250
int nlpcols
Definition: struct_lp.h:236
SCIP_Real minactivity
Definition: struct_lp.h:217
SCIP_Longint activeinlpcounter
Definition: struct_lp.h:222
unsigned int lpcolssorted
Definition: struct_lp.h:251
unsigned int inglobalcutpool
Definition: struct_lp.h:262
SCIP_Real rhs
Definition: struct_lp.h:205
SCIP_Real maxactivity
Definition: struct_lp.h:218
int nunlinked
Definition: struct_lp.h:237
SCIP_Real dualfarkas
Definition: struct_lp.h:215
int lppos
Definition: struct_lp.h:239
SCIP_Longint obsoletenode
Definition: struct_lp.h:221
unsigned int delaysort
Definition: struct_lp.h:253
SCIP_Real flushedrhs
Definition: struct_lp.h:207
int index
Definition: struct_lp.h:233
unsigned int lhschanged
Definition: struct_lp.h:255
int size
Definition: struct_lp.h:234
unsigned int nonlpcolssorted
Definition: struct_lp.h:252
char * name
Definition: struct_lp.h:226
unsigned int origintype
Definition: struct_lp.h:265
SCIP_Real * vals
Definition: struct_lp.h:229
unsigned int validminmaxidx
Definition: struct_lp.h:254
unsigned int removable
Definition: struct_lp.h:261
int numintcols
Definition: struct_lp.h:244
unsigned int local
Definition: struct_lp.h:259
SCIP_Real maxval
Definition: struct_lp.h:211
SCIP_Longint validpsactivitydomchg
Definition: struct_lp.h:219
SCIP_Real flushedlhs
Definition: struct_lp.h:206
int numminval
Definition: struct_lp.h:246
SCIP_Longint validactivitybdsdomchg
Definition: struct_lp.h:220
SCIP_Real lhs
Definition: struct_lp.h:204
int lpipos
Definition: struct_lp.h:240
int maxidx
Definition: struct_lp.h:243
int * linkpos
Definition: struct_lp.h:230
SCIP_Real sqrnorm
Definition: struct_lp.h:208
SCIP_COL ** cols
Definition: struct_lp.h:227
SCIP_Real objprod
Definition: struct_lp.h:210
unsigned int integral
Definition: struct_lp.h:258
int nummaxval
Definition: struct_lp.h:245
void * origin
Definition: struct_lp.h:225
SCIP_Real constant
Definition: struct_lp.h:203
SCIP_ROWSOLVALS * storedsolvals
Definition: struct_lp.h:224
unsigned int coefchanged
Definition: struct_lp.h:257
SCIP_Real activity
Definition: struct_lp.h:214
SCIP_EVENTFILTER * eventfilter
Definition: struct_lp.h:231
SCIP_Real minval
Definition: struct_lp.h:212
SCIP_Real pseudoactivity
Definition: struct_lp.h:216
SCIP_Real sumnorm
Definition: struct_lp.h:209
int * cols_index
Definition: struct_lp.h:228
int minidx
Definition: struct_lp.h:242
unsigned int rhschanged
Definition: struct_lp.h:256
int age
Definition: struct_lp.h:247
SCIP_Real dualsol
Definition: struct_lp.h:213
int lpdepth
Definition: struct_lp.h:241
unsigned int modifiable
Definition: struct_lp.h:260
unsigned int nlocks
Definition: struct_lp.h:264
SCIP_Longint validactivitylp
Definition: struct_lp.h:232
int nuses
Definition: struct_lp.h:238
int len
Definition: struct_lp.h:235
SCIP_STATUS status
Definition: struct_stat.h:186
SCIP_Longint ndualresolvelpiterations
Definition: struct_stat.h:70
SCIP_Longint nprimalresolvelpiterations
Definition: struct_stat.h:69
SCIP_Longint nprimallps
Definition: struct_stat.h:194
SCIP_Longint nnodes
Definition: struct_stat.h:82
SCIP_CLOCK * strongbranchtime
Definition: struct_stat.h:170
SCIP_CLOCK * barrierlptime
Definition: struct_stat.h:167
SCIP_Longint nduallps
Definition: struct_stat.h:196
SCIP_Longint nduallpiterations
Definition: struct_stat.h:66
int nclockskipsleft
Definition: struct_stat.h:275
SCIP_Longint nlps
Definition: struct_stat.h:192
SCIP_Longint ndualresolvelps
Definition: struct_stat.h:202
SCIP_Longint domchgcount
Definition: struct_stat.h:114
SCIP_CLOCK * divinglptime
Definition: struct_stat.h:169
SCIP_Longint lpcount
Definition: struct_stat.h:190
SCIP_Longint nlpiterations
Definition: struct_stat.h:62
SCIP_Longint nprimalresolvelps
Definition: struct_stat.h:201
SCIP_Longint nrootlpiterations
Definition: struct_stat.h:63
SCIP_Longint nnumtroublelpmsgs
Definition: struct_stat.h:210
SCIP_CLOCK * resolveinstablelptime
Definition: struct_stat.h:168
SCIP_CLOCK * duallptime
Definition: struct_stat.h:165
SCIP_Longint ndivinglps
Definition: struct_stat.h:207
int maxdepth
Definition: struct_stat.h:236
SCIP_Longint nrootlps
Definition: struct_stat.h:193
SCIP_CLOCK * primallptime
Definition: struct_stat.h:164
SCIP_Longint nprimallpiterations
Definition: struct_stat.h:65
SCIP_CLOCK * solvingtime
Definition: struct_stat.h:160
SCIP_Longint nbarrierlps
Definition: struct_stat.h:199
SCIP_Bool userinterrupt
Definition: struct_stat.h:278
SCIP_CLOCK * lexduallptime
Definition: struct_stat.h:166
char * name
Definition: struct_var.h:235
SCIP_Real obj
Definition: struct_var.h:209
datastructures for managing events
data structures for LP management
datastructures for storing and manipulating the main problem
datastructures for global SCIP settings
datastructures for problem statistics
datastructures for problem variables
Definition: heur_padm.c:135
enum SCIP_ClockType SCIP_CLOCKTYPE
Definition: type_clock.h:47
@ SCIP_CLOCKTYPE_WALL
Definition: type_clock.h:45
@ SCIP_CLOCKTYPE_CPU
Definition: type_clock.h:44
#define SCIP_EVENTTYPE_ROWSIDECHANGED
Definition: type_event.h:114
#define SCIP_EVENTTYPE_ROWADDEDLP
Definition: type_event.h:110
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:173
#define SCIP_EVENTTYPE_ROWCHANGED
Definition: type_event.h:148
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:152
#define SCIP_EVENTTYPE_ROWDELETEDLP
Definition: type_event.h:111
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:151
#define SCIP_EVENTTYPE_ROWCOEFCHANGED
Definition: type_event.h:112
#define SCIP_EVENTTYPE_ROWCONSTCHANGED
Definition: type_event.h:113
enum SCIP_RowOriginType SCIP_ROWORIGINTYPE
Definition: type_lp.h:78
@ SCIP_LPALGO_BARRIER
Definition: type_lp.h:85
@ SCIP_LPALGO_PRIMALSIMPLEX
Definition: type_lp.h:83
@ SCIP_LPALGO_BARRIERCROSSOVER
Definition: type_lp.h:86
@ SCIP_LPALGO_DUALSIMPLEX
Definition: type_lp.h:84
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:51
@ SCIP_ROWORIGINTYPE_CONSHDLR
Definition: type_lp.h:73
@ SCIP_ROWORIGINTYPE_SEPA
Definition: type_lp.h:75
@ SCIP_ROWORIGINTYPE_CONS
Definition: type_lp.h:74
@ SCIP_BOUNDTYPE_UPPER
Definition: type_lp.h:57
@ SCIP_BOUNDTYPE_LOWER
Definition: type_lp.h:56
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:59
@ SCIP_SIDETYPE_RIGHT
Definition: type_lp.h:65
@ SCIP_SIDETYPE_LEFT
Definition: type_lp.h:64
@ SCIP_LPSOLSTAT_ERROR
Definition: type_lp.h:49
@ SCIP_LPSOLSTAT_NOTSOLVED
Definition: type_lp.h:42
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
@ SCIP_LPSOLSTAT_TIMELIMIT
Definition: type_lp.h:48
@ SCIP_LPSOLSTAT_UNBOUNDEDRAY
Definition: type_lp.h:45
@ SCIP_LPSOLSTAT_INFEASIBLE
Definition: type_lp.h:44
@ SCIP_LPSOLSTAT_OBJLIMIT
Definition: type_lp.h:46
@ SCIP_LPSOLSTAT_ITERLIMIT
Definition: type_lp.h:47
enum SCIP_LPAlgo SCIP_LPALGO
Definition: type_lp.h:88
enum SCIP_SideType SCIP_SIDETYPE
Definition: type_lp.h:67
@ SCIP_PRICING_STEEPQSTART
Definition: type_lpi.h:83
@ SCIP_PRICING_AUTO
Definition: type_lpi.h:79
@ SCIP_PRICING_DEVEX
Definition: type_lpi.h:84
@ SCIP_PRICING_STEEP
Definition: type_lpi.h:82
@ SCIP_PRICING_FULL
Definition: type_lpi.h:80
@ SCIP_PRICING_LPIDEFAULT
Definition: type_lpi.h:78
@ SCIP_PRICING_PARTIAL
Definition: type_lpi.h:81
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:86
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:73
@ SCIP_LPPAR_PRICING
Definition: type_lpi.h:54
@ SCIP_LPPAR_REFACTOR
Definition: type_lpi.h:71
@ SCIP_LPPAR_THREADS
Definition: type_lpi.h:66
@ SCIP_LPPAR_LPINFO
Definition: type_lpi.h:55
@ SCIP_LPPAR_POLISHING
Definition: type_lpi.h:70
@ SCIP_LPPAR_SCALING
Definition: type_lpi.h:52
@ SCIP_LPPAR_TIMING
Definition: type_lpi.h:68
@ SCIP_LPPAR_LPTILIM
Definition: type_lpi.h:61
@ SCIP_LPPAR_BARRIERCONVTOL
Definition: type_lpi.h:58
@ SCIP_LPPAR_PRESOLVING
Definition: type_lpi.h:53
@ SCIP_LPPAR_CONDITIONLIMIT
Definition: type_lpi.h:67
@ SCIP_LPPAR_RANDOMSEED
Definition: type_lpi.h:69
@ SCIP_LPPAR_FASTMIP
Definition: type_lpi.h:51
@ SCIP_LPPAR_DUALFEASTOL
Definition: type_lpi.h:57
@ SCIP_LPPAR_FROMSCRATCH
Definition: type_lpi.h:50
@ SCIP_LPPAR_MARKOWITZ
Definition: type_lpi.h:62
@ SCIP_LPPAR_FEASTOL
Definition: type_lpi.h:56
@ SCIP_LPPAR_LPITLIM
Definition: type_lpi.h:60
@ SCIP_LPPAR_ROWREPSWITCH
Definition: type_lpi.h:63
@ SCIP_LPPAR_OBJLIM
Definition: type_lpi.h:59
@ SCIP_BASESTAT_BASIC
Definition: type_lpi.h:92
@ SCIP_BASESTAT_UPPER
Definition: type_lpi.h:93
@ SCIP_BASESTAT_LOWER
Definition: type_lpi.h:91
@ SCIP_BASESTAT_ZERO
Definition: type_lpi.h:94
@ SCIP_OBJSEN_MAXIMIZE
Definition: type_lpi.h:42
@ SCIP_OBJSEN_MINIMIZE
Definition: type_lpi.h:43
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:96
enum SCIP_VerbLevel SCIP_VERBLEVEL
Definition: type_message.h:59
@ SCIP_VERBLEVEL_NONE
Definition: type_message.h:52
@ SCIP_VERBLEVEL_HIGH
Definition: type_message.h:56
@ SCIP_VERBLEVEL_FULL
Definition: type_message.h:57
@ SCIP_OBJSENSE_MINIMIZE
Definition: type_prob.h:48
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:50
@ SCIP_FILECREATEERROR
Definition: type_retcode.h:48
@ SCIP_LPERROR
Definition: type_retcode.h:49
@ SCIP_INVALIDDATA
Definition: type_retcode.h:52
@ SCIP_PARAMETERUNKNOWN
Definition: type_retcode.h:55
@ SCIP_PARAMETERWRONGVAL
Definition: type_retcode.h:57
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_STATUS_TIMELIMIT
Definition: type_stat.h:51
@ SCIP_VARSTATUS_COLUMN
Definition: type_var.h:51
@ SCIP_VARSTATUS_LOOSE
Definition: type_var.h:50
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13923
internal methods for problem variables