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-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file 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, lp) (set->lp_disablecutoff == 1 || (set->lp_disablecutoff == 2 && !SCIPprobAllColsInLP(prob, set, lp)) || set->misc_exactsolve)
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 /* if the objective limit is disabled or SCIP infinity, make sure that the LP objective limit is deactivated by
2668 * setting it to the LP-solver infinity
2669 */
2670 if( lpCutoffDisabled(set, prob, lp) || SCIPsetIsInfinity(set, objlim) )
2671 objlim = SCIPlpiInfinity(lp->lpi);
2672
2674
2675 if( objlim != lp->lpiobjlim ) /*lint !e777*/
2676 {
2677 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) );
2678 if( *success )
2679 {
2680 SCIP_Real actualobjlim;
2681
2682 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2683 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) );
2684 if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/
2685 {
2686 /* mark the current solution invalid */
2687 lp->solved = FALSE;
2688 lp->primalfeasible = FALSE;
2689 lp->primalchecked = FALSE;
2690 lp->lpobjval = SCIP_INVALID;
2692 }
2693 lp->lpiobjlim = actualobjlim;
2694 }
2695 }
2696
2697 return SCIP_OKAY;
2698}
2699
2700/** sets the feasibility tolerance of the LP solver */
2701static
2703 SCIP_LP* lp, /**< current LP data */
2704 SCIP_Real feastol, /**< new feasibility tolerance */
2705 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2706 )
2707{
2708 assert(lp != NULL);
2709 assert(feastol >= 0.0);
2710 assert(success != NULL);
2711
2713
2714 if( feastol != lp->lpifeastol ) /*lint !e777*/
2715 {
2716 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2717 if( *success )
2718 {
2719 SCIP_Real actualfeastol;
2720
2721 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2722 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) );
2723 if( lp->nrows > 0 && actualfeastol < lp->lpifeastol )
2724 {
2725 /* mark the current solution invalid */
2726 lp->solved = FALSE;
2727 lp->primalfeasible = FALSE;
2728 lp->primalchecked = FALSE;
2729 lp->lpobjval = SCIP_INVALID;
2731 }
2732 else
2733 *success = FALSE;
2734 lp->lpifeastol = actualfeastol;
2735 }
2736 }
2737 else
2738 *success = FALSE;
2739
2740 return SCIP_OKAY;
2741}
2742
2743/** sets the reduced costs feasibility tolerance of the LP solver */
2744static
2746 SCIP_LP* lp, /**< current LP data */
2747 SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2748 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2749 )
2750{
2751 assert(lp != NULL);
2752 assert(dualfeastol >= 0.0);
2753 assert(success != NULL);
2754
2756
2757 if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2758 {
2759 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2760 if( *success )
2761 {
2762 SCIP_Real actualdualfeastol;
2763
2764 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2765 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) );
2766 if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol )
2767 {
2768 /* mark the current solution invalid */
2769 lp->solved = FALSE;
2770 lp->dualfeasible = FALSE;
2771 lp->dualchecked = FALSE;
2772 lp->lpobjval = SCIP_INVALID;
2774 }
2775 else
2776 *success = FALSE;
2777 lp->lpidualfeastol = actualdualfeastol;
2778 }
2779 }
2780 else
2781 *success = FALSE;
2782
2783 return SCIP_OKAY;
2784}
2785
2786/** sets the convergence tolerance used in barrier algorithm of the LP solver */
2787static
2789 SCIP_LP* lp, /**< current LP data */
2790 SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2791 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2792 )
2793{
2794 assert(lp != NULL);
2795 assert(barrierconvtol >= 0.0);
2796 assert(success != NULL);
2797
2799
2800 if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2801 {
2802 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2803 if( *success )
2804 {
2805 SCIP_Real actualbarrierconvtol;
2806
2807 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2808 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) );
2809 if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol
2811 {
2812 /* mark the current solution invalid */
2813 lp->solved = FALSE;
2814 lp->dualfeasible = FALSE;
2815 lp->dualchecked = FALSE;
2816 lp->lpobjval = SCIP_INVALID;
2818 }
2819 else
2820 *success = FALSE;
2821 lp->lpibarrierconvtol = actualbarrierconvtol;
2822 }
2823 }
2824 else
2825 *success = FALSE;
2826
2827 return SCIP_OKAY;
2828}
2829
2830/** sets the FROMSCRATCH setting of the LP solver */
2831static
2833 SCIP_LP* lp, /**< current LP data */
2834 SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2835 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2836 )
2837{
2838 assert(lp != NULL);
2839 assert(success != NULL);
2840
2842
2843 if( fromscratch != lp->lpifromscratch )
2844 {
2845 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2846 if( *success )
2847 lp->lpifromscratch = fromscratch;
2848 }
2849 else
2850 *success = FALSE;
2851
2852 return SCIP_OKAY;
2853}
2854
2855/** sets the FASTMIP setting of the LP solver */
2856static
2858 SCIP_LP* lp, /**< current LP data */
2859 int fastmip, /**< new FASTMIP setting */
2860 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2861 )
2862{
2863 assert(lp != NULL);
2864 assert(success != NULL);
2865 assert(0 <= fastmip && fastmip <= 1);
2866
2868
2869 if( fastmip != lp->lpifastmip )
2870 {
2871 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2872 if( *success )
2873 {
2874 lp->lpifastmip = fastmip;
2875 lp->solved = FALSE;
2876 /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more
2877 * demanding setting; however, in the current code, this should have not effect. */
2878 }
2879 }
2880 else
2881 *success = FALSE;
2882
2883 return SCIP_OKAY;
2884}
2885
2886/** sets the SCALING setting of the LP solver */
2887static
2889 SCIP_LP* lp, /**< current LP data */
2890 int scaling, /**< new SCALING setting */
2891 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2892 )
2893{
2894 assert(lp != NULL);
2895 assert(success != NULL);
2896
2898
2899 if( scaling != lp->lpiscaling )
2900 {
2901 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2902 if( *success )
2903 lp->lpiscaling = scaling;
2904 }
2905 else
2906 *success = FALSE;
2907
2908 return SCIP_OKAY;
2909}
2910
2911/** sets the number of THREADS of the LP solver */
2912static
2914 SCIP_LP* lp, /**< current LP data */
2915 int threads, /**< new number of threads used to solve the LP */
2916 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2917 )
2918{
2919 assert(lp != NULL);
2920 assert(success != NULL);
2921
2923
2924 if( threads != lp->lpithreads )
2925 {
2926 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2927 if( *success )
2928 lp->lpithreads = threads;
2929 }
2930 else
2931 *success = FALSE;
2932
2933 return SCIP_OKAY;
2934}
2935
2936/** sets the PRESOLVING setting of the LP solver */
2937static
2939 SCIP_LP* lp, /**< current LP data */
2940 SCIP_Bool presolving, /**< new PRESOLVING setting */
2941 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2942 )
2943{
2944 assert(lp != NULL);
2945 assert(success != NULL);
2946
2948
2949 if( presolving != lp->lpipresolving )
2950 {
2951 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2952 if( *success )
2953 lp->lpipresolving = presolving;
2954 }
2955 else
2956 *success = FALSE;
2957
2958 return SCIP_OKAY;
2959}
2960
2961/** sets the ROWREPSWITCH setting of the LP solver */
2962static
2964 SCIP_LP* lp, /**< current LP data */
2965 SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2966 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2967 )
2968{
2969 assert(lp != NULL);
2970 assert(success != NULL);
2971
2973
2974 if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2975 {
2976 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2977 if( *success )
2978 lp->lpirowrepswitch = rowrepswitch;
2979 }
2980 else
2981 *success = FALSE;
2982
2983 return SCIP_OKAY;
2984}
2985
2986/** sets the iteration limit of the LP solver */
2987static
2989 SCIP_LP* lp, /**< current LP data */
2990 int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2991 )
2992{
2993 SCIP_Bool success;
2994
2995 assert(lp != NULL);
2996 assert(itlim >= -1);
2997
2998 if( itlim == -1 )
2999 itlim = INT_MAX;
3000
3002
3003 if( itlim != lp->lpiitlim )
3004 {
3005 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
3006 if( success )
3007 {
3008 if( itlim > lp->lpiitlim )
3009 {
3010 /* mark the current solution invalid */
3011 lp->solved = FALSE;
3012 lp->lpobjval = SCIP_INVALID;
3014 }
3015 lp->lpiitlim = itlim;
3016 }
3017 }
3018
3019 return SCIP_OKAY;
3020}
3021
3022/** sets the pricing strategy of the LP solver */
3023static
3025 SCIP_LP* lp, /**< current LP data */
3026 SCIP_PRICING pricing /**< pricing strategy */
3027 )
3028{
3029 SCIP_Bool success;
3030
3031 assert(lp != NULL);
3032
3034
3035 if( pricing != lp->lpipricing )
3036 {
3037 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
3038 if( success )
3039 lp->lpipricing = pricing;
3040 }
3041
3042 return SCIP_OKAY;
3043}
3044
3045/** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
3046static
3048 SCIP_LP* lp, /**< current LP data */
3049 char pricingchar /**< character representing the pricing strategy */
3050 )
3051{
3052 SCIP_PRICING pricing;
3053
3054 switch( pricingchar )
3055 {
3056 case 'l':
3057 pricing = SCIP_PRICING_LPIDEFAULT;
3058 break;
3059 case 'a':
3060 pricing = SCIP_PRICING_AUTO;
3061 break;
3062 case 'f':
3063 pricing = SCIP_PRICING_FULL;
3064 break;
3065 case 'p':
3066 pricing = SCIP_PRICING_PARTIAL;
3067 break;
3068 case 's':
3069 pricing = SCIP_PRICING_STEEP;
3070 break;
3071 case 'q':
3072 pricing = SCIP_PRICING_STEEPQSTART;
3073 break;
3074 case 'd':
3075 pricing = SCIP_PRICING_DEVEX;
3076 break;
3077 default:
3078 SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
3079 return SCIP_INVALIDDATA;
3080 }
3081
3082 SCIP_CALL( lpSetPricing(lp, pricing) );
3083
3084 return SCIP_OKAY;
3085}
3086
3087/** sets the verbosity of the LP solver */
3088static
3090 SCIP_LP* lp, /**< current LP data */
3091 SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3092 )
3093{
3094 SCIP_Bool success;
3095
3096 assert(lp != NULL);
3097
3099
3100 if( lpinfo != lp->lpilpinfo )
3101 {
3102 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3103 if( success )
3104 lp->lpilpinfo = lpinfo;
3105 }
3106
3107 return SCIP_OKAY;
3108}
3109
3110/** sets the CONDITIONLIMIT setting of the LP solver */
3111static
3113 SCIP_LP* lp, /**< current LP data */
3114 SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3115 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3116 )
3117{
3118 assert(lp != NULL);
3119 assert(success != NULL);
3120
3122
3123 if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3124 {
3125 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3126 if( *success )
3127 lp->lpiconditionlimit = condlimit;
3128 }
3129 else
3130 *success = FALSE;
3131
3132 return SCIP_OKAY;
3133}
3134
3135/** sets the MARKOWITZ setting of the LP solver */
3136static
3138 SCIP_LP* lp, /**< current LP data */
3139 SCIP_Real threshhold, /**< new MARKOWITZ value */
3140 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3141 )
3142{
3143 assert(lp != NULL);
3144 assert(success != NULL);
3145
3147
3148 if( threshhold != lp->lpimarkowitz ) /*lint !e777*/
3149 {
3150 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) );
3151 if( *success )
3152 lp->lpimarkowitz = threshhold;
3153 }
3154 else
3155 *success = FALSE;
3156
3157 return SCIP_OKAY;
3158}
3159
3160/** sets the type of timer of the LP solver */
3161static
3163 SCIP_LP* lp, /**< current LP data */
3164 SCIP_CLOCKTYPE timing, /**< new timing value */
3165 SCIP_Bool enabled, /**< is timing enabled? */
3166 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3167 )
3168{
3169 int lptiming;
3170
3171 assert(lp != NULL);
3172 assert(success != NULL);
3173 assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/
3174
3176
3177 if( !enabled )
3178 lptiming = 0;
3179 else
3180 lptiming = (int) timing;
3181
3182 if( lptiming != lp->lpitiming ) /*lint !e777*/
3183 {
3184 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3185 if( *success )
3186 lp->lpitiming = lptiming;
3187 }
3188 else
3189 *success = FALSE;
3190
3191 return SCIP_OKAY;
3192}
3193
3194/** sets the initial random seed of the LP solver */
3195static
3197 SCIP_LP* lp, /**< current LP data */
3198 int randomseed, /**< new initial random seed */
3199 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3200 )
3201{
3202 assert(lp != NULL);
3203 assert(success != NULL);
3204
3205 /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */
3206
3207 if( randomseed == 0 )
3208 {
3209 lp->lpirandomseed = randomseed;
3210 *success = TRUE;
3211 }
3212 else if( randomseed != lp->lpirandomseed ) /*lint !e777*/
3213 {
3214 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) );
3215 if( *success )
3216 lp->lpirandomseed = randomseed;
3217 }
3218 else
3219 *success = FALSE;
3220
3221 return SCIP_OKAY;
3222}
3223
3224/** sets the LP solution polishing method */
3225static
3227 SCIP_LP* lp, /**< current LP data */
3228 SCIP_Bool polishing, /**< LP solution polishing activated (0: disabled, 1: enabled) */
3229 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3230 )
3231{
3232 assert(lp != NULL);
3233 assert(success != NULL);
3234
3235 if( polishing != lp->lpisolutionpolishing )
3236 {
3237 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) );
3238 if( *success )
3239 lp->lpisolutionpolishing = polishing;
3240 }
3241 else
3242 *success = FALSE;
3243
3244 return SCIP_OKAY;
3245}
3246
3247/** sets the LP refactorization interval */
3248static
3250 SCIP_LP* lp, /**< current LP data */
3251 int refactor, /**< LP refactorization interval (0: automatic) */
3252 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3253 )
3254{
3255 assert(lp != NULL);
3256 assert(success != NULL);
3257
3258 if( refactor != lp->lpirefactorinterval )
3259 {
3260 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) );
3261 if( *success )
3262 lp->lpirefactorinterval = refactor;
3263 }
3264 else
3265 *success = FALSE;
3266
3267 return SCIP_OKAY;
3268}
3269
3270
3271/*
3272 * Column methods
3273 */
3274
3275/** creates an LP column */
3277 SCIP_COL** col, /**< pointer to column data */
3278 BMS_BLKMEM* blkmem, /**< block memory */
3279 SCIP_SET* set, /**< global SCIP settings */
3280 SCIP_STAT* stat, /**< problem statistics */
3281 SCIP_VAR* var, /**< variable, this column represents */
3282 int len, /**< number of nonzeros in the column */
3283 SCIP_ROW** rows, /**< array with rows of column entries */
3284 SCIP_Real* vals, /**< array with coefficients of column entries */
3285 SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3286 )
3287{
3288 int i;
3289
3290 assert(col != NULL);
3291 assert(blkmem != NULL);
3292 assert(set != NULL);
3293 assert(stat != NULL);
3294 assert(var != NULL);
3295 assert(len >= 0);
3296 assert(len == 0 || (rows != NULL && vals != NULL));
3297
3298 SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3299
3300 if( len > 0 )
3301 {
3302 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3303 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3304 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3305
3306 for( i = 0; i < len; ++i )
3307 {
3308 assert(rows[i] != NULL);
3309 assert(!SCIPsetIsZero(set, vals[i]));
3310 (*col)->linkpos[i] = -1;
3311 }
3312 }
3313 else
3314 {
3315 (*col)->rows = NULL;
3316 (*col)->vals = NULL;
3317 (*col)->linkpos = NULL;
3318 }
3319
3320 (*col)->var = var;
3321 (*col)->obj = SCIPvarGetObj(var);
3322 (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3323 (*col)->lb = SCIPvarGetLbLocal(var);
3324 (*col)->ub = SCIPvarGetUbLocal(var);
3325 (*col)->flushedobj = 0.0;
3326 (*col)->flushedlb = 0.0;
3327 (*col)->flushedub = 0.0;
3328 (*col)->index = stat->ncolidx;
3329 SCIPstatIncrement(stat, set, ncolidx);
3330 (*col)->size = len;
3331 (*col)->len = len;
3332 (*col)->nlprows = 0;
3333 (*col)->nunlinked = len;
3334 (*col)->lppos = -1;
3335 (*col)->lpipos = -1;
3336 (*col)->lpdepth = -1;
3337 (*col)->primsol = 0.0;
3338 (*col)->redcost = SCIP_INVALID;
3339 (*col)->farkascoef = SCIP_INVALID;
3340 (*col)->minprimsol = (*col)->ub;
3341 (*col)->maxprimsol = (*col)->lb;
3342 (*col)->sbdown = SCIP_INVALID;
3343 (*col)->sbup = SCIP_INVALID;
3344 (*col)->sbsolval = SCIP_INVALID;
3345 (*col)->sblpobjval = SCIP_INVALID;
3346 (*col)->sbnode = -1;
3347 (*col)->validredcostlp = -1;
3348 (*col)->validfarkaslp = -1;
3349 (*col)->validsblp = -1;
3350 (*col)->sbitlim = -1;
3351 (*col)->nsbcalls = 0;
3352 (*col)->age = 0;
3353 (*col)->obsoletenode = -1;
3354 (*col)->var_probindex = SCIPvarGetProbindex(var);
3355 (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3356 (*col)->lprowssorted = TRUE;
3357 (*col)->nonlprowssorted = (len <= 1);
3358 (*col)->objchanged = FALSE;
3359 (*col)->lbchanged = FALSE;
3360 (*col)->ubchanged = FALSE;
3361 (*col)->coefchanged = FALSE;
3362 (*col)->integral = SCIPvarIsIntegral(var);
3363 (*col)->removable = removable;
3364 (*col)->sbdownvalid = FALSE;
3365 (*col)->sbupvalid = FALSE;
3366 (*col)->lazylb = SCIPvarGetLbLazy(var);
3367 (*col)->lazyub = SCIPvarGetUbLazy(var);
3368 (*col)->storedsolvals = NULL;
3369
3370 return SCIP_OKAY;
3371}
3372
3373/** frees an LP column */
3375 SCIP_COL** col, /**< pointer to LP column */
3376 BMS_BLKMEM* blkmem, /**< block memory */
3377 SCIP_SET* set, /**< global SCIP settings */
3378 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3379 SCIP_LP* lp /**< current LP data */
3380 )
3381{
3382 assert(blkmem != NULL);
3383 assert(col != NULL);
3384 assert(*col != NULL);
3385 assert((*col)->var != NULL);
3386 assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3387 assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3388 assert((*col)->lppos == -1);
3389 assert((*col)->lpipos == -1);
3390
3391 /* remove column indices from corresponding rows */
3392 SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3393
3394 BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3395 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3396 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3397 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3398 BMSfreeBlockMemory(blkmem, col);
3399
3400 return SCIP_OKAY;
3401}
3402
3403/** output column to file stream */
3405 SCIP_COL* col, /**< LP column */
3406 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3407 FILE* file /**< output file (or NULL for standard output) */
3408 )
3409{
3410 int r;
3411
3412 assert(col != NULL);
3413 assert(col->var != NULL);
3414
3415 /* print bounds */
3416 SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3417
3418 /* print coefficients */
3419 if( col->len == 0 )
3420 SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3421 for( r = 0; r < col->len; ++r )
3422 {
3423 assert(col->rows[r] != NULL);
3424 assert(col->rows[r]->name != NULL);
3425 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3426 }
3427 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3428}
3429
3430/** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3431 */
3433 SCIP_COL* col /**< column to be sorted */
3434 )
3435{
3436 /* sort LP rows */
3437 colSortLP(col);
3438
3439 /* sort non-LP rows */
3440 colSortNonLP(col);
3441}
3442
3443/** adds a previously non existing coefficient to an LP column */
3445 SCIP_COL* col, /**< LP column */
3446 BMS_BLKMEM* blkmem, /**< block memory */
3447 SCIP_SET* set, /**< global SCIP settings */
3448 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3449 SCIP_LP* lp, /**< current LP data */
3450 SCIP_ROW* row, /**< LP row */
3451 SCIP_Real val /**< value of coefficient */
3452 )
3453{
3454 assert(lp != NULL);
3455 assert(!lp->diving);
3456
3457 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3458
3459 checkLinks(lp);
3460
3461 return SCIP_OKAY;
3462}
3463
3464/** deletes existing coefficient from column */
3466 SCIP_COL* col, /**< column to be changed */
3467 BMS_BLKMEM* blkmem, /**< block memory */
3468 SCIP_SET* set, /**< global SCIP settings */
3469 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3470 SCIP_LP* lp, /**< current LP data */
3471 SCIP_ROW* row /**< coefficient to be deleted */
3472 )
3473{
3474 int pos;
3475
3476 assert(col != NULL);
3477 assert(col->var != NULL);
3478 assert(lp != NULL);
3479 assert(!lp->diving);
3480 assert(row != NULL);
3481
3482 /* search the position of the row in the column's row vector */
3483 pos = colSearchCoef(col, row);
3484 if( pos == -1 )
3485 {
3486 SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3487 return SCIP_INVALIDDATA;
3488 }
3489 assert(0 <= pos && pos < col->len);
3490 assert(col->rows[pos] == row);
3491
3492 /* if row knows of the column, remove the column from the row's col vector */
3493 if( col->linkpos[pos] >= 0 )
3494 {
3495 assert(row->cols[col->linkpos[pos]] == col);
3496 assert(row->cols_index[col->linkpos[pos]] == col->index);
3497 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3498 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3499 }
3500
3501 /* delete the row from the column's row vector */
3502 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3503
3504 checkLinks(lp);
3505
3506 return SCIP_OKAY;
3507}
3508
3509/** changes or adds a coefficient to an LP column */
3511 SCIP_COL* col, /**< LP column */
3512 BMS_BLKMEM* blkmem, /**< block memory */
3513 SCIP_SET* set, /**< global SCIP settings */
3514 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3515 SCIP_LP* lp, /**< current LP data */
3516 SCIP_ROW* row, /**< LP row */
3517 SCIP_Real val /**< value of coefficient */
3518 )
3519{
3520 int pos;
3521
3522 assert(col != NULL);
3523 assert(lp != NULL);
3524 assert(!lp->diving);
3525 assert(row != NULL);
3526
3527 /* search the position of the row in the column's row vector */
3528 pos = colSearchCoef(col, row);
3529
3530 /* check, if row already exists in the column's row vector */
3531 if( pos == -1 )
3532 {
3533 /* add previously not existing coefficient */
3534 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3535 }
3536 else
3537 {
3538 /* modify already existing coefficient */
3539 assert(0 <= pos && pos < col->len);
3540 assert(col->rows[pos] == row);
3541
3542 /* if row knows of the column, change the corresponding coefficient in the row */
3543 if( col->linkpos[pos] >= 0 )
3544 {
3545 assert(row->cols[col->linkpos[pos]] == col);
3546 assert(row->cols_index[col->linkpos[pos]] == col->index);
3547 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3548 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3549 }
3550
3551 /* change the coefficient in the column */
3552 SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3553 }
3554
3555 checkLinks(lp);
3556
3557 return SCIP_OKAY;
3558}
3559
3560/** increases value of an existing or non-existing coefficient in an LP column */
3562 SCIP_COL* col, /**< LP column */
3563 BMS_BLKMEM* blkmem, /**< block memory */
3564 SCIP_SET* set, /**< global SCIP settings */
3565 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3566 SCIP_LP* lp, /**< current LP data */
3567 SCIP_ROW* row, /**< LP row */
3568 SCIP_Real incval /**< value to add to the coefficient */
3569 )
3570{
3571 int pos;
3572
3573 assert(col != NULL);
3574 assert(lp != NULL);
3575 assert(!lp->diving);
3576 assert(row != NULL);
3577
3578 if( SCIPsetIsZero(set, incval) )
3579 return SCIP_OKAY;
3580
3581 /* search the position of the row in the column's row vector */
3582 pos = colSearchCoef(col, row);
3583
3584 /* check, if row already exists in the column's row vector */
3585 if( pos == -1 )
3586 {
3587 /* add previously not existing coefficient */
3588 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3589 }
3590 else
3591 {
3592 /* modify already existing coefficient */
3593 assert(0 <= pos && pos < col->len);
3594 assert(col->rows[pos] == row);
3595
3596 /* if row knows of the column, change the corresponding coefficient in the row */
3597 if( col->linkpos[pos] >= 0 )
3598 {
3599 assert(row->cols[col->linkpos[pos]] == col);
3600 assert(row->cols_index[col->linkpos[pos]] == col->index);
3601 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3602 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3603 }
3604
3605 /* change the coefficient in the column */
3606 SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3607 }
3608
3609 checkLinks(lp);
3610
3611 return SCIP_OKAY;
3612}
3613
3614/** insert column in the chgcols list (if not already there) */
3615static
3617 SCIP_COL* col, /**< LP column to change */
3618 SCIP_SET* set, /**< global SCIP settings */
3619 SCIP_LP* lp /**< current LP data */
3620 )
3621{
3622 if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3623 {
3624 SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3625 lp->chgcols[lp->nchgcols] = col;
3626 lp->nchgcols++;
3627 }
3628
3629 /* mark the current LP unflushed */
3630 lp->flushed = FALSE;
3631
3632 return SCIP_OKAY;
3633}
3634
3635/** Is the new value reliable or may we have cancellation?
3636 *
3637 * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3638 * cancellations which can occur during increasing the oldvalue to the newvalue
3639 */
3640static
3642 SCIP_SET* set, /**< global SCIP settings */
3643 SCIP_Real newvalue, /**< new value */
3644 SCIP_Real oldvalue /**< old reliable value */
3645 )
3646{
3647 SCIP_Real quotient;
3648
3649 assert(set != NULL);
3650 assert(oldvalue != SCIP_INVALID); /*lint !e777*/
3651
3652 quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3653
3654 return SCIPsetIsZero(set, quotient);
3655}
3656
3657/** update norms of objective function vector */
3658static
3660 SCIP_LP* lp, /**< current LP data */
3661 SCIP_SET* set, /**< global SCIP settings */
3662 SCIP_Real oldobj, /**< old objective value of variable */
3663 SCIP_Real newobj /**< new objective value of variable */
3664 )
3665{
3666 if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
3667 {
3668 if( !lp->objsqrnormunreliable )
3669 {
3670 SCIP_Real oldvalue;
3671
3672 oldvalue = lp->objsqrnorm;
3673 lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3674
3675 /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3676 if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3678 else
3679 {
3680 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3681
3682 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3683 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3684
3685 assert(lp->objsqrnorm >= 0.0);
3686 }
3687 }
3688
3689 lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3690 lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3691 }
3692}
3693
3694/** changes objective value of column */
3696 SCIP_COL* col, /**< LP column to change */
3697 SCIP_SET* set, /**< global SCIP settings */
3698 SCIP_LP* lp, /**< current LP data */
3699 SCIP_Real newobj /**< new objective value */
3700 )
3701{
3702 assert(col != NULL);
3703 assert(col->var != NULL);
3705 assert(SCIPvarGetCol(col->var) == col);
3706 assert(lp != NULL);
3707
3708 SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3709
3710 /* only add actual changes */
3711 if( !SCIPsetIsEQ(set, col->obj, newobj) )
3712 {
3713 /* only variables with a real position in the LPI can be inserted */
3714 if( col->lpipos >= 0 )
3715 {
3716 /* insert column in the chgcols list (if not already there) */
3717 SCIP_CALL( insertColChgcols(col, set, lp) );
3718
3719 /* mark objective value change in the column */
3720 col->objchanged = TRUE;
3721
3722 assert(lp->nchgcols > 0);
3723 }
3724 /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3725 * LP and the LP has to be flushed
3726 */
3727 else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3728 || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3729 {
3730 /* mark the LP unflushed */
3731 lp->flushed = FALSE;
3732 }
3733 }
3734
3735 /* store new objective function value */
3736 col->obj = newobj;
3737
3738 /* update original objective value, as long as we are not in diving or probing and changed objective values */
3739 if( !lp->divingobjchg )
3740 {
3741 SCIP_Real oldobj = col->unchangedobj;
3742
3743 assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3744 col->unchangedobj = newobj;
3745
3746 /* update the objective function vector norms */
3747 lpUpdateObjNorms(lp, set, oldobj, newobj);
3748 }
3749
3750 return SCIP_OKAY;
3751}
3752
3753/** changes lower bound of column */
3755 SCIP_COL* col, /**< LP column to change */
3756 SCIP_SET* set, /**< global SCIP settings */
3757 SCIP_LP* lp, /**< current LP data */
3758 SCIP_Real newlb /**< new lower bound value */
3759 )
3760{
3761 assert(col != NULL);
3762 assert(col->var != NULL);
3764 assert(SCIPvarGetCol(col->var) == col);
3765 assert(lp != NULL);
3766
3767 SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3768
3769 /* only add actual changes */
3770 if( !SCIPsetIsEQ(set, col->lb, newlb) )
3771 {
3772 /* only variables with a real position in the LPI can be inserted */
3773 if( col->lpipos >= 0 )
3774 {
3775 /* insert column in the chgcols list (if not already there) */
3776 SCIP_CALL( insertColChgcols(col, set, lp) );
3777
3778 /* mark bound change in the column */
3779 col->lbchanged = TRUE;
3780
3781 assert(lp->nchgcols > 0);
3782 }
3783 /* 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
3784 * flushed
3785 */
3786 else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3787 {
3788 /* mark the LP unflushed */
3789 lp->flushed = FALSE;
3790 }
3791 }
3792
3793 col->lb = newlb;
3794
3795 return SCIP_OKAY;
3796}
3797
3798/** changes upper bound of column */
3800 SCIP_COL* col, /**< LP column to change */
3801 SCIP_SET* set, /**< global SCIP settings */
3802 SCIP_LP* lp, /**< current LP data */
3803 SCIP_Real newub /**< new upper bound value */
3804 )
3805{
3806 assert(col != NULL);
3807 assert(col->var != NULL);
3809 assert(SCIPvarGetCol(col->var) == col);
3810 assert(lp != NULL);
3811
3812 SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3813
3814 /* only add actual changes */
3815 if( !SCIPsetIsEQ(set, col->ub, newub) )
3816 {
3817 /* only variables with a real position in the LPI can be inserted */
3818 if( col->lpipos >= 0 )
3819 {
3820 /* insert column in the chgcols list (if not already there) */
3821 SCIP_CALL( insertColChgcols(col, set, lp) );
3822
3823 /* mark bound change in the column */
3824 col->ubchanged = TRUE;
3825
3826 assert(lp->nchgcols > 0);
3827 }
3828 /* 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
3829 * flushed
3830 */
3831 else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3832 {
3833 /* mark the LP unflushed */
3834 lp->flushed = FALSE;
3835 }
3836 }
3837
3838 col->ub = newub;
3839
3840 return SCIP_OKAY;
3841}
3842
3843/** calculates the reduced costs of a column using the given dual solution vector */
3845 SCIP_COL* col, /**< LP column */
3846 SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3847 )
3848{
3849 SCIP_ROW* row;
3850 SCIP_Real redcost;
3851 int i;
3852
3853 assert(col != NULL);
3855 assert(SCIPvarGetCol(col->var) == col);
3856 assert(dualsol != NULL);
3857
3858 redcost = col->obj;
3859 for( i = 0; i < col->nlprows; ++i )
3860 {
3861 row = col->rows[i];
3862 assert(row != NULL);
3863 assert(row->lppos >= 0);
3864 redcost -= col->vals[i] * dualsol[row->lppos];
3865 }
3866
3867 if( col->nunlinked > 0 )
3868 {
3869 for( i = col->nlprows; i < col->len; ++i )
3870 {
3871 row = col->rows[i];
3872 assert(row != NULL);
3873 assert(row->lppos == -1 || col->linkpos[i] == -1);
3874 if( row->lppos >= 0 )
3875 redcost -= col->vals[i] * dualsol[row->lppos];
3876 }
3877 }
3878#ifndef NDEBUG
3879 else
3880 {
3881 for( i = col->nlprows; i < col->len; ++i )
3882 {
3883 row = col->rows[i];
3884 assert(row != NULL);
3885 assert(row->lppos == -1);
3886 assert(col->linkpos[i] >= 0);
3887 }
3888 }
3889#endif
3890
3891 return redcost;
3892}
3893
3894/** calculates the reduced costs of a column using the dual solution stored in the rows */
3895static
3897 SCIP_COL* col /**< LP column */
3898 )
3899{
3900 SCIP_ROW* row;
3901 SCIP_Real redcost;
3902 int i;
3903
3904 assert(col != NULL);
3906 assert(SCIPvarGetCol(col->var) == col);
3907
3908 redcost = col->obj;
3909 for( i = 0; i < col->nlprows; ++i )
3910 {
3911 row = col->rows[i];
3912 assert(row != NULL);
3913 assert(row->dualsol != SCIP_INVALID); /*lint !e777*/
3914 assert(row->lppos >= 0);
3915 assert(col->linkpos[i] >= 0);
3916 redcost -= col->vals[i] * row->dualsol;
3917 }
3918
3919 if( col->nunlinked > 0 )
3920 {
3921 for( i = col->nlprows; i < col->len; ++i )
3922 {
3923 row = col->rows[i];
3924 assert(row != NULL);
3925 assert(row->lppos >= 0 || row->dualsol == 0.0);
3926 assert(row->lppos == -1 || col->linkpos[i] == -1);
3927 if( row->lppos >= 0 )
3928 redcost -= col->vals[i] * row->dualsol;
3929 }
3930 }
3931#ifndef NDEBUG
3932 else
3933 {
3934 for( i = col->nlprows; i < col->len; ++i )
3935 {
3936 row = col->rows[i];
3937 assert(row != NULL);
3938 assert(row->dualsol == 0.0);
3939 assert(row->lppos == -1);
3940 assert(col->linkpos[i] >= 0);
3941 }
3942 }
3943#endif
3944
3945 return redcost;
3946}
3947
3948/** gets the reduced costs of a column in last LP or after recalculation */
3950 SCIP_COL* col, /**< LP column */
3951 SCIP_STAT* stat, /**< problem statistics */
3952 SCIP_LP* lp /**< current LP data */
3953 )
3954{
3955 assert(col != NULL);
3956 assert(stat != NULL);
3957 assert(lp != NULL);
3958 assert(col->validredcostlp <= stat->lpcount);
3959 assert(lp->validsollp == stat->lpcount);
3960
3961 if( col->validredcostlp < stat->lpcount )
3962 {
3963 col->redcost = colCalcInternalRedcost(col);
3964 col->validredcostlp = stat->lpcount;
3965 }
3966 assert(col->validredcostlp == stat->lpcount);
3967 assert(col->redcost != SCIP_INVALID); /*lint !e777*/
3968
3969 return col->redcost;
3970}
3971
3972/** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3974 SCIP_COL* col, /**< LP column */
3975 SCIP_SET* set, /**< global SCIP settings */
3976 SCIP_STAT* stat, /**< problem statistics */
3977 SCIP_LP* lp /**< current LP data */
3978 )
3979{
3980 assert(col != NULL);
3981 assert(set != NULL);
3982 assert(stat != NULL);
3983 assert(lp != NULL);
3984 assert(lp->validsollp == stat->lpcount);
3985
3986 /* A column's reduced cost is defined as
3987 * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3988 * The activity is equal to the activity of the corresponding row in the dual LP.
3989 * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3990 * The sides of the dual row depend on the bounds of the column:
3991 * - lb == ub : dual row is a free row with infinite sides
3992 * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3993 * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3994 * - lb < ub <= 0: obj <= activity => redcost <= 0
3995 */
3996 if( SCIPsetIsEQ(set, col->lb, col->ub) )
3997 {
3998 /* dual row is free */
3999 return SCIPsetInfinity(set);
4000 }
4001 else
4002 {
4003 SCIP_Real redcost;
4004
4005 /* calculate reduced costs */
4006 redcost = SCIPcolGetRedcost(col, stat, lp);
4007
4008 if( !SCIPsetIsNegative(set, col->lb) )
4009 {
4010 /* dual row is activity <= obj <=> redcost >= 0 */
4011 return redcost;
4012 }
4013 else if( SCIPsetIsPositive(set, col->ub) )
4014 {
4015 /* dual row is activity == obj <=> redcost == 0 */
4016 return -REALABS(redcost);
4017 }
4018 else
4019 {
4020 /* dual row is activity >= obj <=> redcost <= 0 */
4021 return -redcost;
4022 }
4023 }
4024}
4025
4026/** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
4028 SCIP_COL* col, /**< LP column */
4029 SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
4030 )
4031{
4032 SCIP_ROW* row;
4033 SCIP_Real farkas;
4034 int i;
4035
4036 assert(col != NULL);
4038 assert(SCIPvarGetCol(col->var) == col);
4039 assert(dualfarkas != NULL);
4040
4041 farkas = 0.0;
4042 for( i = 0; i < col->nlprows; ++i )
4043 {
4044 row = col->rows[i];
4045 assert(row != NULL);
4046 assert(row->lppos >= 0);
4047 farkas += col->vals[i] * dualfarkas[row->lppos];
4048 }
4049
4050 if( col->nunlinked > 0 )
4051 {
4052 for( i = col->nlprows; i < col->len; ++i )
4053 {
4054 row = col->rows[i];
4055 assert(row != NULL);
4056 assert(row->lppos == -1 || col->linkpos[i] == -1);
4057 if( row->lppos >= 0 )
4058 farkas += col->vals[i] * dualfarkas[row->lppos];
4059 }
4060 }
4061#ifndef NDEBUG
4062 else
4063 {
4064 for( i = col->nlprows; i < col->len; ++i )
4065 {
4066 row = col->rows[i];
4067 assert(row != NULL);
4068 assert(row->lppos == -1);
4069 assert(col->linkpos[i] >= 0);
4070 }
4071 }
4072#endif
4073
4074 return farkas;
4075}
4076
4077/** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
4078static
4080 SCIP_COL* col /**< LP column */
4081 )
4082{
4083 SCIP_ROW* row;
4084 SCIP_Real farkas;
4085 int i;
4086
4087 assert(col != NULL);
4089 assert(SCIPvarGetCol(col->var) == col);
4090
4091 farkas = 0.0;
4092 for( i = 0; i < col->nlprows; ++i )
4093 {
4094 row = col->rows[i];
4095 assert(row != NULL);
4096 assert(row->dualfarkas != SCIP_INVALID); /*lint !e777*/
4097 assert(row->lppos >= 0);
4098 assert(col->linkpos[i] >= 0);
4099 farkas += col->vals[i] * row->dualfarkas;
4100 }
4101
4102 if( col->nunlinked > 0 )
4103 {
4104 for( i = col->nlprows; i < col->len; ++i )
4105 {
4106 row = col->rows[i];
4107 assert(row != NULL);
4108 assert(row->lppos >= 0 || row->dualfarkas == 0.0);
4109 assert(row->lppos == -1 || col->linkpos[i] == -1);
4110 if( row->lppos >= 0 )
4111 farkas += col->vals[i] * row->dualfarkas;
4112 }
4113 }
4114#ifndef NDEBUG
4115 else
4116 {
4117 for( i = col->nlprows; i < col->len; ++i )
4118 {
4119 row = col->rows[i];
4120 assert(row != NULL);
4121 assert(row->dualfarkas == 0.0);
4122 assert(row->lppos == -1);
4123 assert(col->linkpos[i] >= 0);
4124 }
4125 }
4126#endif
4127
4128 return farkas;
4129}
4130
4131/** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
4133 SCIP_COL* col, /**< LP column */
4134 SCIP_STAT* stat, /**< problem statistics */
4135 SCIP_LP* lp /**< current LP data */
4136 )
4137{
4138 assert(col != NULL);
4139 assert(stat != NULL);
4140 assert(lp != NULL);
4141 assert(col->validfarkaslp <= stat->lpcount);
4142 assert(lp->validfarkaslp == stat->lpcount);
4143
4144 if( col->validfarkaslp < stat->lpcount )
4145 {
4147 col->validfarkaslp = stat->lpcount;
4148 }
4149 assert(col->validfarkaslp == stat->lpcount);
4150 assert(col->farkascoef != SCIP_INVALID); /*lint !e777*/
4151
4152 return col->farkascoef;
4153}
4154
4155/** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
4156 * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
4157 */
4159 SCIP_COL* col, /**< LP column */
4160 SCIP_STAT* stat, /**< problem statistics */
4161 SCIP_LP* lp /**< current LP data */
4162 )
4163{
4164 SCIP_Real farkascoef;
4165
4166 assert(col != NULL);
4167
4168 farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
4169
4170 if( farkascoef > 0.0 )
4171 return col->ub * farkascoef;
4172 else
4173 return col->lb * farkascoef;
4174}
4175
4176/** start strong branching - call before any strong branching */
4178 SCIP_LP* lp /**< LP data */
4179 )
4180{
4181 assert(lp != NULL);
4182 assert(!lp->strongbranching);
4183
4184 lp->strongbranching = TRUE;
4185 SCIPdebugMessage("starting strong branching ...\n");
4187
4188 return SCIP_OKAY;
4189}
4190
4191/** end strong branching - call after any strong branching */
4193 SCIP_LP* lp /**< LP data */
4194 )
4195{
4196 assert(lp != NULL);
4197 assert(lp->strongbranching);
4198
4199 lp->strongbranching = FALSE;
4200 SCIPdebugMessage("ending strong branching ...\n");
4202
4203 return SCIP_OKAY;
4204}
4205
4206/** sets strong branching information for a column variable */
4208 SCIP_COL* col, /**< LP column */
4209 SCIP_SET* set, /**< global SCIP settings */
4210 SCIP_STAT* stat, /**< dynamic problem statistics */
4211 SCIP_LP* lp, /**< LP data */
4212 SCIP_Real lpobjval, /**< objective value of the current LP */
4213 SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4214 SCIP_Real sbdown, /**< dual bound after branching column down */
4215 SCIP_Real sbup, /**< dual bound after branching column up */
4216 SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
4217 SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
4218 SCIP_Longint iter, /**< total number of strong branching iterations */
4219 int itlim /**< iteration limit applied to the strong branching call */
4220 )
4221{
4222 assert(col != NULL);
4223 assert(col->var != NULL);
4224 assert(SCIPcolIsIntegral(col));
4225 assert(SCIPvarIsIntegral(col->var));
4227 assert(SCIPvarGetCol(col->var) == col);
4228 assert(col->lpipos >= 0);
4229 assert(col->lppos >= 0);
4230 assert(set != NULL);
4231 assert(stat != NULL);
4232 assert(lp != NULL);
4233 assert(lp->strongbranchprobing);
4234 assert(col->lppos < lp->ncols);
4235 assert(lp->cols[col->lppos] == col);
4236 assert(itlim >= 1);
4237
4238 col->sblpobjval = lpobjval;
4239 col->sbsolval = primsol;
4240 col->validsblp = stat->nlps;
4241 col->sbnode = stat->nnodes;
4242
4243 col->sbitlim = itlim;
4244 col->nsbcalls++;
4245
4246 col->sbdown = MIN(sbdown, lp->cutoffbound);
4247 col->sbup = MIN(sbup, lp->cutoffbound);
4248 col->sbdownvalid = sbdownvalid;
4249 col->sbupvalid = sbupvalid;
4250
4251 SCIPstatIncrement(stat, set, nstrongbranchs);
4252 SCIPstatAdd(stat, set, nsblpiterations, iter);
4253 if( stat->nnodes == 1 )
4254 {
4255 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4256 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4257 }
4258}
4259
4260/** invalidates strong branching information for a column variable */
4262 SCIP_COL* col, /**< LP column */
4263 SCIP_SET* set, /**< global SCIP settings */
4264 SCIP_STAT* stat, /**< dynamic problem statistics */
4265 SCIP_LP* lp /**< LP data */
4266 )
4267{
4268 assert(col != NULL);
4269 assert(col->var != NULL);
4270 assert(SCIPcolIsIntegral(col));
4271 assert(SCIPvarIsIntegral(col->var));
4273 assert(SCIPvarGetCol(col->var) == col);
4274 assert(col->lpipos >= 0);
4275 assert(col->lppos >= 0);
4276 assert(set != NULL);
4277 assert(stat != NULL);
4278 assert(lp != NULL);
4279 assert(lp->strongbranchprobing);
4280 assert(col->lppos < lp->ncols);
4281 assert(lp->cols[col->lppos] == col);
4282
4283 col->sbdown = SCIP_INVALID;
4284 col->sbup = SCIP_INVALID;
4285 col->sbdownvalid = FALSE;
4286 col->sbupvalid = FALSE;
4287 col->validsblp = -1;
4288 col->sbsolval = SCIP_INVALID;
4289 col->sblpobjval = SCIP_INVALID;
4290 col->sbnode = -1;
4291 col->sbitlim = -1;
4292}
4293
4294
4295/** gets strong branching information on a column variable */
4297 SCIP_COL* col, /**< LP column */
4298 SCIP_Bool integral, /**< should integral strong branching be performed? */
4299 SCIP_SET* set, /**< global SCIP settings */
4300 SCIP_STAT* stat, /**< dynamic problem statistics */
4301 SCIP_PROB* prob, /**< problem data */
4302 SCIP_LP* lp, /**< LP data */
4303 int itlim, /**< iteration limit for strong branchings */
4304 SCIP_Bool updatecol, /**< should col be updated, or should it stay in its current state ? */
4305 SCIP_Bool updatestat, /**< should stat be updated, or should it stay in its current state ? */
4306 SCIP_Real* down, /**< stores dual bound after branching column down */
4307 SCIP_Real* up, /**< stores dual bound after branching column up */
4308 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4309 * otherwise, it can only be used as an estimate value */
4310 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4311 * otherwise, it can only be used as an estimate value */
4312 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4313 )
4314{
4315 SCIP_Real sbdown;
4316 SCIP_Real sbup;
4317 SCIP_Bool sbdownvalid;
4318 SCIP_Bool sbupvalid;
4319 SCIP_Longint validsblp;
4320 SCIP_Real sbsolval;
4321 SCIP_Real sblpobjval;
4322 SCIP_Longint sbnode;
4323 int sbitlim;
4324 int nsbcalls;
4325
4326 assert(col != NULL);
4327 assert(col->var != NULL);
4328 assert(SCIPcolIsIntegral(col));
4329 assert(SCIPvarIsIntegral(col->var));
4331 assert(SCIPvarGetCol(col->var) == col);
4332 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4333 assert(col->lpipos >= 0);
4334 assert(col->lppos >= 0);
4335 assert(set != NULL);
4336 assert(stat != NULL);
4337 assert(lp != NULL);
4338 assert(lp->flushed);
4339 assert(lp->solved);
4340 assert(lp->strongbranching);
4341 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4342 assert(lp->validsollp == stat->lpcount);
4343 assert(col->lppos < lp->ncols);
4344 assert(lp->cols[col->lppos] == col);
4345 assert(itlim >= 1);
4346 /* assert(down != NULL);
4347 * assert(up != NULL); temporary hack for cloud branching
4348 */
4349 assert(lperror != NULL);
4350
4351 *lperror = FALSE;
4352
4353 sbdown = col->sbdown;
4354 sbup = col->sbup;
4355 sbdownvalid = col->sbdownvalid;
4356 sbupvalid = col->sbupvalid;
4357 sbitlim = col->sbitlim;
4358 nsbcalls = col->nsbcalls;
4359
4360 validsblp = stat->nlps;
4361 sbsolval = col->primsol;
4362 sblpobjval = SCIPlpGetObjval(lp, set, prob);
4363 sbnode = stat->nnodes;
4364 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4365
4366 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4367 if( lp->looseobjvalinf > 0 )
4368 {
4369 sbdown = -SCIPsetInfinity(set);
4370 sbup = -SCIPsetInfinity(set);
4371 sbdownvalid = FALSE;
4372 sbupvalid = FALSE;
4373 }
4374 else
4375 {
4376 SCIP_RETCODE retcode;
4377 int iter;
4378
4379 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4380 SCIPvarGetName(col->var), col->primsol, itlim);
4381
4382 /* start timing */
4384
4385 /* call LPI strong branching */
4386 sbitlim = itlim;
4387 nsbcalls++;
4388
4389 sbdown = lp->lpobjval;
4390 sbup = lp->lpobjval;
4391
4392 if( integral )
4393 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4394 else
4395 {
4396 assert( ! SCIPsetIsIntegral(set, col->primsol) );
4397 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4398 }
4399
4400 /* check return code for errors */
4401 if( retcode == SCIP_LPERROR )
4402 {
4403 *lperror = TRUE;
4404 sbdown = SCIP_INVALID;
4405 sbup = SCIP_INVALID;
4406 sbdownvalid = FALSE;
4407 sbupvalid = FALSE;
4408 validsblp = -1;
4409 sbsolval = SCIP_INVALID;
4410 sblpobjval = SCIP_INVALID;
4411 sbnode = -1;
4412 }
4413 else
4414 {
4415 SCIP_Real looseobjval;
4416
4417 *lperror = FALSE;
4418 SCIP_CALL( retcode );
4419
4420 looseobjval = getFiniteLooseObjval(lp, set, prob);
4421 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4422 sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4423
4424 /* update strong branching statistics */
4425 if( updatestat )
4426 {
4427 if( iter == -1 )
4428 {
4429 /* calculate average iteration number */
4430 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4431 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4432 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4433 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4434 : 0;
4435 if( iter/2 >= itlim )
4436 iter = 2*itlim;
4437 }
4438 SCIPstatIncrement(stat, set, nstrongbranchs);
4439 SCIPstatAdd(stat, set, nsblpiterations, iter);
4440 if( stat->nnodes == 1 )
4441 {
4442 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4443 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4444 }
4445 }
4446 }
4447
4448 /* stop timing */
4450 }
4451 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/
4452 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/
4453
4454 if( down != NULL)
4455 *down = sbdown;
4456 if( up != NULL )
4457 *up = sbup;
4458 if( downvalid != NULL )
4459 *downvalid = sbdownvalid;
4460 if( upvalid != NULL )
4461 *upvalid = sbupvalid;
4462
4463 if( updatecol )
4464 {
4465 col->sbdown = sbdown;
4466 col->sbup = sbup;
4467 col->sbdownvalid = sbdownvalid;
4468 col->sbupvalid = sbupvalid;
4469 col->validsblp = validsblp;
4470 col->sbsolval = sbsolval;
4471 col->sblpobjval = sblpobjval;
4472 col->sbnode = sbnode;
4473 col->sbitlim = sbitlim;
4474 col->nsbcalls = nsbcalls;
4475 }
4476
4477 return SCIP_OKAY;
4478}
4479
4480/** gets strong branching information on column variables */
4482 SCIP_COL** cols, /**< LP columns */
4483 int ncols, /**< number of columns */
4484 SCIP_Bool integral, /**< should integral strong branching be performed? */
4485 SCIP_SET* set, /**< global SCIP settings */
4486 SCIP_STAT* stat, /**< dynamic problem statistics */
4487 SCIP_PROB* prob, /**< problem data */
4488 SCIP_LP* lp, /**< LP data */
4489 int itlim, /**< iteration limit for strong branchings */
4490 SCIP_Real* down, /**< stores dual bounds after branching columns down */
4491 SCIP_Real* up, /**< stores dual bounds after branching columns up */
4492 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4493 * otherwise, they can only be used as an estimate value */
4494 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4495 * otherwise, they can only be used as an estimate value */
4496 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4497 )
4498{
4499 SCIP_RETCODE retcode;
4500 SCIP_Real* sbdown;
4501 SCIP_Real* sbup;
4502 SCIP_Bool* sbdownvalid;
4503 SCIP_Bool* sbupvalid;
4504 SCIP_Real* primsols;
4505 SCIP_COL** subcols;
4506 int* lpipos;
4507 int* subidx;
4508 int nsubcols;
4509 int iter;
4510 int j;
4511
4512 assert(cols != NULL);
4513 assert(set != NULL);
4514 assert(stat != NULL);
4515 assert(lp != NULL);
4516 assert(lp->flushed);
4517 assert(lp->solved);
4518 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4519 assert(lp->validsollp == stat->lpcount);
4520 assert(itlim >= 1);
4521 assert(down != NULL);
4522 assert(up != NULL);
4523 assert(lperror != NULL);
4524
4525 *lperror = FALSE;
4526
4527 if ( ncols <= 0 )
4528 return SCIP_OKAY;
4529
4530 /* start timing */
4532
4533 /* initialize storage */
4534 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4535 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4536 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4541 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4542
4543 nsubcols = 0;
4544 for( j = 0; j < ncols; ++j )
4545 {
4546 SCIP_COL* col;
4547 col = cols[j];
4548
4549 assert(col->lppos < lp->ncols);
4550 assert(lp->cols[col->lppos] == col);
4551 assert(SCIPcolIsIntegral(col));
4552 assert(SCIPvarIsIntegral(col->var));
4554 assert(SCIPvarGetCol(col->var) == col);
4555 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4556 assert(col->lpipos >= 0);
4557 assert(col->lppos >= 0);
4558
4559 col->validsblp = stat->nlps;
4560 col->sbsolval = col->primsol;
4561 col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4562 col->sbnode = stat->nnodes;
4563 assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4564
4565 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4566 if( lp->looseobjvalinf > 0 )
4567 {
4568 /* directly set up column and result vectors*/
4569 col->sbdown = -SCIPsetInfinity(set);
4570 col->sbup = -SCIPsetInfinity(set);
4571 col->sbdownvalid = FALSE;
4572 col->sbupvalid = FALSE;
4573 down[j] = col->sbdown;
4574 up[j] = col->sbup;
4575 if( downvalid != NULL )
4576 downvalid[j] = col->sbdownvalid;
4577 if( upvalid != NULL )
4578 upvalid[j] = col->sbupvalid;
4579 }
4580 else
4581 {
4582 col->sbitlim = itlim;
4583 col->nsbcalls++;
4584
4585 lpipos[nsubcols] = col->lpipos;
4586 primsols[nsubcols] = col->primsol;
4587 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4588 subidx[nsubcols] = j;
4589 subcols[nsubcols++] = col;
4590 }
4591 }
4592
4593 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4594
4595 /* call LPI strong branching */
4596 if ( integral )
4597 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4598 else
4599 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4600
4601 /* check return code for errors */
4602 if( retcode == SCIP_LPERROR )
4603 {
4604 *lperror = TRUE;
4605
4606 for( j = 0; j < nsubcols; ++j )
4607 {
4608 SCIP_COL* col;
4609 int idx;
4610
4611 col = subcols[j];
4612 idx = subidx[j];
4613
4614 col->sbdown = SCIP_INVALID;
4615 col->sbup = SCIP_INVALID;
4616 col->sbdownvalid = FALSE;
4617 col->sbupvalid = FALSE;
4618 col->validsblp = -1;
4619 col->sbsolval = SCIP_INVALID;
4620 col->sblpobjval = SCIP_INVALID;
4621 col->sbnode = -1;
4622
4623 down[idx] = col->sbdown;
4624 up[idx] = col->sbup;
4625 if( downvalid != NULL )
4626 downvalid[idx] = col->sbdownvalid;
4627 if( upvalid != NULL )
4628 upvalid[idx] = col->sbupvalid;
4629 }
4630 }
4631 else
4632 {
4633 SCIP_Real looseobjval;
4634
4635 *lperror = FALSE;
4636 SCIP_CALL( retcode );
4637
4638 looseobjval = getFiniteLooseObjval(lp, set, prob);
4639
4640 for( j = 0; j < nsubcols; ++j )
4641 {
4642 SCIP_COL* col;
4643 int idx;
4644
4645 col = subcols[j];
4646 idx = subidx[j];
4647
4648 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/
4649 assert( col->sbup != SCIP_INVALID); /*lint !e777*/
4650
4651 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4652 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4653 col->sbdownvalid = sbdownvalid[j];
4654 col->sbupvalid = sbupvalid[j];
4655
4656 down[idx] = col->sbdown;
4657 up[idx] = col->sbup;
4658 if( downvalid != NULL )
4659 downvalid[idx] = col->sbdownvalid;
4660 if( upvalid != NULL )
4661 upvalid[idx] = col->sbupvalid;
4662 }
4663
4664 /* update strong branching statistics */
4665 if( iter == -1 )
4666 {
4667 /* calculate average iteration number */
4668 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4669 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4670 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4671 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4672 : 0;
4673 if( iter/2 >= itlim )
4674 iter = 2*itlim;
4675 }
4676 SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4677 SCIPstatAdd(stat, set, nsblpiterations, iter);
4678 if( stat->nnodes == 1 )
4679 {
4680 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4681 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4682 }
4683 }
4684
4685 SCIPsetFreeBufferArray(set, &sbupvalid);
4686 SCIPsetFreeBufferArray(set, &sbdownvalid);
4688 SCIPsetFreeBufferArray(set, &sbdown);
4689 SCIPsetFreeBufferArray(set, &primsols);
4690 SCIPsetFreeBufferArray(set, &lpipos);
4691 SCIPsetFreeBufferArray(set, &subidx);
4692 SCIPsetFreeBufferArray(set, &subcols);
4693
4694 /* stop timing */
4696
4697 return SCIP_OKAY;
4698}
4699
4700/** gets last strong branching information available for a column variable;
4701 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4702 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4703 */
4705 SCIP_COL* col, /**< LP column */
4706 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4707 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4708 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4709 * otherwise, it can only be used as an estimate value */
4710 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4711 * otherwise, it can only be used as an estimate value */
4712 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4713 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4714 )
4715{
4716 assert(col != NULL);
4717
4718 if( down != NULL )
4719 *down = col->sbdown;
4720 if( up != NULL )
4721 *up = col->sbup;
4722 if( downvalid != NULL )
4723 *downvalid = col->sbdownvalid;
4724 if( upvalid != NULL )
4725 *upvalid = col->sbupvalid;
4726 if( solval != NULL )
4727 *solval = col->sbsolval;
4728 if( lpobjval != NULL )
4729 *lpobjval = col->sblpobjval;
4730}
4731
4732/** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4733 * the LP where the strong branching on this column was applied;
4734 * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4735 */
4737 SCIP_COL* col, /**< LP column */
4738 SCIP_STAT* stat /**< dynamic problem statistics */
4739 )
4740{
4741 assert(col != NULL);
4742 assert(stat != NULL);
4743
4744 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4745}
4746
4747/** marks a column to be not removable from the LP in the current node because it became obsolete */
4749 SCIP_COL* col, /**< LP column */
4750 SCIP_STAT* stat /**< problem statistics */
4751 )
4752{
4753 assert(col != NULL);
4754 assert(stat != NULL);
4755 assert(stat->nnodes > 0);
4756
4757 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4758 col->obsoletenode = stat->nnodes;
4759}
4760
4761
4762/*
4763 * Row methods
4764 */
4765
4766/** calculates row norms and min/maxidx from scratch, and checks for sorting */
4767static
4769 SCIP_ROW* row, /**< LP row */
4770 SCIP_SET* set /**< global SCIP settings */
4771 )
4772{
4773 int i;
4774
4775 assert(row != NULL);
4776 assert(set != NULL);
4777
4778 row->sqrnorm = 0.0;
4779 row->sumnorm = 0.0;
4780 row->objprod = 0.0;
4781 row->maxval = 0.0;
4782 row->nummaxval = 1;
4783 row->minval = SCIPsetInfinity(set);
4784 row->numminval = 1;
4785 row->minidx = INT_MAX;
4786 row->maxidx = INT_MIN;
4787 row->validminmaxidx = TRUE;
4788 row->lpcolssorted = TRUE;
4789 row->nonlpcolssorted = TRUE;
4790
4791 /* check, if row is sorted
4792 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4793 */
4794 for( i = 0; i < row->nlpcols; ++i )
4795 {
4796 assert(row->cols[i] != NULL);
4797 assert(!SCIPsetIsZero(set, row->vals[i]));
4798 assert(row->cols[i]->lppos >= 0);
4799 assert(row->linkpos[i] >= 0);
4800 assert(row->cols[i]->index == row->cols_index[i]);
4801
4802 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4803 if( i > 0 )
4804 {
4805 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4806 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4807 }
4808 }
4809 for( i = row->nlpcols; i < row->len; ++i )
4810 {
4811 assert(row->cols[i] != NULL);
4812 assert(!SCIPsetIsZero(set, row->vals[i]));
4813 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4814 assert(row->cols[i]->index == row->cols_index[i]);
4815
4816 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4817 if( i > row->nlpcols )
4818 {
4819 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4820 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4821 }
4822 }
4823}
4824
4825/** calculates min/maxval and min/maxidx from scratch */
4826static
4828 SCIP_ROW* row, /**< LP row */
4829 SCIP_SET* set /**< global SCIP settings */
4830 )
4831{
4832 SCIP_COL* col;
4833 SCIP_Real absval;
4834 int i;
4835
4836 assert(row != NULL);
4837 assert(set != NULL);
4838
4839 row->maxval = 0.0;
4840 row->nummaxval = 1;
4841 row->numintcols = 0;
4842 row->minval = SCIPsetInfinity(set);
4843 row->numminval = 1;
4844 row->minidx = INT_MAX;
4845 row->maxidx = INT_MIN;
4846 row->validminmaxidx = TRUE;
4847
4848 /* calculate maxval, minval, minidx, and maxidx */
4849 for( i = 0; i < row->len; ++i )
4850 {
4851 col = row->cols[i];
4852 assert(col != NULL);
4853 assert(!SCIPsetIsZero(set, row->vals[i]));
4854
4855 absval = REALABS(row->vals[i]);
4856 assert(!SCIPsetIsZero(set, absval));
4857
4858 /* update min/maxidx */
4859 row->minidx = MIN(row->minidx, col->index);
4860 row->maxidx = MAX(row->maxidx, col->index);
4861 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4862
4863 /* update maximal and minimal non-zero value */
4864 if( row->nummaxval > 0 )
4865 {
4866 if( SCIPsetIsGT(set, absval, row->maxval) )
4867 {
4868 row->maxval = absval;
4869 row->nummaxval = 1;
4870 }
4871 else if( SCIPsetIsGE(set, absval, row->maxval) )
4872 {
4873 /* make sure the maxval is always exactly the same */
4874 row->maxval = MAX(absval, row->maxval);
4875 row->nummaxval++;
4876 }
4877 }
4878 if( row->numminval > 0 )
4879 {
4880 if( SCIPsetIsLT(set, absval, row->minval) )
4881 {
4882 row->minval = absval;
4883 row->numminval = 1;
4884 }
4885 else if( SCIPsetIsLE(set, absval, row->minval) )
4886 {
4887 /* make sure the minval is always exactly the same */
4888 row->minval = MIN(absval, row->minval);
4889 row->numminval++;
4890 }
4891 }
4892 }
4893}
4894
4895/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4896static
4898 SCIP_Real val, /**< value that should be scaled to an integral value */
4899 SCIP_Real scalar, /**< scalar that should be tried */
4900 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4901 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4902 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4903 )
4904{
4905 SCIP_Real sval;
4906 SCIP_Real downval;
4907 SCIP_Real upval;
4908
4909 assert(mindelta <= 0.0);
4910 assert(maxdelta >= 0.0);
4911
4912 sval = val * scalar;
4913 downval = floor(sval);
4914 upval = ceil(sval);
4915
4916 if( SCIPrelDiff(sval, downval) <= maxdelta )
4917 {
4918 if( intval != NULL )
4919 *intval = downval;
4920 return TRUE;
4921 }
4922 else if( SCIPrelDiff(sval, upval) >= mindelta )
4923 {
4924 if( intval != NULL )
4925 *intval = upval;
4926 return TRUE;
4927 }
4928
4929 return FALSE;
4930}
4931
4932/** scales row with given factor, and rounds coefficients to integers if close enough;
4933 * the constant is automatically moved to the sides;
4934 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4935 */
4936static
4938 SCIP_ROW* row, /**< LP row */
4939 BMS_BLKMEM* blkmem, /**< block memory */
4940 SCIP_SET* set, /**< global SCIP settings */
4941 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4942 SCIP_STAT* stat, /**< problem statistics */
4943 SCIP_LP* lp, /**< current LP data */
4944 SCIP_Real scaleval, /**< value to scale row with */
4945 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4946 * if they are close to integral values? */
4947 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4948 * upto which the integral is used instead of the scaled real coefficient */
4949 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4950 * upto which the integral is used instead of the scaled real coefficient */
4951 )
4952{
4953 SCIP_COL* col;
4954 SCIP_Real val;
4955 SCIP_Real newval;
4956 SCIP_Real intval;
4957 SCIP_Real mindelta;
4958 SCIP_Real maxdelta;
4959 SCIP_Real lb;
4960 SCIP_Real ub;
4961 SCIP_Bool mindeltainf;
4962 SCIP_Bool maxdeltainf;
4963 int oldlen;
4964 int c;
4965
4966 assert(row != NULL);
4967 assert(row->len == 0 || row->cols != NULL);
4968 assert(row->len == 0 || row->vals != NULL);
4969 assert(SCIPsetIsPositive(set, scaleval));
4970 assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4971 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4972
4973 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4974
4975 mindelta = 0.0;
4976 maxdelta = 0.0;
4977 mindeltainf = FALSE;
4978 maxdeltainf = FALSE;
4979 oldlen = row->len;
4980
4981 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4982 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4983 * this rounding can lead to
4984 */
4985 row->integral = TRUE;
4986
4987 c = 0;
4988 while( c < row->len )
4989 {
4990 col = row->cols[c];
4991 val = row->vals[c];
4992 assert(!SCIPsetIsZero(set, val));
4993
4994 /* get local or global bounds for column, depending on the local or global feasibility of the row */
4995 if( row->local )
4996 {
4997 lb = col->lb;
4998 ub = col->ub;
4999 }
5000 else
5001 {
5002 lb = SCIPvarGetLbGlobal(col->var);
5003 ub = SCIPvarGetUbGlobal(col->var);
5004 }
5005
5006 /* calculate scaled coefficient */
5007 newval = val * scaleval;
5008 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5009 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5010 {
5011 if( !SCIPsetIsEQ(set, intval, newval) )
5012 {
5013 if( intval < newval )
5014 {
5015 mindelta += (intval - newval)*ub;
5016 maxdelta += (intval - newval)*lb;
5017 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5018 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5019 }
5020 else
5021 {
5022 mindelta += (intval - newval)*lb;
5023 maxdelta += (intval - newval)*ub;
5024 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5025 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5026 }
5027 }
5028 newval = intval;
5029 }
5030
5031 if( !SCIPsetIsEQ(set, val, newval) )
5032 {
5033 /* if column knows of the row, change the corresponding coefficient in the column */
5034 if( row->linkpos[c] >= 0 )
5035 {
5036 assert(col->rows[row->linkpos[c]] == row);
5037 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5038 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5039 }
5040
5041 /* change the coefficient in the row, and update the norms and integrality status */
5042 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5043
5044 /* current coefficient has been deleted from the row because it was almost zero */
5045 if( oldlen != row->len )
5046 {
5047 assert(row->len == oldlen - 1);
5048 c--;
5049 oldlen = row->len;
5050 }
5051 }
5052 else
5053 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5054
5055 ++c;
5056 }
5057
5058 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5059 * to not destroy feasibility due to rounding
5060 */
5061 /**@todo ensure that returned cut does not have infinite lhs and rhs */
5062 if( !SCIPsetIsInfinity(set, -row->lhs) )
5063 {
5064 if( mindeltainf )
5065 newval = -SCIPsetInfinity(set);
5066 else
5067 {
5068 newval = (row->lhs - row->constant) * scaleval + mindelta;
5069 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5070 newval = SCIPsetSumCeil(set, newval);
5071 }
5072 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5073 }
5074 if( !SCIPsetIsInfinity(set, row->rhs) )
5075 {
5076 if( maxdeltainf )
5077 newval = SCIPsetInfinity(set);
5078 else
5079 {
5080 newval = (row->rhs - row->constant) * scaleval + maxdelta;
5081 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5082 newval = SCIPsetSumFloor(set, newval);
5083 }
5084 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5085 }
5086
5087 /* clear the row constant */
5088 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5089
5090 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5091 debugRowPrint(set, row);
5092
5093#ifdef SCIP_DEBUG
5094 /* check integrality status of row */
5095 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5096 {}
5097 assert(row->integral == (c == row->len));
5098#endif
5099
5100 /* invalid the activity */
5101 row->validactivitylp = -1;
5102
5103 return SCIP_OKAY;
5104}
5105
5106/** creates and captures an LP row */
5108 SCIP_ROW** row, /**< pointer to LP row data */
5109 BMS_BLKMEM* blkmem, /**< block memory */
5110 SCIP_SET* set, /**< global SCIP settings */
5111 SCIP_STAT* stat, /**< problem statistics */
5112 const char* name, /**< name of row */
5113 int len, /**< number of nonzeros in the row */
5114 SCIP_COL** cols, /**< array with columns of row entries */
5115 SCIP_Real* vals, /**< array with coefficients of row entries */
5116 SCIP_Real lhs, /**< left hand side of row */
5117 SCIP_Real rhs, /**< right hand side of row */
5118 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
5119 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5120 SCIP_Bool local, /**< is row only valid locally? */
5121 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
5122 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
5123 )
5124{
5125 assert(row != NULL);
5126 assert(blkmem != NULL);
5127 assert(stat != NULL);
5128 assert(len >= 0);
5129 assert(len == 0 || (cols != NULL && vals != NULL));
5130 /* note, that the assert tries to avoid numerical troubles in the LP solver.
5131 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5132 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5133 */
5134 assert(lhs <= rhs);
5135
5136 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5137
5138 (*row)->integral = TRUE;
5139 if( len > 0 )
5140 {
5141 SCIP_VAR* var;
5142 int i;
5143
5144 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5145 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5146 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5147 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5148
5149 for( i = 0; i < len; ++i )
5150 {
5151 assert(cols[i] != NULL);
5152 assert(!SCIPsetIsZero(set, vals[i]));
5153
5154 var = cols[i]->var;
5155 (*row)->cols_index[i] = cols[i]->index;
5156 (*row)->linkpos[i] = -1;
5157 if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5158 {
5159 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5160 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5161 }
5162 else
5163 {
5164 (*row)->integral = FALSE;
5165 }
5166 }
5167 }
5168 else
5169 {
5170 (*row)->cols = NULL;
5171 (*row)->cols_index = NULL;
5172 (*row)->vals = NULL;
5173 (*row)->linkpos = NULL;
5174 }
5175
5176 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5177 (*row)->constant = 0.0;
5178 (*row)->lhs = lhs;
5179 (*row)->rhs = rhs;
5180 (*row)->flushedlhs = -SCIPsetInfinity(set);
5181 (*row)->flushedrhs = SCIPsetInfinity(set);
5182 (*row)->sqrnorm = 0.0;
5183 (*row)->sumnorm = 0.0;
5184 (*row)->objprod = 0.0;
5185 (*row)->maxval = 0.0;
5186 (*row)->minval = SCIPsetInfinity(set);
5187 (*row)->dualsol = 0.0;
5188 (*row)->activity = SCIP_INVALID;
5189 (*row)->dualfarkas = 0.0;
5190 (*row)->pseudoactivity = SCIP_INVALID;
5191 (*row)->minactivity = SCIP_INVALID;
5192 (*row)->maxactivity = SCIP_INVALID;
5193 (*row)->origin = origin;
5194 (*row)->eventfilter = NULL;
5195 (*row)->index = stat->nrowidx;
5196 SCIPstatIncrement(stat, set, nrowidx);
5197 (*row)->size = len;
5198 (*row)->len = len;
5199 (*row)->nlpcols = 0;
5200 (*row)->nunlinked = len;
5201 (*row)->nuses = 0;
5202 (*row)->lppos = -1;
5203 (*row)->lpipos = -1;
5204 (*row)->lpdepth = -1;
5205 (*row)->minidx = INT_MAX;
5206 (*row)->maxidx = INT_MIN;
5207 (*row)->nummaxval = 0;
5208 (*row)->numminval = 0;
5209 (*row)->numintcols = -1;
5210 (*row)->validactivitylp = -1;
5211 (*row)->validpsactivitydomchg = -1;
5212 (*row)->validactivitybdsdomchg = -1;
5213 (*row)->nlpsaftercreation = 0L;
5214 (*row)->activeinlpcounter = 0L;
5215 (*row)->age = 0;
5216 (*row)->rank = 0;
5217 (*row)->obsoletenode = -1;
5218 (*row)->fromcutpool = FALSE;
5219 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5220 (*row)->lpcolssorted = TRUE;
5221 (*row)->nonlpcolssorted = (len <= 1);
5222 (*row)->delaysort = FALSE;
5223 (*row)->validminmaxidx = FALSE;
5224 (*row)->lhschanged = FALSE;
5225 (*row)->rhschanged = FALSE;
5226 (*row)->coefchanged = FALSE;
5227 (*row)->local = local;
5228 (*row)->modifiable = modifiable;
5229 (*row)->nlocks = 0;
5230 (*row)->origintype = origintype; /*lint !e641*/
5231 (*row)->removable = removable;
5232 (*row)->inglobalcutpool = FALSE;
5233 (*row)->storedsolvals = NULL;
5234
5235 /* calculate row norms and min/maxidx, and check if row is sorted */
5236 rowCalcNorms(*row, set);
5237
5238 /* capture the row */
5239 SCIProwCapture(*row);
5240
5241 /* create event filter */
5242 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5243
5244 /* capture origin constraint if available */
5245 if( origintype == SCIP_ROWORIGINTYPE_CONS )
5246 {
5247 SCIP_CONS* cons = (SCIP_CONS*) origin;
5248 assert(cons != NULL);
5249 SCIPconsCapture(cons);
5250 }
5251
5252 return SCIP_OKAY;
5253} /*lint !e715*/
5254
5255/** frees an LP row */
5257 SCIP_ROW** row, /**< pointer to LP row */
5258 BMS_BLKMEM* blkmem, /**< block memory */
5259 SCIP_SET* set, /**< global SCIP settings */
5260 SCIP_LP* lp /**< current LP data */
5261 )
5262{
5263 assert(blkmem != NULL);
5264 assert(row != NULL);
5265 assert(*row != NULL);
5266 assert((*row)->nuses == 0);
5267 assert((*row)->lppos == -1);
5268 assert((*row)->eventfilter != NULL);
5269
5270 /* release constraint that has been used for creating the row */
5271 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5272 {
5273 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5274 assert(cons != NULL);
5275 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5276 }
5277
5278 /* remove column indices from corresponding rows */
5279 SCIP_CALL( rowUnlink(*row, set, lp) );
5280
5281 /* free event filter */
5282 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5283
5284 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5285 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5286 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5287 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5288 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5289 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5290 BMSfreeBlockMemory(blkmem, row);
5291
5292 return SCIP_OKAY;
5293}
5294
5295/** output row to file stream */
5297 SCIP_ROW* row, /**< LP row */
5298 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5299 FILE* file /**< output file (or NULL for standard output) */
5300 )
5301{
5302 int i;
5303
5304 assert(row != NULL);
5305
5306 /* print row name */
5307 if( row->name != NULL && row->name[0] != '\0' )
5308 {
5309 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5310 }
5311
5312 /* print left hand side */
5313 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5314
5315 /* print coefficients */
5316 if( row->len == 0 )
5317 SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5318 for( i = 0; i < row->len; ++i )
5319 {
5320 assert(row->cols[i] != NULL);
5321 assert(row->cols[i]->var != NULL);
5322 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5323 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5324 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5325 }
5326
5327 /* print constant */
5329 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5330
5331 /* print right hand side */
5332 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5333}
5334
5335/** increases usage counter of LP row */
5337 SCIP_ROW* row /**< LP row */
5338 )
5339{
5340 assert(row != NULL);
5341 assert(row->nuses >= 0);
5342 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5343
5344 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5345 row->nuses++;
5346}
5347
5348/** decreases usage counter of LP row, and frees memory if necessary */
5350 SCIP_ROW** row, /**< pointer to LP row */
5351 BMS_BLKMEM* blkmem, /**< block memory */
5352 SCIP_SET* set, /**< global SCIP settings */
5353 SCIP_LP* lp /**< current LP data */
5354 )
5355{
5356 assert(blkmem != NULL);
5357 assert(row != NULL);
5358 assert(*row != NULL);
5359 assert((*row)->nuses >= 1);
5360 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5361
5362 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5363 (*row)->nuses--;
5364 if( (*row)->nuses == 0 )
5365 {
5366 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5367 }
5368
5369 *row = NULL;
5370
5371 return SCIP_OKAY;
5372}
5373
5374/** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5376 SCIP_ROW* row /**< LP row */
5377 )
5378{
5379 assert(row != NULL);
5380
5381 /* check, if row is modifiable */
5382 if( !row->modifiable )
5383 {
5384 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5385 row->nlocks++;
5386 }
5387}
5388
5389/** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5391 SCIP_ROW* row /**< LP row */
5392 )
5393{
5394 assert(row != NULL);
5395
5396 /* check, if row is modifiable */
5397 if( !row->modifiable )
5398 {
5399 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5400 assert(row->nlocks > 0);
5401 row->nlocks--;
5402 }
5403}
5404
5405/** adds a previously non existing coefficient to an LP row */
5407 SCIP_ROW* row, /**< LP row */
5408 BMS_BLKMEM* blkmem, /**< block memory */
5409 SCIP_SET* set, /**< global SCIP settings */
5410 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5411 SCIP_LP* lp, /**< current LP data */
5412 SCIP_COL* col, /**< LP column */
5413 SCIP_Real val /**< value of coefficient */
5414 )
5415{
5416 assert(lp != NULL);
5417 assert(!lp->diving || row->lppos == -1);
5418
5419 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5420
5421 checkLinks(lp);
5422
5423 return SCIP_OKAY;
5424}
5425
5426/** deletes coefficient from row */
5428 SCIP_ROW* row, /**< row to be changed */
5429 BMS_BLKMEM* blkmem, /**< block memory */
5430 SCIP_SET* set, /**< global SCIP settings */
5431 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5432 SCIP_LP* lp, /**< current LP data */
5433 SCIP_COL* col /**< coefficient to be deleted */
5434 )
5435{
5436 int pos;
5437
5438 assert(row != NULL);
5439 assert(!row->delaysort);
5440 assert(lp != NULL);
5441 assert(!lp->diving || row->lppos == -1);
5442 assert(col != NULL);
5443 assert(col->var != NULL);
5444
5445 /* search the position of the column in the row's col vector */
5446 pos = rowSearchCoef(row, col);
5447 if( pos == -1 )
5448 {
5449 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5450 return SCIP_INVALIDDATA;
5451 }
5452 assert(0 <= pos && pos < row->len);
5453 assert(row->cols[pos] == col);
5454 assert(row->cols_index[pos] == col->index);
5455
5456 /* if column knows of the row, remove the row from the column's row vector */
5457 if( row->linkpos[pos] >= 0 )
5458 {
5459 assert(col->rows[row->linkpos[pos]] == row);
5460 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5461 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5462 }
5463
5464 /* delete the column from the row's col vector */
5465 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5466
5467 checkLinks(lp);
5468
5469 return SCIP_OKAY;
5470}
5471
5472/** changes or adds a coefficient to an LP row */
5474 SCIP_ROW* row, /**< LP row */
5475 BMS_BLKMEM* blkmem, /**< block memory */
5476 SCIP_SET* set, /**< global SCIP settings */
5477 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5478 SCIP_LP* lp, /**< current LP data */
5479 SCIP_COL* col, /**< LP column */
5480 SCIP_Real val /**< value of coefficient */
5481 )
5482{
5483 int pos;
5484
5485 assert(row != NULL);
5486 assert(!row->delaysort);
5487 assert(lp != NULL);
5488 assert(!lp->diving || row->lppos == -1);
5489 assert(col != NULL);
5490
5491 /* search the position of the column in the row's col vector */
5492 pos = rowSearchCoef(row, col);
5493
5494 /* check, if column already exists in the row's col vector */
5495 if( pos == -1 )
5496 {
5497 /* add previously not existing coefficient */
5498 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5499 }
5500 else
5501 {
5502 /* modify already existing coefficient */
5503 assert(0 <= pos && pos < row->len);
5504 assert(row->cols[pos] == col);
5505 assert(row->cols_index[pos] == col->index);
5506
5507 /* if column knows of the row, change the corresponding coefficient in the column */
5508 if( row->linkpos[pos] >= 0 )
5509 {
5510 assert(col->rows[row->linkpos[pos]] == row);
5511 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5512 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5513 }
5514
5515 /* change the coefficient in the row */
5516 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5517 }
5518
5519 checkLinks(lp);
5520
5521 return SCIP_OKAY;
5522}
5523
5524/** increases value of an existing or non-existing coefficient in an LP row */
5526 SCIP_ROW* row, /**< LP row */
5527 BMS_BLKMEM* blkmem, /**< block memory */
5528 SCIP_SET* set, /**< global SCIP settings */
5529 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5530 SCIP_LP* lp, /**< current LP data */
5531 SCIP_COL* col, /**< LP column */
5532 SCIP_Real incval /**< value to add to the coefficient */
5533 )
5534{
5535 int pos;
5536
5537 assert(row != NULL);
5538 assert(lp != NULL);
5539 assert(!lp->diving || row->lppos == -1);
5540 assert(col != NULL);
5541
5542 if( SCIPsetIsZero(set, incval) )
5543 return SCIP_OKAY;
5544
5545 /* search the position of the column in the row's col vector */
5546 pos = rowSearchCoef(row, col);
5547
5548 /* check, if column already exists in the row's col vector */
5549 if( pos == -1 )
5550 {
5551 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5552 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5553 }
5554 else
5555 {
5556 /* modify already existing coefficient */
5557 assert(0 <= pos && pos < row->len);
5558 assert(row->cols[pos] == col);
5559 assert(row->cols_index[pos] == col->index);
5560
5561 /* if column knows of the row, change the corresponding coefficient in the column */
5562 if( row->linkpos[pos] >= 0 )
5563 {
5564 assert(col->rows[row->linkpos[pos]] == row);
5565 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5566 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5567 }
5568
5569 /* change the coefficient in the row */
5570 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5571 }
5572
5573 checkLinks(lp);
5574
5575 /* invalid the activity */
5576 row->validactivitylp = -1;
5577
5578 return SCIP_OKAY;
5579}
5580
5581/** changes constant value of a row */
5583 SCIP_ROW* row, /**< LP row */
5584 BMS_BLKMEM* blkmem, /**< block memory */
5585 SCIP_SET* set, /**< global SCIP settings */
5586 SCIP_STAT* stat, /**< problem statistics */
5587 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5588 SCIP_LP* lp, /**< current LP data */
5589 SCIP_Real constant /**< new constant value */
5590 )
5591{
5592 assert(row != NULL);
5593 assert(row->lhs <= row->rhs);
5594 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5595 assert(stat != NULL);
5596 assert(lp != NULL);
5597 assert(!lp->diving || row->lppos == -1);
5598
5599 if( !SCIPsetIsEQ(set, constant, row->constant) )
5600 {
5601 SCIP_Real oldconstant;
5602
5603 if( row->validpsactivitydomchg == stat->domchgcount )
5604 {
5605 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
5606 row->pseudoactivity += constant - row->constant;
5607 }
5608 if( row->validactivitybdsdomchg == stat->domchgcount )
5609 {
5610 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
5611 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
5612 row->minactivity += constant - row->constant;
5613 row->maxactivity += constant - row->constant;
5614 }
5615
5616 if( !SCIPsetIsInfinity(set, -row->lhs) )
5617 {
5619 }
5620 if( !SCIPsetIsInfinity(set, row->rhs) )
5621 {
5623 }
5624
5625 oldconstant = row->constant;
5626
5627 row->constant = constant;
5628
5629 /* issue row constant changed event */
5630 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5631 }
5632
5633 return SCIP_OKAY;
5634}
5635
5636/** add constant value to a row */
5638 SCIP_ROW* row, /**< LP row */
5639 BMS_BLKMEM* blkmem, /**< block memory */
5640 SCIP_SET* set, /**< global SCIP settings */
5641 SCIP_STAT* stat, /**< problem statistics */
5642 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5643 SCIP_LP* lp, /**< current LP data */
5644 SCIP_Real addval /**< constant value to add to the row */
5645 )
5646{
5647 assert(row != NULL);
5648 assert(row->lhs <= row->rhs);
5649 assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5650 assert(stat != NULL);
5651 assert(lp != NULL);
5652 assert(!lp->diving || row->lppos == -1);
5653
5654 if( !SCIPsetIsZero(set, addval) )
5655 {
5656 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5657 }
5658
5659 return SCIP_OKAY;
5660}
5661
5662/** changes left hand side of LP row */
5664 SCIP_ROW* row, /**< LP row */
5665 BMS_BLKMEM* blkmem, /**< block memory */
5666 SCIP_SET* set, /**< global SCIP settings */
5667 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5668 SCIP_LP* lp, /**< current LP data */
5669 SCIP_Real lhs /**< new left hand side */
5670 )
5671{
5672 assert(row != NULL);
5673 assert(lp != NULL);
5674
5675 if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5676 {
5677 SCIP_Real oldlhs;
5678
5679 oldlhs = row->lhs;
5680
5681 row->lhs = lhs;
5683
5684 if( !lp->diving )
5685 {
5686 /* issue row side changed event */
5687 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5688 }
5689 }
5690
5691 return SCIP_OKAY;
5692}
5693
5694/** changes right hand side of LP row */
5696 SCIP_ROW* row, /**< LP row */
5697 BMS_BLKMEM* blkmem, /**< block memory */
5698 SCIP_SET* set, /**< global SCIP settings */
5699 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5700 SCIP_LP* lp, /**< current LP data */
5701 SCIP_Real rhs /**< new right hand side */
5702 )
5703{
5704 assert(row != NULL);
5705 assert(lp != NULL);
5706
5707 if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5708 {
5709 SCIP_Real oldrhs;
5710
5711 oldrhs = row->rhs;
5712
5713 row->rhs = rhs;
5715
5716 if( !lp->diving )
5717 {
5718 /* issue row side changed event */
5719 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5720 }
5721 }
5722
5723 return SCIP_OKAY;
5724}
5725
5726/** changes the local flag of LP row */
5728 SCIP_ROW* row, /**< LP row */
5729 SCIP_Bool local /**< new value for local flag */
5730 )
5731{
5732 assert(row != NULL);
5733
5734 row->local = local;
5735
5736 return SCIP_OKAY;
5737}
5738
5739/** additional scalars that are tried in integrality scaling */
5740static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5741static const int nscalars = 9;
5742
5743/** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5745 SCIP_ROW* row, /**< LP row */
5746 SCIP_SET* set, /**< global SCIP settings */
5747 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5748 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5749 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5750 SCIP_Real maxscale, /**< maximal allowed scalar */
5751 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5752 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5753 SCIP_Bool* success /**< stores whether returned value is valid */
5754 )
5755{
5756#ifndef NDEBUG
5757 SCIP_COL* col;
5758#endif
5759 SCIP_Longint gcd;
5760 SCIP_Longint scm;
5761 SCIP_Longint nominator;
5762 SCIP_Longint denominator;
5763 SCIP_Real val;
5764 SCIP_Real absval;
5765 SCIP_Real minval;
5766 SCIP_Real scaleval;
5767 SCIP_Real twomultval;
5768 SCIP_Bool scalable;
5769 SCIP_Bool twomult;
5770 SCIP_Bool rational;
5771 int c;
5772 int s;
5773
5774 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5775 assert(row != NULL);
5776 assert(row->len == 0 || row->cols != NULL);
5777 assert(row->len == 0 || row->cols_index != NULL);
5778 assert(row->len == 0 || row->vals != NULL);
5779 assert(maxdnom >= 1);
5780 assert(mindelta < 0.0);
5781 assert(maxdelta > 0.0);
5782 assert(success != NULL);
5783
5784 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5785 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5786
5787 if( intscalar != NULL )
5788 *intscalar = SCIP_INVALID;
5789 *success = FALSE;
5790
5791 /* get minimal absolute non-zero value */
5792 minval = SCIP_REAL_MAX;
5793 for( c = 0; c < row->len; ++c )
5794 {
5795#ifndef NDEBUG
5796 col = row->cols[c];
5797 assert(col != NULL);
5798 assert(col->var != NULL);
5800 assert(SCIPvarGetCol(col->var) == col);
5801#endif
5802 val = row->vals[c];
5803 assert(!SCIPsetIsZero(set, val));
5804
5805 if( val < mindelta || val > maxdelta )
5806 {
5807 absval = REALABS(val);
5808 minval = MIN(minval, absval);
5809 }
5810 }
5811 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5812 {
5813 /* all coefficients are zero (inside tolerances) */
5814 if( intscalar != NULL )
5815 *intscalar = 1.0;
5816 *success = TRUE;
5817 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5818
5819 return SCIP_OKAY;
5820 }
5821 assert(minval > MIN(-mindelta, maxdelta));
5822 assert(SCIPsetIsPositive(set, minval));
5823 assert(!SCIPsetIsInfinity(set, minval));
5824
5825 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5826 * and a power of 2
5827 */
5828 scaleval = 1.0/minval;
5829 scalable = (scaleval <= maxscale);
5830 for( c = 0; c < row->len && scalable; ++c )
5831 {
5832 /* don't look at continuous variables, if we don't have to */
5833 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5834 continue;
5835
5836 /* check, if the coefficient can be scaled with a simple scalar */
5837 val = row->vals[c];
5838 absval = REALABS(val);
5839 while( scaleval <= maxscale
5840 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5841 {
5842 for( s = 0; s < nscalars; ++s )
5843 {
5844 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5845 {
5846 scaleval *= scalars[s];
5847 break;
5848 }
5849 }
5850 if( s >= nscalars )
5851 scaleval *= 2.0;
5852 }
5853 scalable = (scaleval <= maxscale);
5854 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5855 }
5856 if( scalable )
5857 {
5858 /* make row coefficients integral by dividing them by the smallest coefficient
5859 * (and multiplying them with a power of 2)
5860 */
5861 assert(scaleval <= maxscale);
5862 if( intscalar != NULL )
5863 *intscalar = scaleval;
5864 *success = TRUE;
5865 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5866
5867 return SCIP_OKAY;
5868 }
5869
5870 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5871 twomultval = 1.0;
5872 twomult = (twomultval <= maxscale);
5873 for( c = 0; c < row->len && twomult; ++c )
5874 {
5875 /* don't look at continuous variables, if we don't have to */
5876 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5877 continue;
5878
5879 /* check, if the coefficient can be scaled with a simple scalar */
5880 val = row->vals[c];
5881 absval = REALABS(val);
5882 while( twomultval <= maxscale
5883 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5884 {
5885 for( s = 0; s < nscalars; ++s )
5886 {
5887 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5888 {
5889 twomultval *= scalars[s];
5890 break;
5891 }
5892 }
5893 if( s >= nscalars )
5894 twomultval *= 2.0;
5895 }
5896 twomult = (twomultval <= maxscale);
5897 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5898 val, twomultval, val*twomultval, twomult);
5899 }
5900 if( twomult )
5901 {
5902 /* make row coefficients integral by multiplying them with a power of 2 */
5903 assert(twomultval <= maxscale);
5904 if( intscalar != NULL )
5905 *intscalar = twomultval;
5906 *success = TRUE;
5907 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5908
5909 return SCIP_OKAY;
5910 }
5911
5912 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5913 * and the smallest common multiple of the denominators
5914 */
5915 gcd = 1;
5916 scm = 1;
5917 rational = (maxdnom > 1);
5918
5919 /* first coefficient (to initialize gcd) */
5920 for( c = 0; c < row->len && rational; ++c )
5921 {
5922 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5923 {
5924 val = row->vals[c];
5925 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5926 if( rational && nominator != 0 )
5927 {
5928 assert(denominator > 0);
5929 gcd = ABS(nominator);
5930 scm = denominator;
5931 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5932 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5933 val, nominator, denominator, gcd, scm, rational);
5934 break;
5935 }
5936 }
5937 }
5938
5939 /* remaining coefficients */
5940 for( ++c; c < row->len && rational; ++c )
5941 {
5942 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5943 {
5944 val = row->vals[c];
5945 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
5946 if( rational && nominator != 0 )
5947 {
5948 assert(denominator > 0);
5949 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
5950 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5951 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5952 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5953 val, nominator, denominator, gcd, scm, rational);
5954 }
5955 }
5956 }
5957
5958 if( rational )
5959 {
5960 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5961 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5962 if( intscalar != NULL )
5963 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5964 *success = TRUE;
5965 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5966 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5967 }
5968 else
5969 {
5970 assert(!(*success));
5971 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5972 }
5973
5974 return SCIP_OKAY;
5975}
5976
5977/** tries to scale row, s.t. all coefficients become integral */
5979 SCIP_ROW* row, /**< LP row */
5980 BMS_BLKMEM* blkmem, /**< block memory */
5981 SCIP_SET* set, /**< global SCIP settings */
5982 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5983 SCIP_STAT* stat, /**< problem statistics */
5984 SCIP_LP* lp, /**< current LP data */
5985 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5986 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5987 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5988 SCIP_Real maxscale, /**< maximal value to scale row with */
5989 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5990 SCIP_Bool* success /**< stores whether row could be made rational */
5991 )
5992{
5993 SCIP_Real intscalar;
5994
5995 assert(success != NULL);
5996
5997 /* calculate scalar to make coefficients integral */
5998 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
5999 &intscalar, success) );
6000
6001 if( *success )
6002 {
6003 /* scale the row */
6004 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6005 }
6006
6007 return SCIP_OKAY;
6008}
6009
6010/** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6011 * higher ones
6012 */
6014 SCIP_ROW* row /**< row to be sorted */
6015 )
6016{
6017 assert(row != NULL);
6018
6019 /* sort LP columns */
6020 rowSortLP(row);
6021
6022 /* sort non-LP columns */
6023 rowSortNonLP(row);
6024
6025#ifdef SCIP_MORE_DEBUG
6026 /* check the sorting */
6027 {
6028 int c;
6029 if( !row->delaysort )
6030 {
6031 for( c = 1; c < row->nlpcols; ++c )
6032 assert(row->cols[c]->index >= row->cols[c-1]->index);
6033 for( c = row->nlpcols + 1; c < row->len; ++c )
6034 assert(row->cols[c]->index >= row->cols[c-1]->index);
6035 }
6036 }
6037#endif
6038}
6039
6040/** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6041 * zero entries from row
6042 * the row must not be linked to the columns; otherwise, we would need to update the columns as
6043 * well, which is too expensive
6044 */
6045static
6047 SCIP_ROW* row, /**< row to be sorted */
6048 SCIP_SET* set /**< global SCIP settings */
6049 )
6050{
6051 assert(row != NULL);
6052 assert(!row->delaysort);
6053 assert(row->nunlinked == row->len);
6054 assert(row->nlpcols == 0);
6055
6056 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6057
6058 /* do nothing on empty rows; if row is sorted, nothing has to be done */
6059 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6060 {
6061 SCIP_COL** cols;
6062 int* cols_index;
6063 SCIP_Real* vals;
6064 int s;
6065 int t;
6066
6067 /* make sure, the row is sorted */
6068 SCIProwSort(row);
6069 assert(row->lpcolssorted);
6070 assert(row->nonlpcolssorted);
6071
6072 /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6073 cols = row->cols;
6074 cols_index = row->cols_index;
6075 vals = row->vals;
6076 assert(cols != NULL);
6077 assert(cols_index != NULL);
6078 assert(vals != NULL);
6079
6080 t = 0;
6081 row->integral = TRUE;
6082 assert(!SCIPsetIsZero(set, vals[0]));
6083 assert(row->linkpos[0] == -1);
6084
6085 for( s = 1; s < row->len; ++s )
6086 {
6087 assert(!SCIPsetIsZero(set, vals[s]));
6088 assert(row->linkpos[s] == -1);
6089
6090 if( cols[s] == cols[t] )
6091 {
6092 /* merge entries with equal column */
6093 vals[t] += vals[s];
6094 }
6095 else
6096 {
6097 /* go to the next entry, overwriting current entry if coefficient is zero */
6098 if( !SCIPsetIsZero(set, vals[t]) )
6099 {
6100 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6101 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6102
6103 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6104 t++;
6105 }
6106 cols[t] = cols[s];
6107 cols_index[t] = cols_index[s];
6108 vals[t] = vals[s];
6109 }
6110 }
6111 if( !SCIPsetIsZero(set, vals[t]) )
6112 {
6113 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6114 t++;
6115 }
6116 assert(s == row->len);
6117 assert(t <= row->len);
6118
6119 row->len = t;
6120 row->nunlinked = t;
6121
6122 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6123 if( t < s )
6124 rowCalcNorms(row, set);
6125 }
6126
6127#ifndef NDEBUG
6128 /* check for double entries */
6129 {
6130 int i;
6131 int j;
6132
6133 for( i = 0; i < row->len; ++i )
6134 {
6135 assert(row->cols[i] != NULL);
6136 assert(row->cols[i]->index == row->cols_index[i]);
6137 for( j = i+1; j < row->len; ++j )
6138 assert(row->cols[i] != row->cols[j]);
6139 }
6140 }
6141#endif
6142}
6143
6144/** enables delaying of row sorting */
6146 SCIP_ROW* row /**< LP row */
6147 )
6148{
6149 assert(row != NULL);
6150 assert(!row->delaysort);
6151
6152 row->delaysort = TRUE;
6153}
6154
6155/** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6157 SCIP_ROW* row, /**< LP row */
6158 SCIP_SET* set /**< global SCIP settings */
6159 )
6160{
6161 assert(row != NULL);
6162 assert(row->delaysort);
6163
6164 row->delaysort = FALSE;
6165 rowMerge(row, set);
6166}
6167
6168/** recalculates the current activity of a row */
6170 SCIP_ROW* row, /**< LP row */
6171 SCIP_STAT* stat /**< problem statistics */
6172 )
6173{
6174 SCIP_COL* col;
6175 int c;
6176
6177 assert(row != NULL);
6178 assert(stat != NULL);
6179
6180 row->activity = row->constant;
6181 for( c = 0; c < row->nlpcols; ++c )
6182 {
6183 col = row->cols[c];
6184 assert(col != NULL);
6185 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
6186 assert(col->lppos >= 0);
6187 assert(row->linkpos[c] >= 0);
6188 row->activity += row->vals[c] * col->primsol;
6189 }
6190
6191 if( row->nunlinked > 0 )
6192 {
6193 for( c = row->nlpcols; c < row->len; ++c )
6194 {
6195 col = row->cols[c];
6196 assert(col != NULL);
6197 assert(col->lppos >= 0 || col->primsol == 0.0);
6198 assert(col->lppos == -1 || row->linkpos[c] == -1);
6199 if( col->lppos >= 0 )
6200 row->activity += row->vals[c] * col->primsol;
6201 }
6202 }
6203#ifndef NDEBUG
6204 else
6205 {
6206 for( c = row->nlpcols; c < row->len; ++c )
6207 {
6208 col = row->cols[c];
6209 assert(col != NULL);
6210 assert(col->primsol == 0.0);
6211 assert(col->lppos == -1);
6212 assert(row->linkpos[c] >= 0);
6213 }
6214 }
6215#endif
6216
6217 row->validactivitylp = stat->lpcount;
6218}
6219
6220/** returns the activity of a row in the current LP solution */
6222 SCIP_ROW* row, /**< LP row */
6223 SCIP_SET* set, /**< global SCIP settings */
6224 SCIP_STAT* stat, /**< problem statistics */
6225 SCIP_LP* lp /**< current LP data */
6226 )
6227{
6228 SCIP_Real inf;
6229 SCIP_Real activity;
6230
6231 assert(row != NULL);
6232 assert(stat != NULL);
6233 assert(lp != NULL);
6234 assert(row->validactivitylp <= stat->lpcount);
6235 assert(lp->validsollp == stat->lpcount);
6236
6237 if( row->validactivitylp != stat->lpcount )
6238 SCIProwRecalcLPActivity(row, stat);
6239 assert(row->validactivitylp == stat->lpcount);
6240 assert(row->activity != SCIP_INVALID); /*lint !e777*/
6241
6242 activity = row->activity;
6243 inf = SCIPsetInfinity(set);
6244 activity = MAX(activity, -inf);
6245 activity = MIN(activity, +inf);
6246
6247 return activity;
6248}
6249
6250/** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6252 SCIP_ROW* row, /**< LP row */
6253 SCIP_SET* set, /**< global SCIP settings */
6254 SCIP_STAT* stat, /**< problem statistics */
6255 SCIP_LP* lp /**< current LP data */
6256 )
6257{
6258 SCIP_Real activity;
6259
6260 assert(row != NULL);
6261
6262 activity = SCIProwGetLPActivity(row, set, stat, lp);
6263
6264 return MIN(row->rhs - activity, activity - row->lhs);
6265}
6266
6267/** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6268 *
6269 * @todo Implement calculation of activities similar to LPs.
6270 */
6272 SCIP_ROW* row, /**< LP row */
6273 SCIP_SET* set, /**< global SCIP settings */
6274 SCIP_STAT* stat /**< problem statistics */
6275 )
6276{
6277 SCIP_Real inf;
6278 SCIP_Real activity;
6279 SCIP_COL* col;
6280 int c;
6281
6282 assert( row != NULL );
6283 assert( stat != NULL );
6284
6285 activity = row->constant;
6286 for (c = 0; c < row->nlpcols; ++c)
6287 {
6288 col = row->cols[c];
6289 assert( col != NULL );
6290 assert( col->lppos >= 0 );
6291 assert( col->var != NULL );
6292 assert( row->linkpos[c] >= 0 );
6293 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6294 }
6295
6296 if ( row->nunlinked > 0 )
6297 {
6298 for (c = row->nlpcols; c < row->len; ++c)
6299 {
6300 col = row->cols[c];
6301 assert( col != NULL );
6302 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6303 if ( col->lppos >= 0 )
6304 {
6305 assert( col->var != NULL );
6306 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6307 }
6308 }
6309 }
6310#ifndef NDEBUG
6311 else
6312 {
6313 for (c = row->nlpcols; c < row->len; ++c)
6314 {
6315 col = row->cols[c];
6316 assert( col != NULL );
6317 assert( col->lppos == -1 );
6318 assert( row->linkpos[c] >= 0 );
6319 }
6320 }
6321#endif
6322 inf = SCIPsetInfinity(set);
6323 activity = MAX(activity, -inf);
6324 activity = MIN(activity, +inf);
6325
6326 return MIN(row->rhs - activity, activity - row->lhs);
6327}
6328
6329/** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6330 *
6331 * @todo Implement calculation of activities similar to LPs.
6332 */
6334 SCIP_ROW* row, /**< LP row */
6335 SCIP_SET* set, /**< global SCIP settings */
6336 SCIP_STAT* stat /**< problem statistics */
6337 )
6338{
6339 SCIP_Real inf;
6340 SCIP_Real activity;
6341 SCIP_COL* col;
6342 int c;
6343
6344 assert( row != NULL );
6345 assert( stat != NULL );
6346
6347 activity = row->constant;
6348 for (c = 0; c < row->nlpcols; ++c)
6349 {
6350 col = row->cols[c];
6351 assert( col != NULL );
6352 assert( col->lppos >= 0 );
6353 assert( col->var != NULL );
6354 assert( row->linkpos[c] >= 0 );
6355 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6356 }
6357
6358 if ( row->nunlinked > 0 )
6359 {
6360 for (c = row->nlpcols; c < row->len; ++c)
6361 {
6362 col = row->cols[c];
6363 assert( col != NULL );
6364 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6365 if ( col->lppos >= 0 )
6366 {
6367 assert( col->var != NULL );
6368 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6369 }
6370 }
6371 }
6372#ifndef NDEBUG
6373 else
6374 {
6375 for (c = row->nlpcols; c < row->len; ++c)
6376 {
6377 col = row->cols[c];
6378 assert( col != NULL );
6379 assert( col->lppos == -1 );
6380 assert( row->linkpos[c] >= 0 );
6381 }
6382 }
6383#endif
6384 inf = SCIPsetInfinity(set);
6385 activity = MAX(activity, -inf);
6386 activity = MIN(activity, +inf);
6387
6388 return MIN(row->rhs - activity, activity - row->lhs);
6389}
6390
6391/** calculates the current pseudo activity of a row */
6393 SCIP_ROW* row, /**< row data */
6394 SCIP_STAT* stat /**< problem statistics */
6395 )
6396{
6397 SCIP_COL* col;
6398 int i;
6399
6400 assert(row != NULL);
6401 assert(stat != NULL);
6402
6403 row->pseudoactivity = row->constant;
6404 for( i = 0; i < row->len; ++i )
6405 {
6406 col = row->cols[i];
6407 assert(col != NULL);
6408 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6409 assert(col->var != NULL);
6411
6412 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6413 }
6415 assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6416}
6417
6418/** returns the pseudo activity of a row in the current pseudo solution */
6420 SCIP_ROW* row, /**< LP row */
6421 SCIP_SET* set, /**< global SCIP settings */
6422 SCIP_STAT* stat /**< problem statistics */
6423 )
6424{
6425 SCIP_Real inf;
6426 SCIP_Real activity;
6427
6428 assert(row != NULL);
6429 assert(stat != NULL);
6430 assert(row->validpsactivitydomchg <= stat->domchgcount);
6431
6432 /* check, if pseudo activity has to be calculated */
6433 if( row->validpsactivitydomchg != stat->domchgcount )
6434 SCIProwRecalcPseudoActivity(row, stat);
6435 assert(row->validpsactivitydomchg == stat->domchgcount);
6436 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
6437
6438 activity = row->pseudoactivity;
6439 inf = SCIPsetInfinity(set);
6440 activity = MAX(activity, -inf);
6441 activity = MIN(activity, +inf);
6442
6443 return activity;
6444}
6445
6446/** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6448 SCIP_ROW* row, /**< LP row */
6449 SCIP_SET* set, /**< global SCIP settings */
6450 SCIP_STAT* stat /**< problem statistics */
6451 )
6452{
6453 SCIP_Real pseudoactivity;
6454
6455 assert(row != NULL);
6456
6457 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6458
6459 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6460}
6461
6462/** returns the activity of a row for a given solution */
6464 SCIP_ROW* row, /**< LP row */
6465 SCIP_SET* set, /**< global SCIP settings */
6466 SCIP_STAT* stat, /**< problem statistics data */
6467 SCIP_SOL* sol /**< primal CIP solution */
6468 )
6469{
6470 SCIP_COL* col;
6471 SCIP_Real inf;
6472 SCIP_Real activity;
6473 SCIP_Real solval;
6474 int i;
6475
6476 assert(row != NULL);
6477
6478 activity = row->constant;
6479 for( i = 0; i < row->len; ++i )
6480 {
6481 col = row->cols[i];
6482 assert(col != NULL);
6483 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6484 solval = SCIPsolGetVal(sol, set, stat, col->var);
6485 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6486 {
6487 if( SCIPsetIsInfinity(set, -row->lhs) )
6488 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6489 else if( SCIPsetIsInfinity(set, row->rhs) )
6490 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6491 else
6492 solval = (col->lb + col->ub)/2.0;
6493 }
6494 activity += row->vals[i] * solval;
6495 }
6496
6497 inf = SCIPsetInfinity(set);
6498 activity = MAX(activity, -inf);
6499 activity = MIN(activity, +inf);
6500
6501 return activity;
6502}
6503
6504/** returns the feasibility of a row for the given solution */
6506 SCIP_ROW* row, /**< LP row */
6507 SCIP_SET* set, /**< global SCIP settings */
6508 SCIP_STAT* stat, /**< problem statistics data */
6509 SCIP_SOL* sol /**< primal CIP solution */
6510 )
6511{
6512 SCIP_Real activity;
6513
6514 assert(row != NULL);
6515
6516 activity = SCIProwGetSolActivity(row, set, stat, sol);
6517
6518 return MIN(row->rhs - activity, activity - row->lhs);
6519}
6520
6521/** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6522static
6524 SCIP_ROW* row, /**< row data */
6525 SCIP_SET* set, /**< global SCIP settings */
6526 SCIP_STAT* stat /**< problem statistics data */
6527 )
6528{
6529 SCIP_COL* col;
6530 SCIP_Real val;
6531 SCIP_Bool mininfinite;
6532 SCIP_Bool maxinfinite;
6533 int i;
6534
6535 assert(row != NULL);
6536 assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6537 assert(stat != NULL);
6538
6539 /* calculate activity bounds */
6540 mininfinite = FALSE;
6541 maxinfinite = FALSE;
6542 row->minactivity = row->constant;
6543 row->maxactivity = row->constant;
6544 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6545 {
6546 col = row->cols[i];
6547 assert(col != NULL);
6548 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6549 val = row->vals[i];
6550 if( val >= 0.0 )
6551 {
6552 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6553 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6554 if( !mininfinite )
6555 row->minactivity += val * col->lb;
6556 if( !maxinfinite )
6557 row->maxactivity += val * col->ub;
6558 }
6559 else
6560 {
6561 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6562 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6563 if( !mininfinite )
6564 row->minactivity += val * col->ub;
6565 if( !maxinfinite )
6566 row->maxactivity += val * col->lb;
6567 }
6568 }
6569
6570 if( mininfinite )
6572 if( maxinfinite )
6575
6576#ifndef NDEBUG
6577 {
6578 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6579
6580 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6581 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6582 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6583 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6584 * tolerance as a proxy to account for the accumulation effect
6585 */
6586 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6587 || EPSISINT(row->minactivity - row->constant, inttol));
6588 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6589 || EPSISINT(row->maxactivity - row->constant, inttol));
6590 }
6591#endif
6592}
6593
6594/** returns the minimal activity of a row w.r.t. the columns' bounds */
6596 SCIP_ROW* row, /**< LP row */
6597 SCIP_SET* set, /**< global SCIP settings */
6598 SCIP_STAT* stat /**< problem statistics data */
6599 )
6600{
6601 assert(row != NULL);
6602 assert(stat != NULL);
6603 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6604
6605 /* check, if activity bounds has to be calculated */
6606 if( row->validactivitybdsdomchg != stat->domchgcount )
6607 rowCalcActivityBounds(row, set, stat);
6608 assert(row->validactivitybdsdomchg == stat->domchgcount);
6609 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6610 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6611
6612 return row->minactivity;
6613}
6614
6615/** returns the maximal activity of a row w.r.t. the columns' bounds */
6617 SCIP_ROW* row, /**< LP row */
6618 SCIP_SET* set, /**< global SCIP settings */
6619 SCIP_STAT* stat /**< problem statistics data */
6620 )
6621{
6622 assert(row != NULL);
6623 assert(stat != NULL);
6624 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6625
6626 /* check, if activity bounds has to be calculated */
6627 if( row->validactivitybdsdomchg != stat->domchgcount )
6628 rowCalcActivityBounds(row, set, stat);
6629 assert(row->validactivitybdsdomchg == stat->domchgcount);
6630 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6631 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6632
6633 return row->maxactivity;
6634}
6635
6636/** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6638 SCIP_ROW* row, /**< LP row */
6639 SCIP_SET* set, /**< global SCIP settings */
6640 SCIP_STAT* stat /**< problem statistics data */
6641 )
6642{
6643 assert(row != NULL);
6644
6645 if( row->modifiable )
6646 return FALSE;
6647 if( !SCIPsetIsInfinity(set, -row->lhs) )
6648 {
6649 SCIP_Real minactivity;
6650
6651 minactivity = SCIProwGetMinActivity(row, set, stat);
6652 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6653 return FALSE;
6654 }
6655 if( !SCIPsetIsInfinity(set, row->rhs) )
6656 {
6657 SCIP_Real maxactivity;
6658
6659 maxactivity = SCIProwGetMaxActivity(row, set, stat);
6660 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6661 return FALSE;
6662 }
6663
6664 return TRUE;
6665}
6666
6667/** gets maximal absolute value of row vector coefficients */
6669 SCIP_ROW* row, /**< LP row */
6670 SCIP_SET* set /**< global SCIP settings */
6671 )
6672{
6673 assert(row != NULL);
6674
6675 if( row->nummaxval == 0 )
6676 rowCalcIdxsAndVals(row, set);
6677 assert(row->nummaxval > 0);
6678 assert(row->maxval >= 0.0 || row->len == 0);
6679
6680 return row->maxval;
6681}
6682
6683/** gets minimal absolute value of row vector's non-zero coefficients */
6685 SCIP_ROW* row, /**< LP row */
6686 SCIP_SET* set /**< global SCIP settings */
6687 )
6688{
6689 assert(row != NULL);
6690
6691 if( row->numminval == 0 )
6692 rowCalcIdxsAndVals(row, set);
6693 assert(row->numminval > 0);
6694 assert(row->minval >= 0.0 || row->len == 0);
6695
6696 return row->minval;
6697}
6698
6699/** gets maximal column index of row entries */
6701 SCIP_ROW* row, /**< LP row */
6702 SCIP_SET* set /**< global SCIP settings */
6703 )
6704{
6705 assert(row != NULL);
6706
6707 if( row->validminmaxidx == 0 )
6708 rowCalcIdxsAndVals(row, set);
6709 assert(row->maxidx >= 0 || row->len == 0);
6710 assert(row->validminmaxidx);
6711
6712 return row->maxidx;
6713}
6714
6715/** gets minimal column index of row entries */
6717 SCIP_ROW* row, /**< LP row */
6718 SCIP_SET* set /**< global SCIP settings */
6719 )
6720{
6721 assert(row != NULL);
6722
6723 if( row->validminmaxidx == 0 )
6724 rowCalcIdxsAndVals(row, set);
6725 assert(row->minidx >= 0 || row->len == 0);
6726 assert(row->validminmaxidx);
6727
6728 return row->minidx;
6729}
6730
6731/** gets number of integral columns in row */
6733 SCIP_ROW* row, /**< LP row */
6734 SCIP_SET* set /**< global SCIP settings */
6735 )
6736{
6737 assert(row != NULL);
6738
6739 if( row->numintcols == -1 )
6740 rowCalcIdxsAndVals(row, set);
6741
6742 assert(row->numintcols <= row->len && row->numintcols >= 0);
6743
6744 return row->numintcols;
6745}
6746
6747/** returns row's cutoff distance in the direction of the given primal solution */
6749 SCIP_ROW* row, /**< LP row */
6750 SCIP_SET* set, /**< global SCIP settings */
6751 SCIP_STAT* stat, /**< problem statistics data */
6752 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
6753 SCIP_LP* lp /**< current LP data */
6754 )
6755{
6756 SCIP_Real solcutoffdist;
6757 int k;
6758
6759 assert(sol != NULL);
6760
6761 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6762 {
6763 SCIP_Real scale = 0.0;
6764
6765 lp->validsoldirlp = stat->lpcount;
6766 lp->validsoldirsol = sol;
6767
6769
6770 for( k = 0; k < lp->ncols; ++k )
6771 {
6772 assert(lp->cols[k]->lppos == k);
6773 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6774 scale += SQR(lp->soldirection[k]);
6775 }
6776
6777 if( scale > 0.0 )
6778 {
6779 scale = 1.0 / sqrt(scale);
6780
6781 for( k = 0; k < lp->ncols; ++k )
6782 lp->soldirection[k] *= scale;
6783 }
6784 }
6785
6786 solcutoffdist = 0.0;
6787 for( k = 0; k < row->nlpcols; ++k )
6788 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6789
6790 for( k = row->nlpcols; k < row->len; ++k )
6791 {
6792 if( row->cols[k]->lppos >= 0 )
6793 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6794 }
6795
6796 if( SCIPsetIsSumZero(set, solcutoffdist) )
6797 solcutoffdist = set->num_sumepsilon;
6798
6799 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6800
6801 return solcutoffdist;
6802}
6803
6804/** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6806 SCIP_ROW* row, /**< LP row */
6807 SCIP_SET* set, /**< global SCIP settings */
6808 SCIP_STAT* stat, /**< problem statistics data */
6809 SCIP_LP* lp /**< current LP data */
6810 )
6811{
6812 SCIP_Real norm;
6813 SCIP_Real feasibility;
6814 SCIP_Real eps;
6815
6816 assert(set != NULL);
6817
6818 switch( set->sepa_efficacynorm )
6819 {
6820 case 'e':
6821 norm = SCIProwGetNorm(row);
6822 break;
6823 case 'm':
6824 norm = SCIProwGetMaxval(row, set);
6825 break;
6826 case 's':
6827 norm = SCIProwGetSumNorm(row);
6828 break;
6829 case 'd':
6830 norm = (row->len == 0 ? 0.0 : 1.0);
6831 break;
6832 default:
6833 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6834 SCIPABORT();
6835 norm = 0.0; /*lint !e527*/
6836 }
6837
6839 norm = MAX(norm, eps);
6840 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6841
6842 return -feasibility / norm;
6843}
6844
6845/** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6847 SCIP_ROW* row, /**< LP row */
6848 SCIP_SET* set, /**< global SCIP settings */
6849 SCIP_STAT* stat, /**< problem statistics data */
6850 SCIP_LP* lp, /**< current LP data */
6851 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6852 )
6853{
6854 SCIP_Real efficacy;
6855
6856 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6857
6858 return SCIPsetIsEfficacious(set, root, efficacy);
6859}
6860
6861/** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6863 SCIP_ROW* row, /**< LP row */
6864 SCIP_SET* set, /**< global SCIP settings */
6865 SCIP_STAT* stat, /**< problem statistics data */
6866 SCIP_SOL* sol /**< primal CIP solution */
6867 )
6868{
6869 SCIP_Real norm;
6870 SCIP_Real feasibility;
6871 SCIP_Real eps;
6872
6873 assert(set != NULL);
6874
6875 switch( set->sepa_efficacynorm )
6876 {
6877 case 'e':
6878 norm = SCIProwGetNorm(row);
6879 break;
6880 case 'm':
6881 norm = SCIProwGetMaxval(row, set);
6882 break;
6883 case 's':
6884 norm = SCIProwGetSumNorm(row);
6885 break;
6886 case 'd':
6887 norm = (row->len == 0 ? 0.0 : 1.0);
6888 break;
6889 default:
6890 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6891 SCIPABORT();
6892 norm = 0.0; /*lint !e527*/
6893 }
6894
6896 norm = MAX(norm, eps);
6897 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6898
6899 return -feasibility / norm;
6900}
6901
6902/** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6903 * efficacy
6904 */
6906 SCIP_ROW* row, /**< LP row */
6907 SCIP_SET* set, /**< global SCIP settings */
6908 SCIP_STAT* stat, /**< problem statistics data */
6909 SCIP_SOL* sol, /**< primal CIP solution */
6910 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6911 )
6912{
6913 SCIP_Real efficacy;
6914
6915 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6916
6917 return SCIPsetIsEfficacious(set, root, efficacy);
6918}
6919
6920/** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6922 SCIP_ROW* row, /**< LP row */
6923 SCIP_SET* set, /**< global SCIP settings */
6924 SCIP_STAT* stat /**< problem statistics data */
6925 )
6926{
6927 SCIP_Real norm;
6928 SCIP_Real feasibility;
6929 SCIP_Real eps;
6930
6931 assert(set != NULL);
6932
6933 switch( set->sepa_efficacynorm )
6934 {
6935 case 'e':
6936 norm = SCIProwGetNorm(row);
6937 break;
6938 case 'm':
6939 norm = SCIProwGetMaxval(row, set);
6940 break;
6941 case 's':
6942 norm = SCIProwGetSumNorm(row);
6943 break;
6944 case 'd':
6945 norm = (row->len == 0 ? 0.0 : 1.0);
6946 break;
6947 default:
6948 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6949 SCIPABORT();
6950 norm = 0.0; /*lint !e527*/
6951 }
6952
6954 norm = MAX(norm, eps);
6955 feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6956
6957 return -feasibility / norm;
6958}
6959
6960/** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6962 SCIP_ROW* row, /**< LP row */
6963 SCIP_SET* set, /**< global SCIP settings */
6964 SCIP_STAT* stat /**< problem statistics data */
6965 )
6966{
6967 SCIP_Real norm;
6968 SCIP_Real feasibility;
6969 SCIP_Real eps;
6970
6971 assert(set != NULL);
6972
6973 switch( set->sepa_efficacynorm )
6974 {
6975 case 'e':
6976 norm = SCIProwGetNorm(row);
6977 break;
6978 case 'm':
6979 norm = SCIProwGetMaxval(row, set);
6980 break;
6981 case 's':
6982 norm = SCIProwGetSumNorm(row);
6983 break;
6984 case 'd':
6985 norm = (row->len == 0 ? 0.0 : 1.0);
6986 break;
6987 default:
6988 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6989 SCIPABORT();
6990 norm = 0.0; /*lint !e527*/
6991 }
6992
6994 norm = MAX(norm, eps);
6995 feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6996
6997 return -feasibility / norm;
6998}
6999
7000/** returns the scalar product of the coefficient vectors of the two given rows
7001 *
7002 * @note the scalar product is computed w.r.t. the current LP columns only
7003 * @todo also consider non-LP columns for the computation?
7004 */
7006 SCIP_ROW* row1, /**< first LP row */
7007 SCIP_ROW* row2 /**< second LP row */
7008 )
7009{
7010 SCIP_Real scalarprod;
7011 int* row1colsidx;
7012 int* row2colsidx;
7013 int i1;
7014 int i2;
7015
7016 assert(row1 != NULL);
7017 assert(row2 != NULL);
7018
7019 /* Sort the column indices of both rows.
7020 *
7021 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7022 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7023 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7024 * for both or one of the non-LP columns for both.
7025 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7026 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7027 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7028 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7029 *
7030 * We distinguish the following cases:
7031 *
7032 * 1) both rows have no unlinked columns
7033 * -> we just check the LP partitions
7034 *
7035 * 2) exactly one row is completely unlinked, the other one is completely linked
7036 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7037 * (thus all common LP columns are regarded)
7038 *
7039 * 3) we have unlinked and LP columns in both rows
7040 * -> we need to compare four partitions at once
7041 *
7042 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7043 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7044 * other row
7045 *
7046 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7047 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7048 *
7049 * 5) both rows are completely unlinked
7050 * -> we need to compare two partitions: both complete rows
7051 */
7052 SCIProwSort(row1);
7053 assert(row1->lpcolssorted);
7054 assert(row1->nonlpcolssorted);
7055 SCIProwSort(row2);
7056 assert(row2->lpcolssorted);
7057 assert(row2->nonlpcolssorted);
7058
7059 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7060 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7061
7062 row1colsidx = row1->cols_index;
7063 row2colsidx = row2->cols_index;
7064
7065#ifndef NDEBUG
7066 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7067 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7068 {
7069 i1 = 0;
7070 i2 = row2->nlpcols;
7071 while( i1 < row1->nlpcols && i2 < row2->len )
7072 {
7073 assert(row1->cols[i1] != row2->cols[i2]);
7074 if( row1->cols[i1]->index < row2->cols[i2]->index )
7075 ++i1;
7076 else
7077 {
7078 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7079 ++i2;
7080 }
7081 }
7082 assert(i1 == row1->nlpcols || i2 == row2->len);
7083
7084 i1 = row1->nlpcols;
7085 i2 = 0;
7086 while( i1 < row1->len && i2 < row2->nlpcols )
7087 {
7088 assert(row1->cols[i1] != row2->cols[i2]);
7089 if( row1->cols[i1]->index < row2->cols[i2]->index )
7090 ++i1;
7091 else
7092 {
7093 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7094 ++i2;
7095 }
7096 }
7097 assert(i1 == row1->len || i2 == row2->nlpcols);
7098 }
7099#endif
7100
7101 /* The "easy" cases 1) and 2) */
7102 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7103 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7104 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7105 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7106 {
7107 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7108 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7109
7110 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7111 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7112 */
7113 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7114 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7115 scalarprod = 0.0;
7116
7117 /* calculate the scalar product */
7118 while( i1 >= 0 && i2 >= 0 )
7119 {
7120 assert(row1->cols[i1]->index == row1colsidx[i1]);
7121 assert(row2->cols[i2]->index == row2colsidx[i2]);
7122 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7123 if( row1colsidx[i1] < row2colsidx[i2] )
7124 --i2;
7125 else if( row1colsidx[i1] > row2colsidx[i2] )
7126 --i1;
7127 else
7128 {
7129 scalarprod += row1->vals[i1] * row2->vals[i2];
7130 --i1;
7131 --i2;
7132 }
7133 }
7134 }
7135 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7136 else
7137 {
7138 SCIP_Bool lpcols;
7139 int ilp1;
7140 int inlp1;
7141 int ilp2;
7142 int inlp2;
7143 int end1;
7144 int end2;
7145
7146 scalarprod = 0;
7147 ilp1 = 0;
7148 ilp2 = 0;
7149
7150 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7151 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7152 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7153
7154 /* handle the case of four partitions (case 3) until one partition is finished;
7155 * cases 4a), 4b), and 5) will fail the while-condition
7156 */
7157 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7158 {
7159 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7160 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7161 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7162 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7163 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7164 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7165 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7166 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7167
7168 /* rows have the same linked LP columns */
7169 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7170 {
7171 scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7172 ++ilp1;
7173 ++ilp2;
7174 }
7175 /* LP column of row1 is the same as unlinked column of row2 */
7176 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7177 {
7178 scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7179 ++ilp1;
7180 ++inlp2;
7181 }
7182 /* unlinked column of row1 is the same as LP column of row2 */
7183 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7184 {
7185 scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7186 ++inlp1;
7187 ++ilp2;
7188 }
7189 /* two unlinked LP columns are the same */
7190 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7191 {
7192 scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7193 ++inlp1;
7194 ++inlp2;
7195 }
7196 /* increase smallest counter */
7197 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7198 {
7199 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7200 {
7201 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7202 ++ilp1;
7203 else
7204 ++ilp2;
7205 }
7206 else
7207 {
7208 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7209 ++ilp1;
7210 else
7211 ++inlp2;
7212 }
7213 }
7214 else
7215 {
7216 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7217 {
7218 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7219 ++inlp1;
7220 else
7221 ++ilp2;
7222 }
7223 else
7224 {
7225 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7226 ++inlp1;
7227 else
7228 ++inlp2;
7229 }
7230 }
7231 }
7232
7233 /* One partition was completely handled, we just have to handle the three remaining partitions:
7234 * the remaining partition of this row and the two partitions of the other row.
7235 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7236 */
7237 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7238 {
7239 int tmpilp;
7240 int tmpinlp;
7241
7242 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7243
7244 SCIPswapPointers((void**) &row1, (void**) &row2);
7245 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7246 tmpilp = ilp1;
7247 tmpinlp = inlp1;
7248 ilp1 = ilp2;
7249 inlp1 = inlp2;
7250 ilp2 = tmpilp;
7251 inlp2 = tmpinlp;
7252 }
7253
7254 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7255 * -> this merges cases 4a) and 4b)
7256 */
7257 if( ilp1 == row1->nlpcols )
7258 {
7259 i1 = inlp1;
7260 end1 = row1->len;
7261 lpcols = FALSE;
7262 }
7263 else
7264 {
7265 assert(inlp1 == row1->len);
7266
7267 i1 = ilp1;
7268 end1 = row1->nlpcols;
7269 lpcols = TRUE;
7270 }
7271
7272 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7273 * case 5) will fail the while-condition
7274 */
7275 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7276 {
7277 assert(row1->cols[i1]->index == row1colsidx[i1]);
7278 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7279 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7280 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7281 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7282
7283 /* current column in row 1 is the same as the current LP column in row 2 */
7284 if( row1colsidx[i1] == row2colsidx[ilp2] )
7285 {
7286 scalarprod += row1->vals[i1] * row2->vals[ilp2];
7287 ++i1;
7288 ++ilp2;
7289 }
7290 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7291 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7292 {
7293 scalarprod += row1->vals[i1] * row2->vals[inlp2];
7294 ++i1;
7295 ++inlp2;
7296 }
7297 /* increase smallest counter */
7298 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7299 {
7300 if( row1colsidx[i1] < row2colsidx[ilp2] )
7301 ++i1;
7302 else
7303 ++ilp2;
7304 }
7305 else
7306 {
7307 if( row1colsidx[i1] < row2colsidx[inlp2] )
7308 ++i1;
7309 else
7310 ++inlp2;
7311 }
7312 }
7313
7314 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7315 * the two rows
7316 */
7317 if( i1 < end1 )
7318 {
7319 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7320 if( ilp2 == row2->nlpcols )
7321 {
7322 i2 = inlp2;
7323 end2 = row2->len;
7324 lpcols = FALSE;
7325 }
7326 else
7327 {
7328 assert(inlp2 == row2->len);
7329
7330 i2 = ilp2;
7331 end2 = row2->nlpcols;
7332 }
7333
7334 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7335 while( i1 < end1 && i2 < end2 )
7336 {
7337 assert(row1->cols[i1]->index == row1colsidx[i1]);
7338 assert(row2->cols[i2]->index == row2colsidx[i2]);
7339 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7340
7341 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7342 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7343 {
7344 scalarprod += row1->vals[i1] * row2->vals[i2];
7345 ++i1;
7346 ++i2;
7347 }
7348 /* increase smallest counter */
7349 else if( row1colsidx[i1] < row2colsidx[i2] )
7350 ++i1;
7351 else
7352 ++i2;
7353 }
7354 }
7355 }
7356
7357 return scalarprod;
7358}
7359
7360/** returns the discrete scalar product of the coefficient vectors of the two given rows */
7361static
7363 SCIP_ROW* row1, /**< first LP row */
7364 SCIP_ROW* row2 /**< second LP row */
7365 )
7366{
7367 int prod;
7368 int* row1colsidx;
7369 int* row2colsidx;
7370 int i1;
7371 int i2;
7372
7373 assert(row1 != NULL);
7374 assert(row2 != NULL);
7375
7376 /* Sort the column indices of both rows.
7377 *
7378 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7379 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7380 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7381 * for both or one of the non-LP columns for both.
7382 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7383 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7384 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7385 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7386 *
7387 * We distinguish the following cases:
7388 *
7389 * 1) both rows have no unlinked columns
7390 * -> we just check the LP partitions
7391 *
7392 * 2) exactly one row is completely unlinked, the other one is completely linked
7393 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7394 * (thus all common LP columns are regarded)
7395 *
7396 * 3) we have unlinked and LP columns in both rows
7397 * -> we need to compare four partitions at once
7398 *
7399 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7400 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7401 * other row
7402 *
7403 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7404 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7405 *
7406 * 5) both rows are completely unlinked
7407 * -> we need to compare two partitions: both complete rows
7408 */
7409 SCIProwSort(row1);
7410 assert(row1->lpcolssorted);
7411 assert(row1->nonlpcolssorted);
7412 SCIProwSort(row2);
7413 assert(row2->lpcolssorted);
7414 assert(row2->nonlpcolssorted);
7415
7416 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7417 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7418
7419 row1colsidx = row1->cols_index;
7420 row2colsidx = row2->cols_index;
7421
7422#ifndef NDEBUG
7423 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7424 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7425 {
7426 i1 = 0;
7427 i2 = row2->nlpcols;
7428 while( i1 < row1->nlpcols && i2 < row2->len )
7429 {
7430 assert(row1->cols[i1] != row2->cols[i2]);
7431 if( row1->cols[i1]->index < row2->cols[i2]->index )
7432 ++i1;
7433 else
7434 {
7435 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7436 ++i2;
7437 }
7438 }
7439 assert(i1 == row1->nlpcols || i2 == row2->len);
7440
7441 i1 = row1->nlpcols;
7442 i2 = 0;
7443 while( i1 < row1->len && i2 < row2->nlpcols )
7444 {
7445 assert(row1->cols[i1] != row2->cols[i2]);
7446 if( row1->cols[i1]->index < row2->cols[i2]->index )
7447 ++i1;
7448 else
7449 {
7450 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7451 ++i2;
7452 }
7453 }
7454 assert(i1 == row1->len || i2 == row2->nlpcols);
7455 }
7456#endif
7457
7458 /* The "easy" cases 1) and 2) */
7459 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7460 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7461 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7462 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7463 {
7464 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7465 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7466
7467 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7468 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7469 */
7470 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7471 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7472 prod = 0;
7473
7474 /* calculate the scalar product */
7475 while( i1 >= 0 && i2 >= 0 )
7476 {
7477 assert(row1->cols[i1]->index == row1colsidx[i1]);
7478 assert(row2->cols[i2]->index == row2colsidx[i2]);
7479 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7480 if( row1colsidx[i1] < row2colsidx[i2] )
7481 --i2;
7482 else if( row1colsidx[i1] > row2colsidx[i2] )
7483 --i1;
7484 else
7485 {
7486 ++prod;
7487 --i1;
7488 --i2;
7489 }
7490 }
7491 }
7492 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7493 else
7494 {
7495 SCIP_Bool lpcols;
7496 int ilp1;
7497 int inlp1;
7498 int ilp2;
7499 int inlp2;
7500 int end1;
7501 int end2;
7502
7503 prod = 0;
7504 ilp1 = 0;
7505 ilp2 = 0;
7506
7507 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7508 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7509 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7510
7511 /* handle the case of four partitions (case 3) until one partition is finished;
7512 * cases 4a), 4b), and 5) will fail the while-condition
7513 */
7514 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7515 {
7516 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7517 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7518 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7519 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7520 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7521 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7522 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7523 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7524
7525 /* rows have the same linked LP columns */
7526 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7527 {
7528 ++prod;
7529 ++ilp1;
7530 ++ilp2;
7531 }
7532 /* LP column of row1 is the same as unlinked column of row2 */
7533 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7534 {
7535 ++prod;
7536 ++ilp1;
7537 ++inlp2;
7538 }
7539 /* unlinked column of row1 is the same as LP column of row2 */
7540 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7541 {
7542 ++prod;
7543 ++inlp1;
7544 ++ilp2;
7545 }
7546 /* two unlinked LP columns are the same */
7547 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7548 {
7549 ++prod;
7550 ++inlp1;
7551 ++inlp2;
7552 }
7553 /* increase smallest counter */
7554 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7555 {
7556 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7557 {
7558 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7559 ++ilp1;
7560 else
7561 ++ilp2;
7562 }
7563 else
7564 {
7565 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7566 ++ilp1;
7567 else
7568 ++inlp2;
7569 }
7570 }
7571 else
7572 {
7573 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7574 {
7575 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7576 ++inlp1;
7577 else
7578 ++ilp2;
7579 }
7580 else
7581 {
7582 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7583 ++inlp1;
7584 else
7585 ++inlp2;
7586 }
7587 }
7588 }
7589
7590 /* One partition was completely handled, we just have to handle the three remaining partitions:
7591 * the remaining partition of this row and the two partitions of the other row.
7592 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7593 */
7594 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7595 {
7596 int tmpilp;
7597 int tmpinlp;
7598
7599 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7600
7601 SCIPswapPointers((void**) &row1, (void**) &row2);
7602 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7603 tmpilp = ilp1;
7604 tmpinlp = inlp1;
7605 ilp1 = ilp2;
7606 inlp1 = inlp2;
7607 ilp2 = tmpilp;
7608 inlp2 = tmpinlp;
7609 }
7610
7611 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7612 * -> this merges cases 4a) and 4b)
7613 */
7614 if( ilp1 == row1->nlpcols )
7615 {
7616 i1 = inlp1;
7617 end1 = row1->len;
7618 lpcols = FALSE;
7619 }
7620 else
7621 {
7622 assert(inlp1 == row1->len);
7623
7624 i1 = ilp1;
7625 end1 = row1->nlpcols;
7626 lpcols = TRUE;
7627 }
7628
7629 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7630 * case 5) will fail the while-condition
7631 */
7632 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7633 {
7634 assert(row1->cols[i1]->index == row1colsidx[i1]);
7635 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7636 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7637 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7638 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7639
7640 /* current column in row 1 is the same as the current LP column in row 2 */
7641 if( row1colsidx[i1] == row2colsidx[ilp2] )
7642 {
7643 ++prod;
7644 ++i1;
7645 ++ilp2;
7646 }
7647 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7648 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7649 {
7650 ++prod;
7651 ++i1;
7652 ++inlp2;
7653 }
7654 /* increase smallest counter */
7655 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7656 {
7657 if( row1colsidx[i1] < row2colsidx[ilp2] )
7658 ++i1;
7659 else
7660 ++ilp2;
7661 }
7662 else
7663 {
7664 if( row1colsidx[i1] < row2colsidx[inlp2] )
7665 ++i1;
7666 else
7667 ++inlp2;
7668 }
7669 }
7670
7671 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7672 * the two rows
7673 */
7674 if( i1 < end1 )
7675 {
7676 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7677 if( ilp2 == row2->nlpcols )
7678 {
7679 i2 = inlp2;
7680 end2 = row2->len;
7681 lpcols = FALSE;
7682 }
7683 else
7684 {
7685 assert(inlp2 == row2->len);
7686
7687 i2 = ilp2;
7688 end2 = row2->nlpcols;
7689 }
7690
7691 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7692 while( i1 < end1 && i2 < end2 )
7693 {
7694 assert(row1->cols[i1]->index == row1colsidx[i1]);
7695 assert(row2->cols[i2]->index == row2colsidx[i2]);
7696 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7697
7698 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7699 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7700 {
7701 ++prod;
7702 ++i1;
7703 ++i2;
7704 }
7705 /* increase smallest counter */
7706 else if( row1colsidx[i1] < row2colsidx[i2] )
7707 ++i1;
7708 else
7709 ++i2;
7710 }
7711 }
7712 }
7713
7714 return prod;
7715}
7716
7717/** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7718 * p = |v*w|/(|v|*|w|);
7719 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7720 */
7722 SCIP_ROW* row1, /**< first LP row */
7723 SCIP_ROW* row2, /**< second LP row */
7724 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7725 )
7726{
7727 SCIP_Real parallelism;
7728 SCIP_Real scalarprod;
7729
7730 switch( orthofunc )
7731 {
7732 case 'e':
7733 scalarprod = SCIProwGetScalarProduct(row1, row2);
7734 if( scalarprod == 0.0 )
7735 {
7736 parallelism = 0.0;
7737 break;
7738 }
7739
7740 if( SCIProwGetNorm(row1) == 0.0 )
7741 {
7742 /* In theory, this should not happen if the scalarproduct is not zero
7743 * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7744 * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7745 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7746 */
7747 int i;
7748 for( i = 0; i < row1->len; ++i )
7749 if( row1->cols[i]->lppos >= 0 )
7750 row1->sqrnorm += SQR(row1->vals[i]);
7751 assert(SCIProwGetNorm(row1) != 0.0);
7752 }
7753
7754 if( SCIProwGetNorm(row2) == 0.0 )
7755 {
7756 /* same as for row1 above: reeval norms if it is 0, which is wrong */
7757 int i;
7758 for( i = 0; i < row2->len; ++i )
7759 if( row2->cols[i]->lppos >= 0 )
7760 row2->sqrnorm += SQR(row2->vals[i]);
7761 assert(SCIProwGetNorm(row2) != 0.0);
7762 }
7763
7764 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7765 break;
7766
7767 case 'd':
7768 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7769 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7770 break;
7771
7772 default:
7773 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7774 SCIPABORT();
7775 parallelism = 0.0; /*lint !e527*/
7776 }
7777
7778 return parallelism;
7779}
7780
7781/** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7782 * o = 1 - |v*w|/(|v|*|w|);
7783 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7784 */
7786 SCIP_ROW* row1, /**< first LP row */
7787 SCIP_ROW* row2, /**< second LP row */
7788 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7789 )
7790{
7791 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7792}
7793
7794/** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7795 * function, if the value is 0, it is orthogonal to the objective function
7796 */
7798 SCIP_ROW* row, /**< LP row */
7799 SCIP_SET* set, /**< global SCIP settings */
7800 SCIP_LP* lp /**< current LP data */
7801 )
7802{
7803 SCIP_Real prod;
7804 SCIP_Real parallelism;
7805
7806 assert(row != NULL);
7807 assert(lp != NULL);
7808
7809 if( lp->objsqrnormunreliable )
7811
7812 assert(!lp->objsqrnormunreliable);
7813 assert(lp->objsqrnorm >= 0.0);
7814
7815 checkRowSqrnorm(row);
7816 checkRowObjprod(row);
7817
7818 prod = row->sqrnorm * lp->objsqrnorm;
7819
7820 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / sqrt(prod) : 0.0;
7821 assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7822 assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7823 parallelism = MIN(parallelism, 1.0);
7824 parallelism = MAX(parallelism, 0.0);
7825
7826 return parallelism;
7827}
7828
7829/** includes event handler with given data in row's event filter */
7831 SCIP_ROW* row, /**< row */
7832 BMS_BLKMEM* blkmem, /**< block memory */
7833 SCIP_SET* set, /**< global SCIP settings */
7834 SCIP_EVENTTYPE eventtype, /**< event type to catch */
7835 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7836 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7837 int* filterpos /**< pointer to store position of event filter entry, or NULL */
7838 )
7839{
7840 assert(row != NULL);
7841 assert(row->eventfilter != NULL);
7842 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7843 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7844
7845 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7846 eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7847
7848 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7849
7850 return SCIP_OKAY;
7851}
7852
7853/** deletes event handler with given data from row's event filter */
7855 SCIP_ROW* row, /**< row */
7856 BMS_BLKMEM* blkmem, /**< block memory */
7857 SCIP_SET* set, /**< global SCIP settings */
7858 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7859 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7860 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7861 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7862 )
7863{
7864 assert(row != NULL);
7865 assert(row->eventfilter != NULL);
7866
7867 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7868
7869 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7870
7871 return SCIP_OKAY;
7872}
7873
7874/** marks a row to be not removable from the LP in the current node because it became obsolete */
7876 SCIP_ROW* row, /**< LP row */
7877 SCIP_STAT* stat /**< problem statistics */
7878 )
7879{
7880 assert(row != NULL);
7881 assert(stat != NULL);
7882 assert(stat->nnodes > 0);
7883
7884 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7885 row->obsoletenode = stat->nnodes;
7886}
7887
7888/*
7889 * LP solver data update
7890 */
7891
7892/** resets column data to represent a column not in the LP solver */
7893static
7895 SCIP_COL* col /**< column to be marked deleted */
7896 )
7897{
7898 assert(col != NULL);
7899
7900 col->lpipos = -1;
7901 col->primsol = 0.0;
7902 col->redcost = SCIP_INVALID;
7903 col->farkascoef = SCIP_INVALID;
7904 col->sbdown = SCIP_INVALID;
7905 col->sbup = SCIP_INVALID;
7906 col->sbdownvalid = FALSE;
7907 col->sbupvalid = FALSE;
7908 col->validredcostlp = -1;
7909 col->validfarkaslp = -1;
7910 col->sbitlim = -1;
7911 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7912}
7913
7914/** applies all cached column removals to the LP solver */
7915static
7917 SCIP_LP* lp /**< current LP data */
7918 )
7919{
7920 assert(lp != NULL);
7921 assert(lp->lpifirstchgcol <= lp->nlpicols);
7922 assert(lp->lpifirstchgcol <= lp->ncols);
7923
7924 /* find the first column to change */
7925 while( lp->lpifirstchgcol < lp->nlpicols
7926 && lp->lpifirstchgcol < lp->ncols
7927 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7928 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7929 {
7930 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7931 lp->lpifirstchgcol++;
7932 }
7933
7934 /* shrink LP to the part which didn't change */
7935 if( lp->lpifirstchgcol < lp->nlpicols )
7936 {
7937 int i;
7938
7939 assert(!lp->diving);
7940 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7942 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7943 {
7944 markColDeleted(lp->lpicols[i]);
7945 }
7946 lp->nlpicols = lp->lpifirstchgcol;
7947 lp->flushdeletedcols = TRUE;
7948 lp->updateintegrality = TRUE;
7949
7950 /* mark the LP unsolved */
7951 lp->solved = FALSE;
7952 lp->primalfeasible = FALSE;
7953 lp->primalchecked = FALSE;
7954 lp->lpobjval = SCIP_INVALID;
7956 }
7957 assert(lp->nlpicols == lp->lpifirstchgcol);
7958
7959 return SCIP_OKAY;
7960}
7961
7962/** computes for the given column the lower and upper bound that should be flushed into the LP
7963 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7964 * the bounds are explicitly added to the LP in any case
7965 */
7966static
7968 SCIP_LP* lp, /**< current LP data */
7969 SCIP_SET* set, /**< global SCIP settings */
7970 SCIP_COL* col, /**< column to compute bounds for */
7971 SCIP_Real lpiinf, /**< infinity value if the LP solver */
7972 SCIP_Real* lb, /**< pointer to store the new lower bound */
7973 SCIP_Real* ub /**< pointer to store the new upper bound */
7974 )
7975{
7976 assert(lp != NULL);
7977 assert(set != NULL);
7978 assert(col != NULL);
7979 assert(lb != NULL);
7980 assert(ub != NULL);
7981
7982 /* get the correct new lower bound:
7983 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7984 * if we are in diving mode, ignore lazy bounds and always take the lower bound
7985 */
7986 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7987 (*lb) = -lpiinf;
7988 else
7989 (*lb) = col->lb;
7990 /* get the correct new upper bound:
7991 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7992 * if we are in diving mode, ignore lazy bounds and always take the upper bound
7993 */
7994 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7995 (*ub) = lpiinf;
7996 else
7997 (*ub) = col->ub;
7998}
7999
8000/** applies all cached column additions to the LP solver */
8001static
8003 SCIP_LP* lp, /**< current LP data */
8004 BMS_BLKMEM* blkmem, /**< block memory */
8005 SCIP_SET* set, /**< global SCIP settings */
8006 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8007 )
8008{
8009 SCIP_Real* obj;
8010 SCIP_Real* lb;
8011 SCIP_Real* ub;
8012 int* beg;
8013 int* ind;
8014 SCIP_Real* val;
8015 char** name;
8016 SCIP_COL* col;
8017 SCIP_Real lpiinf;
8018 int c;
8019 int pos;
8020 int nnonz;
8021 int naddcols;
8022 int naddcoefs;
8023 int i;
8024 int lpipos;
8025
8026 assert(lp != NULL);
8027 assert(lp->lpifirstchgcol == lp->nlpicols);
8028 assert(blkmem != NULL);
8029 assert(set != NULL);
8030
8031 /* if there are no columns to add, we are ready */
8032 if( lp->ncols == lp->nlpicols )
8033 return SCIP_OKAY;
8034
8035 /* add the additional columns */
8036 assert(!lp->diving);
8037 assert(lp->ncols > lp->nlpicols);
8038 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8039
8040 /* get the solver's infinity value */
8041 lpiinf = SCIPlpiInfinity(lp->lpi);
8042
8043 /* count the (maximal) number of added coefficients, calculate the number of added columns */
8044 naddcols = lp->ncols - lp->nlpicols;
8045 naddcoefs = 0;
8046 for( c = lp->nlpicols; c < lp->ncols; ++c )
8047 naddcoefs += lp->cols[c]->len;
8048 assert(naddcols > 0);
8049
8050 /* get temporary memory for changes */
8051 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8052 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8053 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8057 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8058
8059 /* fill temporary memory with column data */
8060 nnonz = 0;
8061 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8062 {
8063 col = lp->cols[c];
8064 assert(col != NULL);
8065 assert(col->var != NULL);
8067 assert(SCIPvarGetCol(col->var) == col);
8068 assert(col->lppos == c);
8069 assert(nnonz + col->nlprows <= naddcoefs);
8070
8071 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8072 debugColPrint(set, col);
8073
8074 /* Because the column becomes a member of the LP solver, it now can take values
8075 * different from zero. That means, we have to include the column in the corresponding
8076 * row vectors.
8077 */
8078 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8079
8080 lp->lpicols[c] = col;
8081 col->lpipos = c;
8082 col->primsol = SCIP_INVALID;
8083 col->redcost = SCIP_INVALID;
8084 col->farkascoef = SCIP_INVALID;
8085 col->sbdown = SCIP_INVALID;
8086 col->sbup = SCIP_INVALID;
8087 col->sbdownvalid = FALSE;
8088 col->sbupvalid = FALSE;
8089 col->validredcostlp = -1;
8090 col->validfarkaslp = -1;
8091 col->sbitlim = -1;
8092 col->objchanged = FALSE;
8093 col->lbchanged = FALSE;
8094 col->ubchanged = FALSE;
8095 col->coefchanged = FALSE;
8096 obj[pos] = col->obj;
8097
8098 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8099 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8100
8101 beg[pos] = nnonz;
8102 name[pos] = (char*)SCIPvarGetName(col->var);
8103
8104 col->flushedobj = obj[pos];
8105 col->flushedlb = lb[pos];
8106 col->flushedub = ub[pos];
8107
8108 for( i = 0; i < col->nlprows; ++i )
8109 {
8110 assert(col->rows[i] != NULL);
8111 lpipos = col->rows[i]->lpipos;
8112 if( lpipos >= 0 )
8113 {
8114 assert(lpipos < lp->nrows);
8115 assert(nnonz < naddcoefs);
8116 ind[nnonz] = lpipos;
8117 val[nnonz] = col->vals[i];
8118 nnonz++;
8119 }
8120 }
8121#ifndef NDEBUG
8122 for( i = col->nlprows; i < col->len; ++i )
8123 {
8124 assert(col->rows[i] != NULL);
8125 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8126 }
8127#endif
8128 }
8129
8130 /* call LP interface */
8131 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8132 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8133 lp->nlpicols = lp->ncols;
8134 lp->lpifirstchgcol = lp->nlpicols;
8135
8136 /* free temporary memory */
8144
8145 lp->flushaddedcols = TRUE;
8146 lp->updateintegrality = TRUE;
8147
8148 /* mark the LP unsolved */
8149 lp->solved = FALSE;
8150 lp->dualfeasible = FALSE;
8151 lp->dualchecked = FALSE;
8152 lp->lpobjval = SCIP_INVALID;
8154
8155 return SCIP_OKAY;
8156}
8157
8158/** resets row data to represent a row not in the LP solver */
8159static
8161 SCIP_ROW* row /**< row to be marked deleted */
8162 )
8163{
8164 assert(row != NULL);
8165
8166 row->lpipos = -1;
8167 row->dualsol = 0.0;
8168 row->activity = SCIP_INVALID;
8169 row->dualfarkas = 0.0;
8170 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8171 row->validactivitylp = -1;
8172}
8173
8174/** applies all cached row removals to the LP solver */
8175static
8177 SCIP_LP* lp, /**< current LP data */
8178 BMS_BLKMEM* blkmem, /**< block memory */
8179 SCIP_SET* set /**< global SCIP settings */
8180 )
8181{
8182 assert(lp != NULL);
8183 assert(lp->lpifirstchgrow <= lp->nlpirows);
8184 assert(lp->lpifirstchgrow <= lp->nrows);
8185
8186 /* find the first row to change */
8187 while( lp->lpifirstchgrow < lp->nlpirows
8188 && lp->lpifirstchgrow < lp->nrows
8189 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8190 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8191 {
8192 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8193 lp->lpifirstchgrow++;
8194 }
8195
8196 /* shrink LP to the part which didn't change */
8197 if( lp->lpifirstchgrow < lp->nlpirows )
8198 {
8199 int i;
8200
8201 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8203 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8204 {
8205 markRowDeleted(lp->lpirows[i]);
8206 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8207 }
8208 lp->nlpirows = lp->lpifirstchgrow;
8209 lp->flushdeletedrows = TRUE;
8210
8211 /* mark the LP unsolved */
8212 lp->solved = FALSE;
8213 lp->dualfeasible = FALSE;
8214 lp->dualchecked = FALSE;
8215 lp->lpobjval = SCIP_INVALID;
8217 }
8218 assert(lp->nlpirows == lp->lpifirstchgrow);
8219
8220 return SCIP_OKAY;
8221}
8222
8223/** applies all cached row additions and removals to the LP solver */
8224static
8226 SCIP_LP* lp, /**< current LP data */
8227 BMS_BLKMEM* blkmem, /**< block memory */
8228 SCIP_SET* set, /**< global SCIP settings */
8229 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8230 )
8231{
8232 SCIP_Real* lhs;
8233 SCIP_Real* rhs;
8234 int* beg;
8235 int* ind;
8236 SCIP_Real* val;
8237 char** name;
8238 SCIP_ROW* row;
8239 SCIP_Real lpiinf;
8240 int r;
8241 int pos;
8242 int nnonz;
8243 int naddrows;
8244 int naddcoefs;
8245 int i;
8246 int lpipos;
8247
8248 assert(lp != NULL);
8249 assert(lp->lpifirstchgrow == lp->nlpirows);
8250 assert(blkmem != NULL);
8251
8252 /* if there are no rows to add, we are ready */
8253 if( lp->nrows == lp->nlpirows )
8254 return SCIP_OKAY;
8255
8256 /* add the additional rows */
8257 assert(lp->nrows > lp->nlpirows);
8258 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8259
8260 /* get the solver's infinity value */
8261 lpiinf = SCIPlpiInfinity(lp->lpi);
8262
8263 /* count the (maximal) number of added coefficients, calculate the number of added rows */
8264 naddrows = lp->nrows - lp->nlpirows;
8265 naddcoefs = 0;
8266 for( r = lp->nlpirows; r < lp->nrows; ++r )
8267 naddcoefs += lp->rows[r]->len;
8268 assert(naddrows > 0);
8269
8270 /* get temporary memory for changes */
8271 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8272 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8273 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8276 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8277
8278 /* fill temporary memory with row data */
8279 nnonz = 0;
8280 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8281 {
8282 row = lp->rows[r];
8283 assert(row != NULL);
8284 assert(row->lppos == r);
8285 assert(nnonz + row->nlpcols <= naddcoefs);
8286
8287 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8288 debugRowPrint(set, row);
8289
8290 /* Because the row becomes a member of the LP solver, its dual variable now can take values
8291 * different from zero. That means, we have to include the row in the corresponding
8292 * column vectors.
8293 */
8294 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8295
8296 SCIProwCapture(row);
8297 lp->lpirows[r] = row;
8298 row->lpipos = r;
8299 row->dualsol = SCIP_INVALID;
8300 row->activity = SCIP_INVALID;
8301 row->dualfarkas = SCIP_INVALID;
8302 row->validactivitylp = -1;
8303 row->lhschanged = FALSE;
8304 row->rhschanged = FALSE;
8305 row->coefchanged = FALSE;
8306 if( SCIPsetIsInfinity(set, -row->lhs) )
8307 lhs[pos] = -lpiinf;
8308 else
8309 lhs[pos] = row->lhs - row->constant;
8310 if( SCIPsetIsInfinity(set, row->rhs) )
8311 rhs[pos] = lpiinf;
8312 else
8313 rhs[pos] = row->rhs - row->constant;
8314 beg[pos] = nnonz;
8315 name[pos] = row->name;
8316
8317 row->flushedlhs = lhs[pos];
8318 row->flushedrhs = rhs[pos];
8319
8320 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8321 for( i = 0; i < row->nlpcols; ++i )
8322 {
8323 assert(row->cols[i] != NULL);
8324 lpipos = row->cols[i]->lpipos;
8325 if( lpipos >= 0 )
8326 {
8327 assert(lpipos < lp->ncols);
8328 assert(nnonz < naddcoefs);
8329 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8330 ind[nnonz] = lpipos;
8331 val[nnonz] = row->vals[i];
8332 nnonz++;
8333 }
8334 }
8335 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8336#ifndef NDEBUG
8337 for( i = row->nlpcols; i < row->len; ++i )
8338 {
8339 assert(row->cols[i] != NULL);
8340 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8341 }
8342#endif
8343 }
8344
8345 /* call LP interface */
8346 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8347 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8348 lp->nlpirows = lp->nrows;
8349 lp->lpifirstchgrow = lp->nlpirows;
8350
8351 /* free temporary memory */
8358
8359 lp->flushaddedrows = TRUE;
8360
8361 /* mark the LP unsolved */
8362 lp->solved = FALSE;
8363 lp->primalfeasible = FALSE;
8364 lp->primalchecked = FALSE;
8365 lp->lpobjval = SCIP_INVALID;
8367
8368 return SCIP_OKAY;
8369}
8370
8371/** applies all cached column bound and objective changes to the LP */
8372static
8374 SCIP_LP* lp, /**< current LP data */
8375 SCIP_SET* set /**< global SCIP settings */
8376 )
8377{
8378#ifndef NDEBUG
8379 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8380#endif
8381 SCIP_COL* col;
8382 int* objind;
8383 int* bdind;
8384 SCIP_Real* obj;
8385 SCIP_Real* lb;
8386 SCIP_Real* ub;
8387 SCIP_Real lpiinf;
8388 int nobjchg;
8389 int nbdchg;
8390 int i;
8391
8392 assert(lp != NULL);
8393
8394 if( lp->nchgcols == 0 )
8395 return SCIP_OKAY;
8396
8397 /* get the solver's infinity value */
8398 lpiinf = SCIPlpiInfinity(lp->lpi);
8399
8400 /* get temporary memory for changes */
8401 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8403 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8406
8407 /* collect all cached bound and objective changes */
8408 nobjchg = 0;
8409 nbdchg = 0;
8410 for( i = 0; i < lp->nchgcols; ++i )
8411 {
8412 col = lp->chgcols[i];
8413 assert(col != NULL);
8414 assert(col->var != NULL);
8416 assert(SCIPvarGetCol(col->var) == col);
8417
8418 if( col->lpipos >= 0 )
8419 {
8420#ifndef NDEBUG
8421 /* do not check consistency of data with LPI in case of LPI=none */
8422 if( !lpinone )
8423 {
8424 SCIP_Real lpiobj;
8425 SCIP_Real lpilb;
8426 SCIP_Real lpiub;
8427
8428 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8429 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8430 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8431 assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb))
8432 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8433 assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub))
8434 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8435 }
8436#endif
8437
8438 if( col->objchanged )
8439 {
8440 SCIP_Real newobj;
8441
8442 newobj = col->obj;
8443 if( col->flushedobj != newobj ) /*lint !e777*/
8444 {
8445 assert(nobjchg < lp->ncols);
8446 objind[nobjchg] = col->lpipos;
8447 obj[nobjchg] = newobj;
8448 nobjchg++;
8449 col->flushedobj = newobj;
8450 }
8451 col->objchanged = FALSE;
8452 }
8453
8454 if( col->lbchanged || col->ubchanged )
8455 {
8456 SCIP_Real newlb;
8457 SCIP_Real newub;
8458
8459 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8460 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8461
8462 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8463 {
8464 assert(nbdchg < lp->ncols);
8465 bdind[nbdchg] = col->lpipos;
8466 lb[nbdchg] = newlb;
8467 ub[nbdchg] = newub;
8468 nbdchg++;
8469 col->flushedlb = newlb;
8470 col->flushedub = newub;
8471 }
8472 col->lbchanged = FALSE;
8473 col->ubchanged = FALSE;
8474 }
8475 }
8476 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8477 }
8478
8479 /* change objective values in LP */
8480 if( nobjchg > 0 )
8481 {
8482 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8483 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8484
8485 /* mark the LP unsolved */
8486 lp->solved = FALSE;
8487 lp->dualfeasible = FALSE;
8488 lp->dualchecked = FALSE;
8489 lp->lpobjval = SCIP_INVALID;
8491 }
8492
8493 /* change bounds in LP */
8494 if( nbdchg > 0 )
8495 {
8496 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8497 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8498
8499 /* mark the LP unsolved */
8500 lp->solved = FALSE;
8501 lp->primalfeasible = FALSE;
8502 lp->primalchecked = FALSE;
8503 lp->lpobjval = SCIP_INVALID;
8505 }
8506
8507 lp->nchgcols = 0;
8508
8509 /* free temporary memory */
8512 SCIPsetFreeBufferArray(set, &bdind);
8514 SCIPsetFreeBufferArray(set, &objind);
8515
8516 return SCIP_OKAY;
8517}
8518
8519/** applies all cached row side changes to the LP */
8520static
8522 SCIP_LP* lp, /**< current LP data */
8523 SCIP_SET* set /**< global SCIP settings */
8524 )
8525{
8526#ifndef NDEBUG
8527 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8528#endif
8529 SCIP_ROW* row;
8530 int* ind;
8531 SCIP_Real* lhs;
8532 SCIP_Real* rhs;
8533 SCIP_Real lpiinf;
8534 int i;
8535 int nchg;
8536
8537 assert(lp != NULL);
8538
8539 if( lp->nchgrows == 0 )
8540 return SCIP_OKAY;
8541
8542 /* get the solver's infinity value */
8543 lpiinf = SCIPlpiInfinity(lp->lpi);
8544
8545 /* get temporary memory for changes */
8549
8550 /* collect all cached left and right hand side changes */
8551 nchg = 0;
8552 for( i = 0; i < lp->nchgrows; ++i )
8553 {
8554 row = lp->chgrows[i];
8555 assert(row != NULL);
8556
8557 if( row->lpipos >= 0 )
8558 {
8559#ifndef NDEBUG
8560 /* do not check consistency of data with LPI in case of LPI=none */
8561 if( !lpinone )
8562 {
8563 SCIP_Real lpilhs;
8564 SCIP_Real lpirhs;
8565
8566 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8567 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8568 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8569 }
8570#endif
8571 if( row->lhschanged || row->rhschanged )
8572 {
8573 SCIP_Real newlhs;
8574 SCIP_Real newrhs;
8575
8576 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8577 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8578 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8579 {
8580 assert(nchg < lp->nrows);
8581 ind[nchg] = row->lpipos;
8582 lhs[nchg] = newlhs;
8583 rhs[nchg] = newrhs;
8584 nchg++;
8585 row->flushedlhs = newlhs;
8586 row->flushedrhs = newrhs;
8587 }
8588 row->lhschanged = FALSE;
8589 row->rhschanged = FALSE;
8590 }
8591 }
8592 }
8593
8594 /* change left and right hand sides in LP */
8595 if( nchg > 0 )
8596 {
8597 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8598 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8599
8600 /* mark the LP unsolved */
8601 lp->solved = FALSE;
8602 lp->primalfeasible = FALSE;
8603 lp->primalchecked = FALSE;
8604 lp->lpobjval = SCIP_INVALID;
8606 }
8607
8608 lp->nchgrows = 0;
8609
8610 /* free temporary memory */
8614
8615 return SCIP_OKAY;
8616}
8617
8618/** copy integrality information to the LP */
8619static
8621 SCIP_LP* lp, /**< current LP data */
8622 SCIP_SET* set /**< global SCIP settings */
8623 )
8624{
8625 int i;
8626 int nintegers;
8627 int* integerInfo;
8628 SCIP_VAR* var;
8629
8630 assert(lp != NULL);
8631
8632 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8633
8634 /* count total number of integralities */
8635 nintegers = 0;
8636
8637 for( i = 0; i < lp->ncols; ++i )
8638 {
8639 var = SCIPcolGetVar(lp->cols[i]);
8640 if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) )
8641 {
8642 integerInfo[i] = 1;
8643 ++nintegers;
8644 }
8645 else
8646 integerInfo[i] = 0;
8647 }
8648
8649 /* only pass integrality information if integer variables are present */
8650 if( nintegers > 0 )
8651 {
8652 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8653 }
8654 else
8655 {
8657 }
8658
8659 SCIPsetFreeBufferArray(set, &integerInfo);
8660
8661 /* mark integralities to be updated */
8663
8664 return SCIP_OKAY;
8665}
8666
8667/** applies all cached changes to the LP solver */
8669 SCIP_LP* lp, /**< current LP data */
8670 BMS_BLKMEM* blkmem, /**< block memory */
8671 SCIP_SET* set, /**< global SCIP settings */
8672 SCIP_PROB* prob, /**< problem data */
8673 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8674 )
8675{
8676 assert(lp != NULL);
8677 assert(blkmem != NULL);
8678
8679 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",
8680 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8681
8682 if( !lp->flushed )
8683 {
8684 lp->flushdeletedcols = FALSE;
8685 lp->flushaddedcols = FALSE;
8686 lp->flushdeletedrows = FALSE;
8687 lp->flushaddedrows = FALSE;
8688
8690 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8693 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8694 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8695
8696 lp->flushed = TRUE;
8697
8698 checkLinks(lp);
8699 }
8700
8701 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8702 * we want to re-optimize the LP even if nothing else has changed
8703 */
8704 if( !lpCutoffDisabled(set, prob, lp) && lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 ) /*lint !e777*/
8705 {
8706 lp->solved = FALSE;
8708 }
8709
8710 assert(lp->nlpicols == lp->ncols);
8711 assert(lp->lpifirstchgcol == lp->nlpicols);
8712 assert(lp->nlpirows == lp->nrows);
8713 assert(lp->lpifirstchgrow == lp->nlpirows);
8714 assert(lp->nchgcols == 0);
8715 assert(lp->nchgrows == 0);
8716#ifndef NDEBUG
8717 {
8718 int ncols;
8719 int nrows;
8720
8721 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8722 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8723 assert(ncols == lp->ncols);
8724 assert(nrows == lp->nrows);
8725 }
8726#endif
8727
8728 return SCIP_OKAY;
8729}
8730
8731/** marks the LP to be flushed, even if the LP thinks it is not flushed */
8733 SCIP_LP* lp, /**< current LP data */
8734 SCIP_SET* set /**< global SCIP settings */
8735 )
8736{
8737#ifndef NDEBUG
8738 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8739#endif
8740 int i;
8741
8742 assert(lp != NULL);
8743
8744#ifndef NDEBUG
8745 /* check, if there are really no column or row deletions or coefficient changes left */
8746 while( lp->lpifirstchgcol < lp->nlpicols
8747 && lp->lpifirstchgcol < lp->ncols
8748 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8749 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8750 {
8751 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8752 lp->lpifirstchgcol++;
8753 }
8754 assert(lp->nlpicols == lp->lpifirstchgcol);
8755
8756 while( lp->lpifirstchgrow < lp->nlpirows
8757 && lp->lpifirstchgrow < lp->nrows
8758 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8759 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8760 {
8761 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8762 lp->lpifirstchgrow++;
8763 }
8764 assert(lp->nlpirows == lp->lpifirstchgrow);
8765#endif
8766
8767 lp->lpifirstchgcol = lp->nlpicols;
8768 lp->lpifirstchgrow = lp->nlpirows;
8769
8770 /* check, if there are really no column or row additions left */
8771 assert(lp->ncols == lp->nlpicols);
8772 assert(lp->nrows == lp->nlpirows);
8773
8774 /* mark the changed columns to be unchanged, and check, if this is really correct */
8775 for( i = 0; i < lp->nchgcols; ++i )
8776 {
8777 SCIP_COL* col;
8778
8779 col = lp->chgcols[i];
8780 assert(col != NULL);
8781 assert(col->var != NULL);
8783 assert(SCIPvarGetCol(col->var) == col);
8784
8785 if( col->lpipos >= 0 )
8786 {
8787#ifndef NDEBUG
8788 /* do not check consistency of data with LPI in case of LPI=none */
8789 if( !lpinone )
8790 {
8791 SCIP_Real lpiobj;
8792 SCIP_Real lpilb;
8793 SCIP_Real lpiub;
8794
8795 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8796 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8797 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8798 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8799 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8800 assert(col->flushedobj == col->obj); /*lint !e777*/
8801 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8802 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8803 }
8804#endif
8805 col->objchanged = FALSE;
8806 col->lbchanged = FALSE;
8807 col->ubchanged = FALSE;
8808 }
8809 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8810 }
8811 lp->nchgcols = 0;
8812
8813 /* mark the changed rows to be unchanged, and check, if this is really correct */
8814 for( i = 0; i < lp->nchgrows; ++i )
8815 {
8816 SCIP_ROW* row;
8817
8818 row = lp->chgrows[i];
8819 assert(row != NULL);
8820
8821 if( row->lpipos >= 0 )
8822 {
8823#ifndef NDEBUG
8824 /* do not check consistency of data with LPI in case of LPI=none */
8825 if( !lpinone )
8826 {
8827 SCIP_Real lpilhs;
8828 SCIP_Real lpirhs;
8829
8830 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8831 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8832 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8833 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8834 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8835 }
8836#endif
8837 row->lhschanged = FALSE;
8838 row->rhschanged = FALSE;
8839 }
8840 }
8841 lp->nchgrows = 0;
8842
8843 /* mark the LP to be flushed */
8844 lp->flushed = TRUE;
8845
8846 checkLinks(lp);
8847
8848 return SCIP_OKAY;
8849}
8850
8851
8852
8853
8854/*
8855 * LP methods
8856 */
8857
8858/** updates link data after addition of column */
8859static
8861 SCIP_COL* col, /**< LP column */
8862 SCIP_SET* set /**< global SCIP settings */
8863 )
8864{
8865 SCIP_ROW* row;
8866 int i;
8867 int pos;
8868
8869 assert(col != NULL);
8870 assert(col->lppos >= 0);
8871
8872 /* update column arrays of all linked rows */
8873 for( i = 0; i < col->len; ++i )
8874 {
8875 pos = col->linkpos[i];
8876 if( pos >= 0 )
8877 {
8878 row = col->rows[i];
8879 assert(row != NULL);
8880 assert(row->linkpos[pos] == i);
8881 assert(row->cols[pos] == col);
8882 assert(row->nlpcols <= pos && pos < row->len);
8883
8884 row->nlpcols++;
8885 rowSwapCoefs(row, pos, row->nlpcols-1);
8886 assert(row->cols[row->nlpcols-1] == col);
8887
8888 /* if no swap was necessary, mark lpcols to be unsorted */
8889 if( pos == row->nlpcols-1 )
8890 row->lpcolssorted = FALSE;
8891
8892 /* update norms */
8893 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8894 }
8895 }
8896}
8897
8898/** updates link data after addition of row */
8899static
8901 SCIP_ROW* row /**< LP row */
8902 )
8903{
8904 SCIP_COL* col;
8905 int i;
8906 int pos;
8907
8908 assert(row != NULL);
8909 assert(row->lppos >= 0);
8910
8911 /* update row arrays of all linked columns */
8912 for( i = 0; i < row->len; ++i )
8913 {
8914 pos = row->linkpos[i];
8915 if( pos >= 0 )
8916 {
8917 col = row->cols[i];
8918 assert(col != NULL);
8919 assert(col->linkpos[pos] == i);
8920 assert(col->rows[pos] == row);
8921 assert(col->nlprows <= pos && pos < col->len);
8922
8923 col->nlprows++;
8924 colSwapCoefs(col, pos, col->nlprows-1);
8925
8926 /* if no swap was necessary, mark lprows to be unsorted */
8927 if( pos == col->nlprows-1 )
8928 col->lprowssorted = FALSE;
8929 }
8930 }
8931}
8932
8933/** updates link data after removal of column */
8934static
8936 SCIP_COL* col, /**< LP column */
8937 SCIP_SET* set /**< global SCIP settings */
8938 )
8939{
8940 SCIP_ROW* row;
8941 int i;
8942 int pos;
8943
8944 assert(col != NULL);
8945 assert(col->lppos == -1);
8946
8947 /* update column arrays of all linked rows */
8948 for( i = 0; i < col->len; ++i )
8949 {
8950 pos = col->linkpos[i];
8951 if( pos >= 0 )
8952 {
8953 row = col->rows[i];
8954 assert(row != NULL);
8955 assert(row->linkpos[pos] == i);
8956 assert(row->cols[pos] == col);
8957 assert(0 <= pos && pos < row->nlpcols);
8958
8959 /* update norms */
8960 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8961
8962 row->nlpcols--;
8963 rowSwapCoefs(row, pos, row->nlpcols);
8964
8965 /* if no swap was necessary, mark nonlpcols to be unsorted */
8966 if( pos == row->nlpcols )
8967 row->nonlpcolssorted = FALSE;
8968 }
8969 }
8970}
8971
8972/** updates link data after removal of row */
8973static
8975 SCIP_ROW* row /**< LP row */
8976 )
8977{
8978 SCIP_COL* col;
8979 int i;
8980 int pos;
8981
8982 assert(row != NULL);
8983 assert(row->lppos == -1);
8984
8985 /* update row arrays of all linked columns */
8986 for( i = 0; i < row->len; ++i )
8987 {
8988 pos = row->linkpos[i];
8989 if( pos >= 0 )
8990 {
8991 col = row->cols[i];
8992 assert(col != NULL);
8993 assert(0 <= pos && pos < col->nlprows);
8994 assert(col->linkpos[pos] == i);
8995 assert(col->rows[pos] == row);
8996
8997 col->nlprows--;
8998 colSwapCoefs(col, pos, col->nlprows);
8999
9000 /* if no swap was necessary, mark lprows to be unsorted */
9001 if( pos == col->nlprows )
9002 col->nonlprowssorted = FALSE;
9003 }
9004 }
9005}
9006
9007static
9009 SCIP_LP* lp, /**< LP data object */
9010 int initsize /**< initial size of the arrays */
9011 )
9012{
9013 assert(lp != NULL);
9014 assert(lp->divechgsides == NULL);
9015 assert(lp->divechgsidetypes == NULL);
9016 assert(lp->divechgrows == NULL);
9017 assert(lp->ndivechgsides == 0);
9018 assert(lp->divechgsidessize == 0);
9019 assert(initsize > 0);
9020
9021 lp->divechgsidessize = initsize;
9025
9026 return SCIP_OKAY;
9027}
9028
9029static
9031 SCIP_LP* lp, /**< LP data object */
9032 int minsize, /**< minimal number of elements */
9033 SCIP_Real growfact /**< growing factor */
9034 )
9035{
9036 assert(lp != NULL);
9037 assert(lp->divechgsides != NULL);
9038 assert(lp->divechgsidetypes != NULL);
9039 assert(lp->divechgrows != NULL);
9040 assert(lp->ndivechgsides > 0);
9041 assert(lp->divechgsidessize > 0);
9042 assert(minsize > 0);
9043
9044 if( minsize <= lp->divechgsidessize )
9045 return SCIP_OKAY;
9046
9047 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9051
9052 return SCIP_OKAY;
9053}
9054
9055static
9057 SCIP_LP* lp /**< LP data object */
9058 )
9059{
9060 assert(lp != NULL);
9061 assert(lp->divechgsides != NULL);
9062 assert(lp->divechgsidetypes != NULL);
9063 assert(lp->divechgrows != NULL);
9064 assert(lp->ndivechgsides == 0);
9065 assert(lp->divechgsidessize > 0);
9066
9070 lp->divechgsidessize = 0;
9071}
9072
9073#define DIVESTACKINITSIZE 100
9074
9075/** creates empty LP data object */
9077 SCIP_LP** lp, /**< pointer to LP data object */
9078 SCIP_SET* set, /**< global SCIP settings */
9079 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
9080 SCIP_STAT* stat, /**< problem statistics */
9081 const char* name /**< problem name */
9082 )
9083{
9084 SCIP_Bool success;
9085
9086 assert(lp != NULL);
9087 assert(set != NULL);
9088 assert(stat != NULL);
9089 assert(name != NULL);
9090
9092
9093 /* open LP Solver interface */
9094 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9095
9096 (*lp)->lpicols = NULL;
9097 (*lp)->lpirows = NULL;
9098 (*lp)->chgcols = NULL;
9099 (*lp)->chgrows = NULL;
9100 (*lp)->cols = NULL;
9101 (*lp)->soldirection = NULL;
9102 (*lp)->lazycols = NULL;
9103 (*lp)->rows = NULL;
9104 (*lp)->lpobjval = 0.0;
9105 (*lp)->glbpseudoobjval = 0.0;
9106 (*lp)->relglbpseudoobjval = 0.0;
9107 (*lp)->glbpseudoobjvalid = TRUE;
9108 (*lp)->glbpseudoobjvalinf = 0;
9109 (*lp)->pseudoobjval = 0.0;
9110 (*lp)->relpseudoobjval = 0.0;
9111 (*lp)->pseudoobjvalid = TRUE;
9112 (*lp)->pseudoobjvalinf = 0;
9113 (*lp)->looseobjval = 0.0;
9114 (*lp)->rellooseobjval = 0.0;
9115 (*lp)->looseobjvalid = TRUE;
9116 (*lp)->looseobjvalinf = 0;
9117 (*lp)->nloosevars = 0;
9118 (*lp)->rootlpobjval = SCIP_INVALID;
9119 (*lp)->rootlooseobjval = SCIP_INVALID;
9120 (*lp)->cutoffbound = SCIPsetInfinity(set);
9121 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9122 SCIPlpResetFeastol(*lp, set);
9123 (*lp)->validdegeneracylp = -1;
9124 (*lp)->objsqrnorm = 0.0;
9125 (*lp)->objsumnorm = 0.0;
9126 (*lp)->lpicolssize = 0;
9127 (*lp)->nlpicols = 0;
9128 (*lp)->lpirowssize = 0;
9129 (*lp)->nlpirows = 0;
9130 (*lp)->lpifirstchgcol = 0;
9131 (*lp)->lpifirstchgrow = 0;
9132 (*lp)->colssize = 0;
9133 (*lp)->soldirectionsize = 0;
9134 (*lp)->ncols = 0;
9135 (*lp)->lazycolssize = 0;
9136 (*lp)->nlazycols = 0;
9137 (*lp)->rowssize = 0;
9138 (*lp)->nrows = 0;
9139 (*lp)->chgcolssize = 0;
9140 (*lp)->nchgcols = 0;
9141 (*lp)->chgrowssize = 0;
9142 (*lp)->nchgrows = 0;
9143 (*lp)->firstnewcol = 0;
9144 (*lp)->firstnewrow = 0;
9145 (*lp)->nremovablecols = 0;
9146 (*lp)->nremovablerows = 0;
9147 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9148 (*lp)->validfarkaslp = -1;
9149 (*lp)->validsoldirlp = -1;
9150 (*lp)->validsoldirsol = NULL;
9151 (*lp)->objsqrnormunreliable = FALSE;
9152 (*lp)->flushdeletedcols = FALSE;
9153 (*lp)->flushaddedcols = FALSE;
9154 (*lp)->flushdeletedrows = FALSE;
9155 (*lp)->flushaddedrows = FALSE;
9156 (*lp)->updateintegrality = TRUE;
9157 (*lp)->flushed = TRUE;
9158 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9159 (*lp)->solved = TRUE;
9160 (*lp)->primalfeasible = TRUE;
9161 (*lp)->primalchecked = TRUE;
9162 (*lp)->dualfeasible = TRUE;
9163 (*lp)->dualchecked = TRUE;
9164 (*lp)->solisbasic = FALSE;
9165 (*lp)->rootlpisrelax = TRUE;
9166 (*lp)->isrelax = TRUE;
9167 (*lp)->installing = FALSE;
9168 (*lp)->strongbranching = FALSE;
9169 (*lp)->strongbranchprobing = FALSE;
9170 (*lp)->probing = FALSE;
9171 (*lp)->diving = FALSE;
9172 (*lp)->divingobjchg = FALSE;
9173 (*lp)->divinglazyapplied = FALSE;
9174 (*lp)->divelpistate = NULL;
9175 (*lp)->divelpwasprimfeas = TRUE;
9176 (*lp)->divelpwasprimchecked = TRUE;
9177 (*lp)->divelpwasdualfeas = TRUE;
9178 (*lp)->divelpwasdualchecked = TRUE;
9179 (*lp)->divechgsides = NULL;
9180 (*lp)->divechgsidetypes = NULL;
9181 (*lp)->divechgrows = NULL;
9182 (*lp)->ndivechgsides = 0;
9183 (*lp)->divechgsidessize = 0;
9184 (*lp)->ndivingrows = 0;
9185 (*lp)->divinglpiitlim = INT_MAX;
9186 (*lp)->resolvelperror = FALSE;
9187 (*lp)->divenolddomchgs = 0;
9188 (*lp)->adjustlpval = FALSE;
9189 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9190 (*lp)->lpifeastol = (*lp)->feastol;
9191 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9192 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9193 (*lp)->lpifromscratch = FALSE;
9194 (*lp)->lpifastmip = set->lp_fastmip;
9195 (*lp)->lpiscaling = set->lp_scaling;
9196 (*lp)->lpipresolving = set->lp_presolving;
9197 (*lp)->lpilpinfo = set->disp_lpinfo;
9198 (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9199 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9200 (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9201 (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9202 (*lp)->lpimarkowitz = set->lp_markowitz;
9203 (*lp)->lpiitlim = INT_MAX;
9204 (*lp)->lpipricing = SCIP_PRICING_AUTO;
9205 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9206 (*lp)->lpithreads = set->lp_threads;
9207 (*lp)->lpitiming = (int) set->time_clocktype;
9208 (*lp)->lpirandomseed = set->random_randomseed;
9209 (*lp)->storedsolvals = NULL;
9210
9211 /* allocate arrays for diving */
9213
9214 /* set default parameters in LP solver */
9215 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9216 if( !success )
9217 {
9218 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9219 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9221 }
9222 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9223 (*lp)->lpihasfeastol = success;
9224 if( !success )
9225 {
9226 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9227 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9229 }
9230 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9231 (*lp)->lpihasdualfeastol = success;
9232 if( !success )
9233 {
9234 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9235 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9237 }
9238 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9239 (*lp)->lpihasbarrierconvtol = success;
9240 if( !success )
9241 {
9242 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9243 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9245 }
9246 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9247 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9248 (*lp)->lpihasfastmip = success;
9249 if( !success )
9250 {
9251 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9252 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9254 }
9255 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9256 (*lp)->lpihasscaling = success;
9257 if( !success )
9258 {
9259 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9260 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9262 }
9263 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9264 (*lp)->lpihaspresolving = success;
9265 if( !success )
9266 {
9267 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9268 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9270 }
9271 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9272 if( !success )
9273 {
9274 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9275 "LP Solver <%s>: clock type cannot be set\n",
9277 }
9278 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9279 if( !success )
9280 {
9281 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9282 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9284 }
9285 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9286 if( !success )
9287 {
9288 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9289 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9291 }
9292 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9293 if( !success )
9294 {
9295 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9296 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9298 }
9299 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9300 (*lp)->lpihasrowrep = success;
9301 if( !success )
9302 {
9303 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9304 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9306 }
9307 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9308 (*lp)->lpihaspolishing = success;
9309 if( !success )
9310 {
9311 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9312 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9314 }
9315 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9316 (*lp)->lpihasrefactor = success;
9317 if( !success )
9318 {
9319 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9320 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9322 }
9323 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9324 if( !success )
9325 {
9326 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9327 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9329 }
9330 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9331 if( !success )
9332 {
9333 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9334 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9336 }
9337 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9338 if( !success )
9339 {
9340 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9341 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9343 }
9344 /* keep the default LP random seed if this parameter is set to 0 (current default) */
9345 if( (*lp)->lpirandomseed != 0 )
9346 {
9347 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9348 if( !success )
9349 {
9350 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9351 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9353 }
9354 }
9355
9356 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9357 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9358 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9359 {
9360 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9362 }
9363
9364 return SCIP_OKAY;
9365}
9366
9367/** frees LP data object */
9369 SCIP_LP** lp, /**< pointer to LP data object */
9370 BMS_BLKMEM* blkmem, /**< block memory */
9371 SCIP_SET* set, /**< global SCIP settings */
9372 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9373 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9374 )
9375{
9376 int i;
9377
9378 assert(lp != NULL);
9379 assert(*lp != NULL);
9380
9381 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9382
9384
9385 /* release LPI rows */
9386 for( i = 0; i < (*lp)->nlpirows; ++i )
9387 {
9388 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9389 }
9390
9391 if( (*lp)->lpi != NULL )
9392 {
9393 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9394 }
9395
9396 BMSfreeMemoryNull(&(*lp)->storedsolvals);
9397 BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9398 BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9399 BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9400 BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9401 BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9402 BMSfreeMemoryArrayNull(&(*lp)->cols);
9403 BMSfreeMemoryArrayNull(&(*lp)->rows);
9404 BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9405 BMSfreeMemory(lp);
9406
9407 return SCIP_OKAY;
9408}
9409
9410/** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9411 * changes to the LP solver
9412 */
9414 SCIP_LP* lp, /**< LP data */
9415 BMS_BLKMEM* blkmem, /**< block memory */
9416 SCIP_SET* set, /**< global SCIP settings */
9417 SCIP_PROB* prob, /**< problem data */
9418 SCIP_STAT* stat, /**< problem statistics */
9419 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9420 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9421 )
9422{
9423 assert(stat != NULL);
9424
9425 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9426 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9427
9428 /* mark the empty LP to be solved */
9430 lp->lpobjval = 0.0;
9431 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9432 lp->validfarkaslp = -1;
9433 lp->validdegeneracylp = -1;
9434 lp->validsoldirlp = -1;
9435 lp->validsoldirsol = NULL;
9436 lp->solved = TRUE;
9437 lp->primalfeasible = TRUE;
9438 lp->primalchecked = TRUE;
9439 lp->dualfeasible = TRUE;
9440 lp->dualchecked = TRUE;
9441 lp->solisbasic = FALSE;
9443
9444 return SCIP_OKAY;
9445}
9446
9447/** adds a column to the LP */
9449 SCIP_LP* lp, /**< LP data */
9450 SCIP_SET* set, /**< global SCIP settings */
9451 SCIP_COL* col, /**< LP column */
9452 int depth /**< depth in the tree where the column addition is performed */
9453 )
9454{
9455 assert(lp != NULL);
9456 assert(!lp->diving);
9457 assert(col != NULL);
9458 assert(col->len == 0 || col->rows != NULL);
9459 assert(col->lppos == -1);
9460 assert(col->var != NULL);
9462 assert(SCIPvarGetCol(col->var) == col);
9463 assert(SCIPvarIsIntegral(col->var) == col->integral);
9464
9465 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9466#ifdef SCIP_DEBUG
9467 {
9468 int i;
9469 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9470 for( i = 0; i < col->len; ++i )
9471 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9473 }
9474#endif
9475
9476 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9477 lp->cols[lp->ncols] = col;
9478 col->lppos = lp->ncols;
9479 col->lpdepth = depth;
9480 col->age = 0;
9481 lp->ncols++;
9482 if( col->removable )
9483 lp->nremovablecols++;
9484
9485 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9486 {
9488 lp->lazycols[lp->nlazycols] = col;
9489 lp->nlazycols++;
9490 }
9491
9492 /* mark the current LP unflushed */
9493 lp->flushed = FALSE;
9494
9495 /* update column arrays of all linked rows */
9496 colUpdateAddLP(col, set);
9497
9498 /* update the objective function vector norms */
9499 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9500
9501 checkLinks(lp);
9502
9503 return SCIP_OKAY;
9504}
9505
9506/** adds a row to the LP and captures it */
9508 SCIP_LP* lp, /**< LP data */
9509 BMS_BLKMEM* blkmem, /**< block memory buffers */
9510 SCIP_SET* set, /**< global SCIP settings */
9511 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9512 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9513 SCIP_ROW* row, /**< LP row */
9514 int depth /**< depth in the tree where the row addition is performed */
9515 )
9516{
9517 assert(lp != NULL);
9518 assert(row != NULL);
9519 assert(row->len == 0 || row->cols != NULL);
9520 assert(row->lppos == -1);
9521
9522 SCIProwCapture(row);
9523 SCIProwLock(row);
9524
9525 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9526#ifdef SCIP_DEBUG
9527 {
9528 int i;
9529 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs);
9530 for( i = 0; i < row->len; ++i )
9531 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9532 if( !SCIPsetIsZero(set, row->constant) )
9533 SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9534 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9535 }
9536#endif
9537
9538 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9539 lp->rows[lp->nrows] = row;
9540 row->lppos = lp->nrows;
9541 row->lpdepth = depth;
9542 row->age = 0;
9543 lp->nrows++;
9544 if( row->removable )
9545 lp->nremovablerows++;
9546
9547 /* mark the current LP unflushed */
9548 lp->flushed = FALSE;
9549
9550 /* update row arrays of all linked columns */
9551 rowUpdateAddLP(row);
9552
9553 checkLinks(lp);
9554
9555 rowCalcNorms(row, set);
9556
9557 /* check, if row addition to LP events are tracked
9558 * if so, issue ROWADDEDLP event
9559 */
9560 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9561 {
9562 SCIP_EVENT* event;
9563
9564 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9565 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9566 }
9567
9568 return SCIP_OKAY;
9569}
9570
9571
9572#ifndef NDEBUG
9573/** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9574 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9575 * the lazycols array
9576 */
9577static
9579 SCIP_LP* lp, /**< LP data */
9580 SCIP_SET* set /**< global SCIP settings */
9581 )
9582{
9583 SCIP_Bool contained;
9584 int c;
9585 int i;
9586
9587 assert(lp != NULL);
9588
9589 /* check if each column in the lazy column array has a counter part in the column array */
9590 for( i = 0; i < lp->nlazycols; ++i )
9591 {
9592 /* check if each lazy column has at least on lazy bound */
9593 assert(lp->lazycols[i] != NULL);
9594 assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9595
9596 contained = FALSE;
9597 for( c = 0; c < lp->ncols; ++c )
9598 {
9599 if( lp->lazycols[i] == lp->cols[c] )
9600 {
9601 assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9602 contained = TRUE;
9603 }
9604 }
9605 assert(contained);
9606 }
9607
9608 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9609 * array */
9610 for( c = 0; c < lp->ncols; ++c )
9611 {
9612 contained = FALSE;
9613 assert(lp->cols[c] != NULL);
9614
9615 for( i = 0; i < lp->nlazycols; ++i )
9616 {
9617 if( lp->lazycols[i] == lp->cols[c] )
9618 {
9619 contained = TRUE;
9620 }
9621 }
9622
9623 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9624 }
9625}
9626#else
9627#define checkLazyColArray(lp, set) /**/
9628#endif
9629
9630/** removes all columns after the given number of cols from the LP */
9632 SCIP_LP* lp, /**< LP data */
9633 SCIP_SET* set, /**< global SCIP settings */
9634 int newncols /**< new number of columns in the LP */
9635 )
9636{
9637 SCIP_COL* col;
9638 int c;
9639
9640 assert(lp != NULL);
9641
9642 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9643 assert(0 <= newncols);
9644 assert(newncols <= lp->ncols);
9645
9646 if( newncols < lp->ncols )
9647 {
9648 assert(!lp->diving);
9649
9650 for( c = lp->ncols-1; c >= newncols; --c )
9651 {
9652 col = lp->cols[c];
9653 assert(col != NULL);
9654 assert(col->len == 0 || col->rows != NULL);
9655 assert(col->var != NULL);
9657 assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9658 assert(col->lppos == c);
9659
9660 /* mark column to be removed from the LP */
9661 col->lppos = -1;
9662 col->lpdepth = -1;
9663 lp->ncols--;
9664
9665 /* count removable columns */
9666 if( col->removable )
9667 lp->nremovablecols--;
9668
9669 /* update column arrays of all linked rows */
9670 colUpdateDelLP(col, set);
9671
9672 /* update the objective function vector norms */
9673 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9674 }
9675 assert(lp->ncols == newncols);
9676 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9677
9678 /* remove columns which are deleted from the lazy column array */
9679 c = 0;
9680 while( c < lp->nlazycols )
9681 {
9682 if( lp->lazycols[c]->lppos < 0 )
9683 {
9684 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9685 lp->nlazycols--;
9686 }
9687 else
9688 c++;
9689 }
9690
9691 /* mark the current LP unflushed */
9692 lp->flushed = FALSE;
9693
9695 checkLinks(lp);
9696 }
9697 assert(lp->nremovablecols <= lp->ncols);
9698
9699 return SCIP_OKAY;
9700}
9701
9702/** removes and releases all rows after the given number of rows from the LP */
9704 SCIP_LP* lp, /**< LP data */
9705 BMS_BLKMEM* blkmem, /**< block memory */
9706 SCIP_SET* set, /**< global SCIP settings */
9707 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9708 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9709 int newnrows /**< new number of rows in the LP */
9710 )
9711{
9712 SCIP_ROW* row;
9713 int r;
9714
9715 assert(lp != NULL);
9716 assert(0 <= newnrows && newnrows <= lp->nrows);
9717
9718 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9719 if( newnrows < lp->nrows )
9720 {
9721 for( r = lp->nrows-1; r >= newnrows; --r )
9722 {
9723 row = lp->rows[r];
9724 assert(row != NULL);
9725 assert(row->len == 0 || row->cols != NULL);
9726 assert(row->lppos == r);
9727
9728 /* mark row to be removed from the LP */
9729 row->lppos = -1;
9730 row->lpdepth = -1;
9731 lp->nrows--;
9732
9733 /* count removable rows */
9734 if( row->removable )
9735 lp->nremovablerows--;
9736
9737 /* update row arrays of all linked columns */
9738 rowUpdateDelLP(row);
9739
9740 SCIProwUnlock(lp->rows[r]);
9741
9742 /* check, if row deletion events are tracked
9743 * if so, issue ROWDELETEDLP event
9744 */
9745 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9746 {
9747 SCIP_EVENT* event;
9748
9749 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9750 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9751 }
9752
9753 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9754 }
9755 assert(lp->nrows == newnrows);
9756 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9757
9758 /* mark the current LP unflushed */
9759 lp->flushed = FALSE;
9760
9761 checkLinks(lp);
9762 }
9763 assert(lp->nremovablerows <= lp->nrows);
9764
9765 return SCIP_OKAY;
9766}
9767
9768/** removes all columns and rows from LP, releases all rows */
9770 SCIP_LP* lp, /**< LP data */
9771 BMS_BLKMEM* blkmem, /**< block memory */
9772 SCIP_SET* set, /**< global SCIP settings */
9773 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9774 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9775 )
9776{
9777 assert(lp != NULL);
9778 assert(!lp->diving);
9779
9780 SCIPsetDebugMsg(set, "clearing LP\n");
9781 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9782 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9783
9784 return SCIP_OKAY;
9785}
9786
9787/** remembers number of columns and rows to track the newly added ones */
9789 SCIP_LP* lp /**< current LP data */
9790 )
9791{
9792 assert(lp != NULL);
9793 assert(!lp->diving);
9794
9795 lp->firstnewrow = lp->nrows;
9796 lp->firstnewcol = lp->ncols;
9797}
9798
9799/** sets the remembered number of columns and rows to the given values */
9801 SCIP_LP* lp, /**< current LP data */
9802 int nrows, /**< number of rows to set the size marker to */
9803 int ncols /**< number of columns to set the size marker to */
9804 )
9805{
9806 assert(lp != NULL);
9807 assert(!lp->diving);
9808
9809 lp->firstnewrow = nrows;
9810 lp->firstnewcol = ncols;
9811}
9812
9813/** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9815 SCIP_LP* lp, /**< LP data */
9816 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9817 )
9818{
9819 assert(lp != NULL);
9820 assert(lp->flushed);
9821 assert(lp->solved);
9822 assert(lp->solisbasic);
9823 assert(basisind != NULL);
9824
9825 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9826
9827 return SCIP_OKAY;
9828}
9829
9830/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9832 SCIP_LP* lp, /**< LP data */
9833 int* cstat, /**< array to store column basis status, or NULL */
9834 int* rstat /**< array to store row basis status, or NULL */
9835 )
9836{
9837 assert(lp != NULL);
9838 assert(lp->flushed);
9839 assert(lp->solved);
9840 assert(lp->solisbasic);
9841
9842 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9843
9844 return SCIP_OKAY;
9845}
9846
9847/** gets a row from the inverse basis matrix B^-1 */
9849 SCIP_LP* lp, /**< LP data */
9850 int r, /**< row number */
9851 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9852 int* inds, /**< array to store the non-zero indices, or NULL */
9853 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9854 * (-1: if we do not store sparsity informations) */
9855 )
9856{
9857 assert(lp != NULL);
9858 assert(lp->flushed);
9859 assert(lp->solved);
9860 assert(lp->solisbasic);
9861 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9862 assert(coef != NULL);
9863
9864 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9865
9866 return SCIP_OKAY;
9867}
9868
9869/** gets a column from the inverse basis matrix B^-1 */
9871 SCIP_LP* lp, /**< LP data */
9872 int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9873 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9874 * to get the array which links the B^-1 column numbers to the row and
9875 * column numbers of the LP! c must be between 0 and nrows-1, since the
9876 * basis has the size nrows * nrows */
9877 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9878 int* inds, /**< array to store the non-zero indices, or NULL */
9879 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9880 * (-1: if we do not store sparsity informations) */
9881 )
9882{
9883 assert(lp != NULL);
9884 assert(lp->flushed);
9885 assert(lp->solved);
9886 assert(lp->solisbasic);
9887 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9888 assert(coef != NULL);
9889
9890 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9891
9892 return SCIP_OKAY;
9893}
9894
9895/** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9897 SCIP_LP* lp, /**< LP data */
9898 int r, /**< row number */
9899 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9900 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9901 int* inds, /**< array to store the non-zero indices, or NULL */
9902 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9903 * (-1: if we do not store sparsity informations) */
9904 )
9905{
9906 assert(lp != NULL);
9907 assert(lp->flushed);
9908 assert(lp->solved);
9909 assert(lp->solisbasic);
9910 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9911 assert(coef != NULL);
9912
9913 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9914
9915 return SCIP_OKAY;
9916}
9917
9918/** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9919 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9920 */
9922 SCIP_LP* lp, /**< LP data */
9923 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9924 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9925 int* inds, /**< array to store the non-zero indices, or NULL */
9926 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9927 * (-1: if we do not store sparsity informations) */
9928 )
9929{
9930 assert(lp != NULL);
9931 assert(lp->flushed);
9932 assert(lp->solved);
9933 assert(lp->solisbasic);
9934 assert(0 <= c && c < lp->ncols);
9935 assert(coef != NULL);
9936
9937 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9938
9939 return SCIP_OKAY;
9940}
9941
9942/** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9943 * LP row are swapped in the summation
9944 */
9946 SCIP_LP* lp, /**< LP data */
9947 SCIP_SET* set, /**< global SCIP settings */
9948 SCIP_PROB* prob, /**< problem data */
9949 SCIP_Real* weights, /**< row weights in row summation */
9950 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9951 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9952 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9953 )
9954{
9955 SCIP_ROW* row;
9956 int r;
9957 int i;
9958 int idx;
9959 SCIP_Bool lhsinfinite;
9960 SCIP_Bool rhsinfinite;
9961
9962 assert(lp != NULL);
9963 assert(prob != NULL);
9964 assert(weights != NULL);
9965 assert(sumcoef != NULL);
9966 assert(sumlhs != NULL);
9967 assert(sumrhs != NULL);
9968
9969 /**@todo test, if a column based summation is faster */
9970
9971 SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9972 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9973 *sumlhs = 0.0;
9974 *sumrhs = 0.0;
9975 lhsinfinite = FALSE;
9976 rhsinfinite = FALSE;
9977 for( r = 0; r < lp->nrows; ++r )
9978 {
9979 if( !SCIPsetIsZero(set, weights[r]) )
9980 {
9981 row = lp->rows[r];
9982 assert(row != NULL);
9983 assert(row->len == 0 || row->cols != NULL);
9984 assert(row->len == 0 || row->cols_index != NULL);
9985 assert(row->len == 0 || row->vals != NULL);
9986
9987 /* add the row coefficients to the sum */
9988 for( i = 0; i < row->len; ++i )
9989 {
9990 assert(row->cols[i] != NULL);
9991 assert(row->cols[i]->var != NULL);
9992 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9993 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9994 assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9995 idx = row->cols[i]->var_probindex;
9996 assert(0 <= idx && idx < prob->nvars);
9997 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
9998 }
9999
10000 /* add the row sides to the sum, depending on the sign of the weight */
10001 if( weights[r] > 0.0 )
10002 {
10003 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10004 if( !lhsinfinite )
10005 (*sumlhs) += weights[r] * (row->lhs - row->constant);
10006 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10007 if( !rhsinfinite )
10008 (*sumrhs) += weights[r] * (row->rhs - row->constant);
10009 }
10010 else
10011 {
10012 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10013 if( !lhsinfinite )
10014 (*sumlhs) += weights[r] * (row->rhs - row->constant);
10015 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10016 if( !rhsinfinite )
10017 (*sumrhs) += weights[r] * (row->lhs - row->constant);
10018 }
10019 }
10020 }
10021
10022 if( lhsinfinite )
10023 *sumlhs = -SCIPsetInfinity(set);
10024 if( rhsinfinite )
10025 *sumrhs = SCIPsetInfinity(set);
10026
10027 return SCIP_OKAY;
10028}
10029
10030/** stores LP state (like basis information) into LP state object */
10032 SCIP_LP* lp, /**< LP data */
10033 BMS_BLKMEM* blkmem, /**< block memory */
10034 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10035 )
10036{
10037 assert(lp != NULL);
10038 assert(lp->flushed);
10039 assert(lp->solved);
10040 assert(blkmem != NULL);
10041 assert(lpistate != NULL);
10042
10043 /* check whether there is no lp */
10044 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10045 *lpistate = NULL;
10046 else
10047 {
10048 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10049 }
10050
10051 return SCIP_OKAY;
10052}
10053
10054/** loads LP state (like basis information) into solver */
10056 SCIP_LP* lp, /**< LP data */
10057 BMS_BLKMEM* blkmem, /**< block memory */
10058 SCIP_SET* set, /**< global SCIP settings */
10059 SCIP_PROB* prob, /**< problem data */
10060 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10061 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
10062 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
10063 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */
10064 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */
10065 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */
10066 )
10067{
10068 assert(lp != NULL);
10069 assert(blkmem != NULL);
10070
10071 /* flush changes to the LP solver */
10072 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10073 assert(lp->flushed);
10074
10075 if( lp->solved && lp->solisbasic )
10076 return SCIP_OKAY;
10077
10078 /* set LPI state in the LP solver */
10079 if( lpistate == NULL )
10080 lp->solisbasic = FALSE;
10081 else
10082 {
10083 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10084 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10085 }
10086 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10087 * flushed and solved, also, e.g., when we hit the iteration limit
10088 */
10089 lp->primalfeasible = wasprimfeas;
10090 lp->primalchecked = wasprimchecked;
10091 lp->dualfeasible = wasdualfeas;
10092 lp->dualchecked = wasdualchecked;
10093
10094 return SCIP_OKAY;
10095}
10096
10097/** frees LP state information */
10099 SCIP_LP* lp, /**< LP data */
10100 BMS_BLKMEM* blkmem, /**< block memory */
10101 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10102 )
10103{
10104 assert(lp != NULL);
10105
10106 if( *lpistate != NULL )
10107 {
10108 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10109 }
10110
10111 return SCIP_OKAY;
10112}
10113
10114/** interrupts the currently ongoing lp solve, or disables the interrupt */
10116 SCIP_LP* lp, /**< LP data */
10117 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10118 )
10119{
10120 assert(lp != NULL);
10121
10122 if( lp->lpi == NULL )
10123 return SCIP_OKAY;
10124
10125 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10126
10127 return SCIP_OKAY;
10128}
10129
10130/** stores pricing norms into LP norms object */
10132 SCIP_LP* lp, /**< LP data */
10133 BMS_BLKMEM* blkmem, /**< block memory */
10134 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10135 )
10136{
10137 assert(lp != NULL);
10138 assert(lp->flushed);
10139 assert(lp->solved);
10140 assert(blkmem != NULL);
10141 assert(lpinorms != NULL);
10142
10143 /* check whether there is no lp */
10144 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10145 *lpinorms = NULL;
10146 else
10147 {
10148 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10149 }
10150
10151 return SCIP_OKAY;
10152}
10153
10154/** loads pricing norms from LP norms object into solver */
10156 SCIP_LP* lp, /**< LP data */
10157 BMS_BLKMEM* blkmem, /**< block memory */
10158 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
10159 )
10160{
10161 assert(lp != NULL);
10162 assert(blkmem != NULL);
10163 assert(lp->flushed);
10164
10165 /* set LPI norms in the LP solver */
10166 if( lpinorms != NULL )
10167 {
10168 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10169 }
10170
10171 return SCIP_OKAY;
10172}
10173
10174/** frees pricing norms information */
10176 SCIP_LP* lp, /**< LP data */
10177 BMS_BLKMEM* blkmem, /**< block memory */
10178 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10179 )
10180{
10181 assert(lp != NULL);
10182
10183 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10184
10185 return SCIP_OKAY;
10186}
10187
10188/** return the current cutoff bound of the lp */
10190 SCIP_LP* lp /**< current LP data */
10191 )
10192{
10193 assert(lp != NULL);
10194
10195 return lp->cutoffbound;
10196}
10197
10198/** sets the upper objective limit of the LP solver */
10200 SCIP_LP* lp, /**< current LP data */
10201 SCIP_SET* set, /**< global SCIP settings */
10202 SCIP_PROB* prob, /**< problem data */
10203 SCIP_Real cutoffbound /**< new upper objective limit */
10204 )
10205{
10206 assert(lp != NULL);
10207
10208 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10209
10210 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10211 * in SCIPendDive())
10212 */
10213 if( SCIPlpDivingObjChanged(lp) )
10214 {
10215 assert(SCIPsetIsInfinity(set, lp->cutoffbound));
10216 return SCIP_OKAY;
10217 }
10218
10219 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10220 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10221 {
10222 /* mark the current solution invalid */
10223 lp->solved = FALSE;
10224 lp->lpobjval = SCIP_INVALID;
10226 }
10227 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10228 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10229 */
10230 else if( !lpCutoffDisabled(set, prob, lp) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
10231 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10232 {
10233 assert(lp->flushed);
10234 assert(lp->solved);
10236 }
10237
10238 lp->cutoffbound = cutoffbound;
10239
10240 return SCIP_OKAY;
10241}
10242
10243/** gets current primal feasibility tolerance of LP solver */
10245 SCIP_LP* lp /**< current LP data */
10246 )
10247{
10248 assert(lp != NULL);
10249
10250 return lp->feastol;
10251}
10252
10253/** sets primal feasibility tolerance of LP solver */
10255 SCIP_LP* lp, /**< current LP data */
10256 SCIP_SET* set, /**< global SCIP settings */
10257 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */
10258 )
10259{
10260 assert(lp != NULL);
10261 assert(newfeastol > 0.0);
10262
10263 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10264
10265 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10266 if( newfeastol < lp->feastol )
10267 {
10268 lp->solved = FALSE;
10270 }
10271
10272 lp->feastol = newfeastol;
10273}
10274
10275/** resets primal feasibility tolerance of LP solver
10276 *
10277 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10278 */
10280 SCIP_LP* lp, /**< current LP data */
10281 SCIP_SET* set /**< global SCIP settings */
10282 )
10283{
10284 assert(lp != NULL);
10285
10286 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10287
10288 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10290 else
10292}
10293
10294/** returns the name of the given LP algorithm */
10295static
10296const char* lpalgoName(
10297 SCIP_LPALGO lpalgo /**< LP algorithm */
10298 )
10299{
10300 switch( lpalgo )
10301 {
10303 return "primal simplex";
10305 return "dual simplex";
10307 return "barrier";
10309 return "barrier/crossover";
10310 default:
10311 SCIPerrorMessage("invalid LP algorithm\n");
10312 SCIPABORT();
10313 return "invalid"; /*lint !e527*/
10314 }
10315}
10316
10317/** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10318static
10320 SCIP_LP* lp, /**< current LP data */
10321 SCIP_SET* set, /**< global SCIP settings */
10322 SCIP_STAT* stat, /**< problem statistics */
10323 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10324 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10325 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10326 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10327 )
10328{
10329 SCIP_Real timedelta;
10330 SCIP_RETCODE retcode;
10331 int iterations;
10332
10333 assert(lp != NULL);
10334 assert(lp->flushed);
10335 assert(set != NULL);
10336 assert(stat != NULL);
10337 assert(lperror != NULL);
10338
10339 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",
10340 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10341
10342 *lperror = FALSE;
10343
10344#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10345 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10346 {
10347 char fname[SCIP_MAXSTRLEN];
10348 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10349 SCIP_CALL( SCIPlpWrite(lp, fname) );
10350 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10351 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10353 }
10354#endif
10355
10356 /* start timing */
10357 if( lp->diving || lp->probing )
10358 {
10359 if( lp->strongbranchprobing )
10361 else
10363
10364 timedelta = 0.0; /* unused for diving or probing */
10365 }
10366 else
10367 {
10369 timedelta = -SCIPclockGetTime(stat->primallptime);
10370 }
10371
10372 /* if this is a call to resolve an instable LP, collect time */
10373 if( instable )
10374 {
10376 }
10377
10378 /* call primal simplex */
10379 retcode = SCIPlpiSolvePrimal(lp->lpi);
10380 if( retcode == SCIP_LPERROR )
10381 {
10382 *lperror = TRUE;
10383 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10384 }
10385 else
10386 {
10387 SCIP_CALL( retcode );
10388 }
10390 lp->solisbasic = TRUE;
10391
10392 /* stop timing */
10393 if( lp->diving || lp->probing )
10394 {
10395 if( lp->strongbranchprobing )
10397 else
10399 }
10400 else
10401 {
10402 timedelta += SCIPclockGetTime(stat->primallptime);
10404 }
10405
10406 if ( instable )
10407 {
10409 }
10410
10411 /* count number of iterations */
10412 SCIPstatIncrement(stat, set, lpcount);
10413 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10414 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10415 {
10416 if( !lp->strongbranchprobing )
10417 {
10418 SCIPstatIncrement(stat, set, nlps);
10419 SCIPstatAdd( stat, set, nlpiterations, iterations );
10420 }
10421 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10422 {
10423 SCIPstatIncrement(stat, set, nprimalresolvelps );
10424 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10425 }
10426 if ( instable )
10427 {
10428 SCIPstatIncrement(stat, set, nresolveinstablelps);
10429 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10430 }
10431 if( lp->diving || lp->probing )
10432 {
10433 if( lp->strongbranchprobing )
10434 {
10435 SCIPstatIncrement(stat, set, nsbdivinglps);
10436 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10437 }
10438 else
10439 {
10440 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10441 SCIPstatIncrement(stat, set, ndivinglps);
10442 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10443 }
10444 }
10445 else
10446 {
10447 SCIPstatIncrement(stat, set, nprimallps);
10448 SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10449 }
10450 }
10451 else
10452 {
10453 if ( ! lp->diving && ! lp->probing )
10454 {
10455 SCIPstatIncrement(stat, set, nprimalzeroitlps);
10456 SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10457 }
10458
10459 if ( keepsol && !(*lperror) )
10460 {
10461 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10462 if( lp->validsollp == stat->lpcount-1 )
10463 lp->validsollp = stat->lpcount;
10464 if( lp->validfarkaslp == stat->lpcount-1 )
10465 lp->validfarkaslp = stat->lpcount;
10466 }
10467 }
10468
10469 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10470 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10471
10472 return SCIP_OKAY;
10473}
10474
10475/** calls LPI to perform dual simplex, measures time and counts iterations */
10476static
10478 SCIP_LP* lp, /**< current LP data */
10479 SCIP_SET* set, /**< global SCIP settings */
10480 SCIP_STAT* stat, /**< problem statistics */
10481 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10482 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10483 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10484 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10485 )
10486{
10487 SCIP_Real timedelta;
10488 SCIP_RETCODE retcode;
10489 int iterations;
10490
10491 assert(lp != NULL);
10492 assert(lp->flushed);
10493 assert(set != NULL);
10494 assert(stat != NULL);
10495 assert(lperror != NULL);
10496
10497 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",
10498 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10499
10500 *lperror = FALSE;
10501
10502#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10503 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10504 {
10505 char fname[SCIP_MAXSTRLEN];
10506 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10507 SCIP_CALL( SCIPlpWrite(lp, fname) );
10508 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10509 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10511 }
10512#endif
10513
10514 /* start timing */
10515 if( lp->diving || lp->probing )
10516 {
10517 if( lp->strongbranchprobing )
10519 else
10521
10522 timedelta = 0.0; /* unused for diving or probing */
10523 }
10524 else
10525 {
10527 timedelta = -SCIPclockGetTime(stat->duallptime);
10528 }
10529
10530 /* if this is a call to resolve an instable LP, collect time */
10531 if ( instable )
10532 {
10534 }
10535
10536 /* call dual simplex */
10537 retcode = SCIPlpiSolveDual(lp->lpi);
10538 if( retcode == SCIP_LPERROR )
10539 {
10540 *lperror = TRUE;
10541 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10542 }
10543 else
10544 {
10545 SCIP_CALL( retcode );
10546 }
10548 lp->solisbasic = TRUE;
10549
10550 /* stop timing */
10551 if( lp->diving || lp->probing )
10552 {
10553 if( lp->strongbranchprobing )
10555 else
10557 }
10558 else
10559 {
10560 timedelta += SCIPclockGetTime(stat->duallptime);
10562 }
10563
10564 if ( instable )
10565 {
10567 }
10568
10569 /* count number of iterations */
10570 SCIPstatIncrement(stat, set, lpcount);
10571 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10572 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10573 {
10574 if( !lp->strongbranchprobing )
10575 {
10576 SCIPstatIncrement(stat, set, nlps);
10577 SCIPstatAdd(stat, set, nlpiterations, iterations);
10578 }
10579 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10580 {
10581 SCIPstatIncrement(stat, set, ndualresolvelps);
10582 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10583 }
10584 if ( instable )
10585 {
10586 SCIPstatIncrement(stat, set, nresolveinstablelps);
10587 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10588 }
10589 if( lp->diving || lp->probing )
10590 {
10591 if( lp->strongbranchprobing )
10592 {
10593 SCIPstatIncrement(stat, set, nsbdivinglps);
10594 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10595 }
10596 else
10597 {
10598 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10599 SCIPstatIncrement(stat, set, ndivinglps);
10600 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10601 }
10602 }
10603 else
10604 {
10605 SCIPstatIncrement(stat, set, nduallps);
10606 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10607 }
10608 }
10609 else
10610 {
10611 if ( ! lp->diving && ! lp->probing )
10612 {
10613 SCIPstatIncrement(stat, set, ndualzeroitlps);
10614 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10615 }
10616
10617 if( keepsol && !(*lperror) )
10618 {
10619 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10620 if( lp->validsollp == stat->lpcount-1 )
10621 lp->validsollp = stat->lpcount;
10622 if( lp->validfarkaslp == stat->lpcount-1 )
10623 lp->validfarkaslp = stat->lpcount;
10624 }
10625 }
10626
10627 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10628 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10629
10630 return SCIP_OKAY;
10631}
10632
10633/** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10634 *
10635 * We follow the approach of the following paper to find a lexicographically minimal optimal
10636 * solution:
10637 *
10638 * Zanette, Fischetti, Balas@n
10639 * Can pure cutting plane algorithms work?@n
10640 * IPCO 2008, Bertinoro, Italy.
10641 *
10642 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10643 * heuristic, i.e., we limit the number of components which are minimized.
10644 *
10645 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10646 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10647 * variables) that have nonzero reduced cost. This fixes the objective function value, because only
10648 * pivots that will not change the objective are allowed afterwards.
10649 *
10650 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10651 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10652 * candidate is found, we set the objective to minimize this variable. We run the primal simplex
10653 * algorithm (since the objective is changed the solution is not dual feasible anymore; if
10654 * variables out of the basis have been fixed to their lower bound, the basis is also not primal
10655 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10656 * reduced cost. We then choose the next variable and iterate.
10657 *
10658 * We stop the process once we do not find candidates or have performed a maximum number of
10659 * iterations.
10660 *
10661 * @todo Does this really produce a lexicographically minimal solution?
10662 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10663 * guarantee that these variables will not be changed in later stages? We can fix these variables
10664 * to their lower bound, but this destroys the basis.
10665 * @todo Should we use lexicographical minimization in diving/probing or not?
10666 */
10667static
10669 SCIP_LP* lp, /**< current LP data */
10670 SCIP_SET* set, /**< global SCIP settings */
10671 SCIP_STAT* stat, /**< problem statistics */
10672 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10673 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10674 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10675 )
10676{
10677 SCIP_Real timedelta;
10678 SCIP_RETCODE retcode;
10679 int totalIterations;
10680 int lexIterations;
10681 int iterations;
10682 int rounds;
10683
10684 assert(lp != NULL);
10685 assert(lp->flushed);
10686 assert(set != NULL);
10687 assert(stat != NULL);
10688 assert(lperror != NULL);
10689
10690 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",
10691 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10692
10693 *lperror = FALSE;
10694
10695 /* start timing */
10696 if( lp->diving || lp->probing )
10697 {
10698 if( lp->strongbranchprobing )
10700 else
10702
10703 timedelta = 0.0; /* unused for diving or probing */
10704 }
10705 else
10706 {
10708 timedelta = -SCIPclockGetTime(stat->duallptime);
10709 }
10710
10711 /* call dual simplex for first lp */
10712 retcode = SCIPlpiSolveDual(lp->lpi);
10713 if( retcode == SCIP_LPERROR )
10714 {
10715 *lperror = TRUE;
10716 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10717 }
10718 else
10719 {
10720 SCIP_CALL( retcode );
10721 }
10722 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10723 totalIterations = iterations;
10724
10725 /* stop timing */
10726 if( lp->diving || lp->probing )
10727 {
10728 if( lp->strongbranchprobing )
10730 else
10732 }
10733 else
10734 {
10735 timedelta += SCIPclockGetTime(stat->duallptime);
10737 }
10738
10739 /* count number of iterations */
10740 SCIPstatIncrement(stat, set, lpcount);
10741 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10742 {
10743 if( lp->strongbranchprobing )
10744 {
10745 SCIPstatAdd(stat, set, nlpiterations, iterations);
10746 }
10747 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10748 {
10749 SCIPstatIncrement(stat, set, ndualresolvelps);
10750 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10751 }
10752 if( lp->diving || lp->probing )
10753 {
10754 if( lp->strongbranchprobing )
10755 {
10756 SCIPstatIncrement(stat, set, nsbdivinglps);
10757 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10758 }
10759 else
10760 {
10761 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10762 SCIPstatIncrement(stat, set, ndivinglps);
10763 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10764 }
10765 }
10766 else
10767 {
10768 SCIPstatIncrement(stat, set, nduallps);
10769 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10770 }
10771 }
10772 else
10773 {
10774 if ( ! lp->diving && ! lp->probing )
10775 {
10776 SCIPstatIncrement(stat, set, ndualzeroitlps);
10777 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10778 }
10779 }
10780 lexIterations = 0;
10781
10782 /* search for lexicographically minimal optimal solution */
10783 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10784 {
10785 SCIP_Bool chooseBasic;
10786 SCIP_Real* primsol;
10787 SCIP_Real* dualsol;
10788 SCIP_Real* redcost;
10789 int* cstat;
10790 int* rstat;
10791 SCIP_Real* newobj;
10792 SCIP_Real* newlb;
10793 SCIP_Real* newub;
10794 SCIP_Real* newlhs;
10795 SCIP_Real* newrhs;
10796 SCIP_Real* oldlb;
10797 SCIP_Real* oldub;
10798 SCIP_Real* oldlhs;
10799 SCIP_Real* oldrhs;
10800 SCIP_Real* oldobj;
10801 SCIP_Bool* fixedc;
10802 SCIP_Bool* fixedr;
10803 int* indcol;
10804 int* indrow;
10805 int* indallcol;
10806 int* indallrow;
10807 int nDualDeg;
10808 int r, c;
10809 int cntcol;
10810 int cntrow;
10811 int nruns;
10812 int pos;
10813
10814 chooseBasic = set->lp_lexdualbasic;
10815
10816 /* start timing */
10818
10819 /* get all solution information */
10820 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10821 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10822 if( chooseBasic )
10823 {
10824 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10825 }
10826 else
10827 primsol = NULL;
10828
10829 /* get basic and nonbasic information */
10832
10833 /* save bounds, lhs/rhs, and objective */
10839 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10840 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10841 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10842
10843 /* get storage for several arrays */
10847
10851
10852 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10853 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10854
10857
10858 /* initialize: set objective to 0, get fixed variables */
10860 for( c = 0; c < lp->nlpicols; ++c )
10861 {
10862 newobj[c] = 0.0;
10863 indallcol[c] = c;
10864 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10865 fixedc[c] = TRUE;
10866 else
10867 fixedc[c] = FALSE;
10868 }
10869
10870 /* initialize: get fixed slack variables */
10871 for( r = 0; r < lp->nlpirows; ++r )
10872 {
10873 indallrow[r] = r;
10874 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10875 fixedr[r] = TRUE;
10876 else
10877 fixedr[r] = FALSE;
10878 }
10879
10880#ifdef DEBUG_LEXDUAL
10881 {
10882 int j;
10883
10884 if( !chooseBasic )
10885 {
10886 assert(primsol == NULL);
10887 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10888 }
10889 assert(primsol != NULL);
10890 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10891 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10892
10893 for( j = 0; j < lp->nlpicols; ++j )
10894 {
10895 if( fixedc[j] )
10896 {
10897 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10898 }
10899 else
10900 {
10901 char type;
10902 switch( (SCIP_BASESTAT) cstat[j] )
10903 {
10905 type = 'l';
10906 break;
10908 type = 'u';
10909 break;
10910 case SCIP_BASESTAT_ZERO:
10911 type = 'z';
10912 break;
10914 type = 'b';
10915 break;
10916 default:
10917 type = '?';
10918 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10919 SCIPABORT();
10920 }
10921 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10922 }
10923 }
10924 SCIPsetDebugMsg(set, "\n\n");
10925
10926 if( !chooseBasic )
10927 {
10928 SCIPsetFreeBufferArray(set, &primsol);
10929 assert(primsol == NULL);
10930 }
10931 }
10932#endif
10933
10934 /* perform lexicographic rounds */
10935 pos = -1;
10936 nruns = 0;
10937 rounds = 0;
10938 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10939 do
10940 {
10941 int oldpos;
10942
10943 /* get current solution */
10944 if( chooseBasic )
10945 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10946 else
10947 {
10948 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10949 assert(primsol == NULL);
10950 }
10951
10952 /* get current basis */
10953 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10954
10955 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10956 nDualDeg = 0;
10957 cntcol = 0;
10958 oldpos = pos;
10959 pos = -1;
10960 for( c = 0; c < lp->nlpicols; ++c )
10961 {
10962 if( !fixedc[c] )
10963 {
10964 /* check whether variable is in basis */
10965 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10966 {
10967 /* store first candidate */
10968 if( pos == -1 && c > oldpos )
10969 {
10970 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10971 pos = c;
10972 }
10973 }
10974 else
10975 {
10976 /* reduced cost == 0 -> possible candidate */
10977 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10978 {
10979 ++nDualDeg;
10980 /* only if we have not yet found a candidate */
10981 if( pos == -1 && c > oldpos )
10982 {
10983 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10984 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10985 {
10986 newlb[cntcol] = oldlb[c];
10987 newub[cntcol] = oldlb[c];
10988 indcol[cntcol++] = c;
10989 fixedc[c] = TRUE;
10990 }
10991 else /* found a non-fixed candidate */
10992 {
10993 if( !chooseBasic )
10994 pos = c;
10995 }
10996 }
10997 }
10998 else
10999 {
11000 /* nonzero reduced cost -> variable can be fixed */
11001 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11002 {
11003 newlb[cntcol] = oldlb[c];
11004 newub[cntcol] = oldlb[c];
11005 }
11006 else
11007 {
11008 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11009 {
11010 newlb[cntcol] = oldub[c];
11011 newub[cntcol] = oldub[c];
11012 }
11013 else
11014 {
11015 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11016 newlb[cntcol] = 0.0;
11017 newub[cntcol] = 0.0;
11018 }
11019 }
11020 indcol[cntcol++] = c;
11021 fixedc[c] = TRUE;
11022 }
11023 }
11024 }
11025 }
11026
11027 /* check rows */
11028 cntrow = 0;
11029 for( r = 0; r < lp->nlpirows; ++r )
11030 {
11031 if( !fixedr[r] )
11032 {
11033 /* consider only nonbasic rows */
11034 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11035 {
11036 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11037 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11038 ++nDualDeg;
11039 else
11040 {
11041 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11042 {
11043 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11044 newlhs[cntrow] = oldlhs[r];
11045 newrhs[cntrow] = oldlhs[r];
11046 }
11047 else
11048 {
11049 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11050 newlhs[cntrow] = oldrhs[r];
11051 newrhs[cntrow] = oldrhs[r];
11052 }
11053 indrow[cntrow++] = r;
11054 fixedr[r] = TRUE;
11055 }
11056 }
11057 }
11058 }
11059
11060 if( nDualDeg > 0 && pos >= 0 )
11061 {
11062 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11063
11064 /* change objective */
11065 if( nruns == 0 )
11066 {
11067 /* set objective to appropriate unit vector for first run */
11068 newobj[pos] = 1.0;
11069 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11070 }
11071 else
11072 {
11073 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11074 SCIP_Real obj = 1.0;
11075 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11076 }
11077
11078 /* fix variables */
11079 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11080 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11081
11082 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11083 retcode = SCIPlpiSolvePrimal(lp->lpi);
11084 if( retcode == SCIP_LPERROR )
11085 {
11086 *lperror = TRUE;
11087 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11088 }
11089 else
11090 {
11091 SCIP_CALL( retcode );
11092 }
11093 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11094 lexIterations += iterations;
11095
11096#ifdef DEBUG_LEXDUAL
11097 if( iterations > 0 )
11098 {
11099 int j;
11100
11101 if( !chooseBasic )
11102 {
11103 assert(primsol == NULL);
11104 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11105 }
11106 assert(primsol != NULL);
11107 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11108
11109 for( j = 0; j < lp->nlpicols; ++j )
11110 {
11111 if( fixedc[j] )
11112 {
11113 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11114 }
11115 else
11116 {
11117 char cstart = '[';
11118 char cend = ']';
11119 char type;
11120
11121 if(j == pos)
11122 {
11123 cstart = '*';
11124 cend = '*';
11125 }
11126
11127 switch( (SCIP_BASESTAT) cstat[j] )
11128 {
11130 type = 'l';
11131 break;
11133 type = 'u';
11134 break;
11135 case SCIP_BASESTAT_ZERO:
11136 type = 'z';
11137 break;
11139 type = 'b';
11140 break;
11141 default:
11142 type = '?';
11143 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11144 SCIPABORT();
11145 }
11146 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11147 }
11148 }
11149 SCIPsetDebugMsg(set, "\n\n");
11150
11151 if( !chooseBasic )
11152 {
11153 SCIPsetFreeBufferArray(set, &primsol);
11154 assert(primsol == NULL);
11155 }
11156 }
11157#endif
11158
11159 /* count only as round if iterations have been performed */
11160 if( iterations > 0 )
11161 ++rounds;
11162 ++nruns;
11163 }
11164 }
11165 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11166
11167 /* reset bounds, lhs/rhs, and obj */
11168 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11169 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11170 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11171
11172 /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
11173 retcode = SCIPlpiSolveDual(lp->lpi);
11174 if( retcode == SCIP_LPERROR )
11175 {
11176 *lperror = TRUE;
11177 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11178 }
11179 else
11180 {
11181 SCIP_CALL( retcode );
11182 }
11183 assert(SCIPlpiIsOptimal(lp->lpi));
11184 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11185 lexIterations += iterations;
11186
11187 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11188
11189 /* count number of iterations */
11190 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11191 SCIPstatIncrement(stat, set, nlps);
11192
11193 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11194 {
11195 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11196 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11197 {
11198 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11199 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11200 }
11201 SCIPstatIncrement(stat, set, nlexduallps);
11202 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11203
11204 totalIterations += lexIterations;
11205 }
11206
11207 /* free space */
11208 SCIPsetFreeBufferArray(set, &newobj);
11209
11210 SCIPsetFreeBufferArray(set, &fixedr);
11211 SCIPsetFreeBufferArray(set, &fixedc);
11212
11213 SCIPsetFreeBufferArray(set, &indallrow);
11214 SCIPsetFreeBufferArray(set, &indallcol);
11215
11216 SCIPsetFreeBufferArray(set, &indrow);
11217 SCIPsetFreeBufferArray(set, &newrhs);
11218 SCIPsetFreeBufferArray(set, &newlhs);
11219
11220 SCIPsetFreeBufferArray(set, &indcol);
11221 SCIPsetFreeBufferArray(set, &newub);
11222 SCIPsetFreeBufferArray(set, &newlb);
11223
11224 SCIPsetFreeBufferArray(set, &oldobj);
11225 SCIPsetFreeBufferArray(set, &oldrhs);
11226 SCIPsetFreeBufferArray(set, &oldlhs);
11227 SCIPsetFreeBufferArray(set, &oldub);
11228 SCIPsetFreeBufferArray(set, &oldlb);
11229
11230 SCIPsetFreeBufferArray(set, &rstat);
11231 SCIPsetFreeBufferArray(set, &cstat);
11232
11233 SCIPsetFreeBufferArray(set, &redcost);
11234 SCIPsetFreeBufferArray(set, &dualsol);
11235 if( chooseBasic )
11236 SCIPsetFreeBufferArray(set, &primsol);
11237
11238 /* stop timing */
11240
11241 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11242 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11243 }
11245 lp->solisbasic = TRUE;
11246
11247 if( totalIterations > 0 && !lp->strongbranchprobing )
11248 SCIPstatIncrement(stat, set, nlps);
11249 else
11250 {
11251 if( keepsol && !(*lperror) )
11252 {
11253 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11254 if( lp->validsollp == stat->lpcount-1 )
11255 lp->validsollp = stat->lpcount;
11256 if( lp->validfarkaslp == stat->lpcount-1 )
11257 lp->validfarkaslp = stat->lpcount;
11258 }
11259 }
11260
11261 return SCIP_OKAY;
11262}
11263
11264/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11265static
11267 SCIP_LP* lp, /**< current LP data */
11268 SCIP_SET* set, /**< global SCIP settings */
11269 SCIP_STAT* stat, /**< problem statistics */
11270 SCIP_Bool crossover, /**< should crossover be performed? */
11271 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11272 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11273 )
11274{
11275 SCIP_Real timedelta;
11276 SCIP_RETCODE retcode;
11277 int iterations;
11278
11279 assert(lp != NULL);
11280 assert(lp->flushed);
11281 assert(set != NULL);
11282 assert(stat != NULL);
11283 assert(lperror != NULL);
11284
11285 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",
11286 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11287 stat->nbarrierlps, stat->ndivinglps);
11288
11289 *lperror = FALSE;
11290
11291#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11292 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11293 {
11294 char fname[SCIP_MAXSTRLEN];
11295 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11296 SCIP_CALL( SCIPlpWrite(lp, fname) );
11297 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11298 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11300 }
11301#endif
11302
11303 /* start timing */
11304 if( lp->diving || lp->probing )
11305 {
11306 if( lp->strongbranchprobing )
11308 else
11310
11311 timedelta = 0.0; /* unused for diving or probing */
11312 }
11313 else
11314 {
11316 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11317 }
11318
11319 /* call barrier algorithm */
11320 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11321 if( retcode == SCIP_LPERROR )
11322 {
11323 *lperror = TRUE;
11324 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11325 }
11326 else
11327 {
11328 SCIP_CALL( retcode );
11329 }
11331 lp->solisbasic = crossover;
11332
11333 /* stop timing */
11334 if( lp->diving || lp->probing )
11335 {
11336 if( lp->strongbranchprobing )
11338 else
11340 }
11341 else
11342 {
11344 timedelta += SCIPclockGetTime(stat->barrierlptime);
11345 }
11346
11347 /* count number of iterations */
11348 SCIPstatIncrement(stat, set, lpcount);
11349 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11350 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11351 {
11352 if( !lp->strongbranchprobing )
11353 {
11354 SCIPstatIncrement(stat, set, nlps);
11355 SCIPstatAdd(stat, set, nlpiterations, iterations);
11356 }
11357 if( lp->diving || lp->probing )
11358 {
11359 if( lp->strongbranchprobing )
11360 {
11361 SCIPstatIncrement(stat, set, nsbdivinglps);
11362 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11363 }
11364 else
11365 {
11366 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11367 SCIPstatIncrement(stat, set, ndivinglps);
11368 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11369 }
11370 }
11371 else
11372 {
11373 SCIPstatIncrement(stat, set, nbarrierlps);
11374 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11375 }
11376 }
11377 else
11378 {
11379 if ( ! lp->diving && ! lp->probing )
11380 {
11381 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11382 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11383 }
11384
11385 if( keepsol && !(*lperror) )
11386 {
11387 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11388 if( lp->validsollp == stat->lpcount-1 )
11389 lp->validsollp = stat->lpcount;
11390 if( lp->validfarkaslp == stat->lpcount-1 )
11391 lp->validfarkaslp = stat->lpcount;
11392 }
11393 }
11394
11395 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11396 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11397
11398 return SCIP_OKAY;
11399}
11400
11401/** solves the LP with the given algorithm */
11402static
11404 SCIP_LP* lp, /**< current LP data */
11405 SCIP_SET* set, /**< global SCIP settings */
11406 SCIP_STAT* stat, /**< problem statistics */
11407 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11408 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11409 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11410 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11411 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11412 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11413 )
11414{
11415 SCIP_Real lptimelimit;
11416 SCIP_Bool success;
11417
11418 assert(lp != NULL);
11419 assert(lp->flushed);
11420 assert(lperror != NULL);
11421
11422 /* check if a time limit is set, and set time limit for LP solver accordingly */
11423 lptimelimit = SCIPlpiInfinity(lp->lpi);
11424 if( set->istimelimitfinite )
11425 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11426
11427 success = FALSE;
11428 if( lptimelimit > 0.0 )
11429 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11430
11431 if( lptimelimit <= 0.0 || !success )
11432 {
11433 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11434 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11435 *timelimit = TRUE;
11436 return SCIP_OKAY;
11437 }
11438 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11439
11440 /* call appropriate LP algorithm */
11441 switch( lpalgo )
11442 {
11444 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11445 break;
11446
11448 /* run dual lexicographic simplex if required */
11449 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11450 {
11451 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11452 }
11453 else
11454 {
11455 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11456 }
11457 break;
11458
11460 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11461 break;
11462
11464 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11465 break;
11466
11467 default:
11468 SCIPerrorMessage("invalid LP algorithm\n");
11469 return SCIP_INVALIDDATA;
11470 }
11471
11472 if( !(*lperror) )
11473 {
11474 /* check for primal and dual feasibility */
11476
11477 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11478 }
11479
11480 return SCIP_OKAY;
11481}
11482
11483/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11484 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11485 */
11486#define MAXNUMTROUBLELPMSGS 10
11487
11488/** prints message about numerical trouble
11489 *
11490 * If message has verblevel at most high and display/verblevel is not full,
11491 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11492 * were printed before in the current run.
11493 */
11494static
11496 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11497 SCIP_SET* set, /**< global SCIP settings */
11498 SCIP_STAT* stat, /**< problem statistics */
11499 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11500 const char* formatstr, /**< message format string */
11501 ... /**< arguments to format string */
11502 )
11503{
11504 va_list ap;
11505
11506 assert(verblevel > SCIP_VERBLEVEL_NONE);
11507 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11508 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11509
11510 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11511 {
11512 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11513 {
11514 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11516 return;
11517
11518 /* increase count on messages with verblevel high */
11519 ++stat->nnumtroublelpmsgs ;
11520 }
11521
11522 /* if messages wouldn't be printed, then return already */
11523 if( verblevel > set->disp_verblevel )
11524 return;
11525 }
11526
11527 /* print common begin of message */
11528 SCIPmessagePrintInfo(messagehdlr,
11529 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11530 stat->nnodes, stat->nlps);
11531
11532 /* print individual part of message */
11533 va_start(ap, formatstr); /*lint !e838*/
11534 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11535 va_end(ap);
11536
11537 /* warn that further messages will be suppressed */
11538 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11539 {
11540 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11541 }
11542
11543 /* print closing new-line */
11544 SCIPmessagePrintInfo(messagehdlr, "\n");
11545}
11546
11547static
11549 SCIP_LP* lp, /**< current LP data */
11550 SCIP_SET* set, /**< global SCIP settings */
11551 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11552 SCIP_STAT* stat, /**< problem statistics */
11553 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11554 SCIP_Bool* success /**< was instability successfully ignored */
11555 )
11556{
11557 assert(lp != NULL);
11558 assert(set != NULL);
11559
11560 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11561
11562 if( *success )
11563 {
11564 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11565 if( !set->lp_checkdualfeas )
11566 lp->dualfeasible = TRUE;
11567 if( !set->lp_checkprimfeas )
11568 lp->primalchecked = TRUE;
11569 }
11570
11571 return SCIP_OKAY;
11572}
11573
11574#define FEASTOLTIGHTFAC 0.001
11575/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11576static
11578 SCIP_LP* lp, /**< current LP data */
11579 SCIP_SET* set, /**< global SCIP settings */
11580 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11581 SCIP_STAT* stat, /**< problem statistics */
11582 SCIP_PROB* prob, /**< problem data */
11583 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11584 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11585 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11586 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11587 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11588 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11589 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11590 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11591 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11592 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11593 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11594 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11595 )
11596{
11597 SCIP_Bool success;
11598 SCIP_Bool success2;
11599 SCIP_Bool success3;
11600 SCIP_Bool simplex;
11601 SCIP_Bool itlimishard;
11602 SCIP_Bool usepolishing;
11603
11604 assert(lp != NULL);
11605 assert(lp->flushed);
11606 assert(set != NULL);
11607 assert(stat != NULL);
11608 assert(lperror != NULL);
11609 assert(timelimit != NULL);
11610
11611 *lperror = FALSE;
11612
11613 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11614 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11615 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11616 * SCIP_LP such that we can return a primal ray
11617 */
11618 if( lp->looseobjvalinf > 0 )
11619 {
11620 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11621 return SCIP_ERROR;
11622 }
11623
11624 /* check, whether we solve with a simplex algorithm */
11625 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11626
11627 /* check whether the iteration limit is a hard one */
11628 itlimishard = (itlim == harditlim);
11629
11630 /* check whether solution polishing should be used */
11631 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11632 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11633 {
11634 usepolishing = TRUE;
11635 if( lp->updateintegrality )
11636 {
11638 }
11639 }
11640 else
11641 usepolishing = FALSE;
11642
11643 /* solve with given settings (usually fast but imprecise) */
11645 {
11646 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11647 }
11648 else
11649 {
11650 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11651 }
11652 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11653 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11655 &success) );
11656 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11657 : SCIPsetBarrierconvtol(set), &success) );
11658 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11659 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11660 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11661 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11662 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11663 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11664 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11665 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11666 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11667 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11668 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11669 SCIP_CALL( lpSetRandomseed(lp, (int) (SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed) % INT_MAX), &success) );
11670 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11671 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11672
11673 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11674
11675 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11676 * optimal without preforming scaling/change tolerances/presolving */
11677 resolve = FALSE;
11678
11679 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11680 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11681 return SCIP_OKAY;
11682
11683 if( !set->lp_checkstability )
11684 {
11685 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11686
11687 if( success )
11688 return SCIP_OKAY;
11689 }
11690
11691 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11692 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11693 */
11694
11695 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11696 * do this only if the iteration limit was not exceeded in the last LP solving call
11697 */
11698 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11699 {
11700 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11701 if( success )
11702 {
11703 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11704 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11705
11706 /* check for stability */
11707 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11708 return SCIP_OKAY;
11709
11710 if( !set->lp_checkstability )
11711 {
11712 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11713
11714 if( success )
11715 return SCIP_OKAY;
11716 }
11717 }
11718 }
11719
11720 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11721 * and go directly to solving the LP from scratch
11722 */
11723 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11724 {
11725 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11726 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11727 if( success )
11728 {
11729 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11730 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11731 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11732
11733 /* check for stability */
11734 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11735 return SCIP_OKAY;
11736
11737 if( !set->lp_checkstability )
11738 {
11739 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11740
11741 if( success )
11742 return SCIP_OKAY;
11743 }
11744
11745 /* reset scaling */
11746 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11747 assert(success);
11748 }
11749 }
11750
11751 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11752 * and go directly to solving the LP from scratch */
11753 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11754 {
11755 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11756 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11757 if( success )
11758 {
11759 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11760 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11761 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11762
11763 /* check for stability */
11764 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11765 return SCIP_OKAY;
11766
11767 if( !set->lp_checkstability )
11768 {
11769 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11770
11771 if( success )
11772 return SCIP_OKAY;
11773 }
11774
11775 /* reset presolving */
11776 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11777 assert(success);
11778 }
11779 }
11780
11781 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11782 * do this only if the iteration limit was not exceeded in the last LP solving call
11783 */
11784 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11785 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11786 {
11787 success = FALSE;
11788 if( !tightprimfeastol )
11789 {
11790 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11791 }
11792
11793 success2 = FALSE;
11794 if( !tightdualfeastol )
11795 {
11797 }
11798
11799 success3 = FALSE;
11800 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11801 {
11803 }
11804
11805 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11806 if( success || success2 || success3 )
11807 {
11808 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11809 lpalgoName(lpalgo));
11810 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11811
11812 /* check for stability */
11813 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11814 return SCIP_OKAY;
11815
11816 if( !set->lp_checkstability )
11817 {
11818 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11819
11820 if( success )
11821 return SCIP_OKAY;
11822 }
11823
11824 /* reset feasibility tolerance */
11825 if( !tightprimfeastol )
11826 {
11827 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11828 }
11829 if( !tightdualfeastol )
11830 {
11832 }
11833 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11834 {
11836 }
11837 }
11838 }
11839
11840 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11841 * the given iteration limit might be a soft one to restrict resolving calls only */
11842 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11843
11844 /* if not already done, solve again from scratch */
11845 if( !fromscratch && simplex )
11846 {
11847 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11848 if( success )
11849 {
11850 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11851 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11852
11853 /* check for stability */
11854 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11855 return SCIP_OKAY;
11856
11857 if( !set->lp_checkstability )
11858 {
11859 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11860
11861 if( success )
11862 return SCIP_OKAY;
11863 }
11864 }
11865 }
11866
11867 /* solve again, use other simplex this time */
11868 if( simplex )
11869 {
11871 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11872 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11873
11874 /* check for stability */
11875 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11876 return SCIP_OKAY;
11877
11878 if( !set->lp_checkstability )
11879 {
11880 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11881
11882 if( success )
11883 return SCIP_OKAY;
11884 }
11885
11886 /* solve again with opposite scaling and other simplex */
11887 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11888 if( success )
11889 {
11890 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11891 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11892 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11893
11894 /* check for stability */
11895 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11896 return SCIP_OKAY;
11897
11898 if( !set->lp_checkstability )
11899 {
11900 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11901
11902 if( success )
11903 return SCIP_OKAY;
11904 }
11905
11906 /* reset scaling */
11907 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11908 assert(success);
11909 }
11910
11911 /* solve again with opposite presolving and other simplex */
11912 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11913 if( success )
11914 {
11915 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11916 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11917 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11918
11919 /* check for stability */
11920 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11921 return SCIP_OKAY;
11922
11923 if( !set->lp_checkstability )
11924 {
11925 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11926
11927 if( success )
11928 return SCIP_OKAY;
11929 }
11930
11931 /* reset presolving */
11932 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11933 assert(success);
11934 }
11935
11936 /* solve again with tighter feasibility tolerance, use other simplex this time */
11937 if( !tightprimfeastol || !tightdualfeastol )
11938 {
11939 success = FALSE;
11940 if( !tightprimfeastol )
11941 {
11942 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11943 }
11944
11945 success2 = FALSE;
11946 if( !tightdualfeastol )
11947 {
11949 }
11950
11951 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11952 if( success || success2 )
11953 {
11954 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11955 lpalgoName(lpalgo));
11956 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11957
11958 /* check for stability */
11959 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11960 return SCIP_OKAY;
11961
11962 if( !set->lp_checkstability )
11963 {
11964 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11965
11966 if( success )
11967 return SCIP_OKAY;
11968 }
11969
11970 /* reset feasibility tolerance */
11971 if( !tightprimfeastol )
11972 {
11973 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11974 }
11975 if( !tightdualfeastol )
11976 {
11978 }
11979 SCIP_UNUSED(success);
11980 }
11981 }
11982 }
11983
11984 /* nothing worked -- exit with an LPERROR */
11985 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11986 *lperror = TRUE;
11987
11988 return SCIP_OKAY;
11989}
11990
11991/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
11992static
11994 SCIP_LP* lp, /**< current LP data */
11995 SCIP_SET* set, /**< global SCIP settings */
11996 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
11997 )
11998{
11999 assert(lp != NULL);
12000 assert(set != NULL);
12001
12002 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12003 {
12004 if( !lp->adjustlpval && messagehdlr != NULL )
12005 {
12006 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12007 lp->adjustlpval = TRUE;
12008 }
12010 }
12011 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12012 {
12013 if( !lp->adjustlpval && messagehdlr != NULL )
12014 {
12015 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12016 lp->adjustlpval = TRUE;
12017 }
12019 }
12020}
12021
12022/** solves the LP with the given algorithm and evaluates return status */
12023static
12025 SCIP_LP* lp, /**< current LP data */
12026 SCIP_SET* set, /**< global SCIP settings */
12027 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12028 SCIP_STAT* stat, /**< problem statistics */
12029 SCIP_PROB* prob, /**< problem data */
12030 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12031 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12032 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12033 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12034 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12035 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12036 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12037 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12038 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12039 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12040 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12041 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12042 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12043 )
12044{
12045 SCIP_Bool solvedprimal;
12046 SCIP_Bool solveddual;
12047 SCIP_Bool timelimit;
12048 int itlim;
12049
12050 assert(lp != NULL);
12051 assert(lp->flushed);
12052 assert(set != NULL);
12053 assert(stat != NULL);
12054 assert(lperror != NULL);
12055
12056 checkLinks(lp);
12057
12058 solvedprimal = FALSE;
12059 solveddual = FALSE;
12060 timelimit = FALSE;
12061
12062 /* select the basic iteration limit depending on whether this is a resolving call or not */
12063 itlim = ( resolve ? resolveitlim : harditlim );
12064
12065 SOLVEAGAIN:
12066 /* call simplex */
12067 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12068 scaling, keepsol, &timelimit, lperror) );
12069 resolve = FALSE; /* only the first solve should be counted as resolving call */
12070 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12071 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12072
12073 /* check, if an error occurred */
12074 if( *lperror )
12075 {
12076 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12077 lp->solved = FALSE;
12079 return SCIP_OKAY;
12080 }
12081
12082 /* check, if a time limit was exceeded */
12083 if( timelimit )
12084 {
12085 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12086 lp->solved = TRUE;
12089 return SCIP_OKAY;
12090 }
12091
12092 /* only one should return true */
12095
12096 /* evaluate solution status */
12097 if( SCIPlpiIsOptimal(lp->lpi) )
12098 {
12099 assert(lp->primalfeasible);
12100 assert(lp->dualfeasible);
12102 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12103 adjustLPobjval(lp, set, messagehdlr);
12104
12106 {
12107 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12108 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12111 }
12112 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12113 * reached if the LP objective value is greater than the cutoff bound
12114 */
12115 assert(lpCutoffDisabled(set, prob, lp) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
12117 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12118 }
12119 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12120 {
12121 assert(!lpCutoffDisabled(set, prob, lp));
12122
12123#ifndef NDEBUG
12124 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12125 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12126 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12127 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12128#endif
12129
12132 }
12133 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12134 {
12135 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12136 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12137 {
12138 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12139 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12140 goto SOLVEAGAIN;
12141 }
12144 }
12145 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12146 {
12147 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12148 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12149 {
12150 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12153 goto SOLVEAGAIN;
12154 }
12157 }
12158 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12159 {
12160 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12161
12162 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12163 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12164 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12165 adjustLPobjval(lp, set, NULL);
12166 else
12167 adjustLPobjval(lp, set, messagehdlr);
12168
12170 }
12171 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12172 {
12175 }
12176 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12177 {
12178 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12179 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12180 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12181 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12182 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12183 goto SOLVEAGAIN;
12184 }
12185 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12186 {
12189 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12190 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12191 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12192 goto SOLVEAGAIN;
12193 }
12194 else
12195 {
12196 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12197 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12199 return SCIP_LPERROR;
12200 }
12201
12202 lp->solved = TRUE;
12203
12204 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12207
12208 return SCIP_OKAY;
12209}
12210
12211/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12212static
12214 SCIP_LP* lp, /**< current LP data */
12215 BMS_BLKMEM* blkmem, /**< block memory */
12216 SCIP_SET* set, /**< global SCIP settings */
12217 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12218 SCIP_STAT* stat, /**< problem statistics */
12219 SCIP_PROB* prob, /**< problem data */
12220 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12221 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12222 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12223 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12224 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12225 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12226 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12227 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12228 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12229 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12230 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12231 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12232 )
12233{
12234 SCIP_Bool resolve;
12235 char algo;
12236
12237 assert(lp != NULL);
12238 assert(set != NULL);
12239 assert(lperror != NULL);
12240
12241 /* flush changes to the LP solver */
12242 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12243 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12244
12245 /* select LP algorithm to apply */
12246 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12247 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12248
12249 switch( algo )
12250 {
12251 case 's':
12252 /* select simplex method */
12253 if( lp->dualfeasible || !lp->primalfeasible )
12254 {
12255 SCIPsetDebugMsg(set, "solving dual LP\n");
12256 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12257 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12258 }
12259 else
12260 {
12261 SCIPsetDebugMsg(set, "solving primal LP\n");
12262 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12263 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12264 }
12265 break;
12266
12267 case 'p':
12268 SCIPsetDebugMsg(set, "solving primal LP\n");
12269 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12270 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12271 break;
12272
12273 case 'd':
12274 SCIPsetDebugMsg(set, "solving dual LP\n");
12275 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12276 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12277 break;
12278
12279 case 'b':
12280 SCIPsetDebugMsg(set, "solving barrier LP\n");
12281 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12282 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12283 break;
12284
12285 case 'c':
12286 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12287 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12288 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12289 break;
12290
12291 default:
12292 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12294 }
12295 assert(!(*lperror) || !lp->solved);
12296
12297 return SCIP_OKAY;
12298}
12299
12300#ifndef NDEBUG
12301/** checks if the lazy bounds are valid */
12302static
12304 SCIP_LP* lp, /**< LP data */
12305 SCIP_SET* set /**< global SCIP settings */
12306 )
12307{
12308 SCIP_COL* col;
12309 int c;
12310
12311 assert(lp->flushed);
12312
12313 for( c = 0; c < lp->nlazycols; ++c )
12314 {
12315 col = lp->lazycols[c];
12316
12317 /* in case lazy bounds are given, check that the primal solution satisfies them */
12318 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12319 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12320 }
12321}
12322#else
12323#define checkLazyBounds(lp, set) /**/
12324#endif
12325
12326/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12327 * diving
12328 */
12329static
12331 SCIP_LP* lp, /**< LP data */
12332 SCIP_SET* set /**< global SCIP settings */
12333 )
12334{
12335 SCIP_COL* col;
12336 int c;
12337
12338 assert(lp->nlazycols > 0);
12339
12340 /* return, if we are in diving, and bounds were already applied
12341 * or if we are not in diving and bounds were not applied
12342 */
12343 if( lp->diving == lp->divinglazyapplied )
12344 return SCIP_OKAY;
12345
12346 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12347 lp->diving, lp->divinglazyapplied);
12348
12349 for( c = 0; c < lp->nlazycols; ++c )
12350 {
12351 col = lp->lazycols[c];
12352
12353 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12354 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12355 {
12356 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12357 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12358 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12359
12360 /* insert column in the chgcols list (if not already there) */
12361 SCIP_CALL( insertColChgcols(col, set, lp) );
12362
12363 /* mark bound change in the column */
12364 col->lbchanged = TRUE;
12365 }
12366
12367 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12368 if( !SCIPsetIsInfinity(set, col->lazyub) )
12369 {
12370 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12371 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12372 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12373
12374 /* insert column in the chgcols list (if not already there) */
12375 SCIP_CALL( insertColChgcols(col, set, lp) );
12376
12377 /* mark bound change in the column */
12378 col->ubchanged = TRUE;
12379 }
12380 }
12381
12382 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12383 * if not, we just removed them
12384 */
12385 lp->divinglazyapplied = lp->diving;
12386
12387 return SCIP_OKAY;
12388}
12389
12390/** returns the iteration limit for an LP resolving call */
12391static
12393 SCIP_SET* set, /**< global SCIP settings */
12394 SCIP_STAT* stat, /**< dynamic problem statistics */
12395 int itlim /**< hard iteration limit */
12396 )
12397{
12398 /* no limit set or average not yet reliable */
12399 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12400 return itlim;
12401 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12402 if( itlim == -1 )
12403 itlim = INT_MAX;
12404 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12405 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12406 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12407}
12408
12409
12410
12411/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12413 SCIP_LP* lp, /**< LP data */
12414 SCIP_SET* set, /**< global SCIP settings */
12415 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12416 BMS_BLKMEM* blkmem, /**< block memory buffers */
12417 SCIP_STAT* stat, /**< problem statistics */
12418 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12419 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12420 SCIP_PROB* prob, /**< problem data */
12421 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12422 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12423 * (limit is computed within the method w.r.t. the average LP iterations) */
12424 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12425 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12426 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12427 )
12428{
12429 SCIP_RETCODE retcode;
12430 SCIP_Bool needprimalray;
12431 SCIP_Bool needdualray;
12432 int harditlim;
12433 int resolveitlim;
12434
12435 assert(lp != NULL);
12436 assert(prob != NULL);
12437 assert(prob->nvars >= lp->ncols);
12438 assert(lperror != NULL);
12439
12440 retcode = SCIP_OKAY;
12441 *lperror = FALSE;
12442
12443 if( lp->flushed && lp->solved )
12444 {
12445 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12446 return SCIP_OKAY;
12447 }
12448
12449 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12450 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12451
12452 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12453 needprimalray = TRUE;
12454 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12455 || (set->conf_enable && set->conf_useinflp != 'o'));
12456
12457 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12458 harditlim = (int) MIN(itlim, INT_MAX);
12459 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12460 assert(harditlim == -1 || (resolveitlim <= harditlim));
12461
12462 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12463 * or removed from the LP (diving was ended)
12464 */
12465 if( lp->nlazycols > 0 )
12466 {
12467 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12468 * first resolve LP?
12469 */
12471 assert(lp->diving == lp->divinglazyapplied);
12472 }
12473
12474 /* flush changes to the LP solver */
12475 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12476 assert(lp->flushed);
12477
12478 /* 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
12479 * to run again anyway, since there seems to be some time left / the time limit was increased
12480 */
12481 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12482 {
12483 SCIP_Bool* primalfeaspointer;
12484 SCIP_Bool* dualfeaspointer;
12485 SCIP_Bool primalfeasible;
12486 SCIP_Bool dualfeasible;
12487 SCIP_Bool farkasvalid;
12488 SCIP_Bool rayfeasible;
12489 SCIP_Bool tightprimfeastol;
12490 SCIP_Bool tightdualfeastol;
12491 SCIP_Bool fromscratch;
12492 SCIP_Bool wasfromscratch;
12493 int scaling;
12494 SCIP_Longint oldnlps;
12495 int fastmip;
12496
12497 /* set initial LP solver settings */
12498 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12499 tightprimfeastol = FALSE;
12500 tightdualfeastol = FALSE;
12501 fromscratch = FALSE;
12502 primalfeasible = FALSE;
12503 dualfeasible = FALSE;
12504 wasfromscratch = (stat->nlps == 0);
12505 scaling = set->lp_scaling;
12506
12507 SOLVEAGAIN:
12508 /* solve the LP */
12509 oldnlps = stat->nlps;
12510 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12511 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12512 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12513 assert(!(*lperror) || !lp->solved);
12514
12515 /* check for error */
12516 if( *lperror )
12517 {
12518 retcode = SCIP_OKAY;
12519 goto TERMINATE;
12520 }
12521
12522 /* evaluate solution status */
12523 switch( SCIPlpGetSolstat(lp) )
12524 {
12526 /* get LP solution and possibly check the solution's feasibility again */
12527 if( set->lp_checkprimfeas )
12528 {
12529 primalfeaspointer = &primalfeasible;
12530 lp->primalchecked = TRUE;
12531 }
12532 else
12533 {
12534 /* believe in the primal feasibility of the LP solution */
12535 primalfeasible = TRUE;
12536 primalfeaspointer = NULL;
12537 lp->primalchecked = FALSE;
12538 }
12539 if( set->lp_checkdualfeas )
12540 {
12541 dualfeaspointer = &dualfeasible;
12542 lp->dualchecked = TRUE;
12543 }
12544 else
12545 {
12546 /* believe in the dual feasibility of the LP solution */
12547 dualfeasible = TRUE;
12548 dualfeaspointer = NULL;
12549 lp->dualchecked = FALSE;
12550 }
12551
12552 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12553
12554 /* in debug mode, check that lazy bounds (if present) are not violated */
12555 checkLazyBounds(lp, set);
12556
12557 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12558 {
12559 /* update ages and remove obsolete columns and rows from LP */
12560 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12561 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12562 {
12563 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12564 }
12565
12566 if( !lp->solved )
12567 {
12568 /* resolve LP after removing obsolete columns and rows */
12569 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12570 aging = FALSE; /* to prevent infinite loops */
12571 goto SOLVEAGAIN;
12572 }
12573 }
12574 if( !primalfeasible || !dualfeasible )
12575 {
12577
12578 if( (fastmip > 0) && simplex )
12579 {
12580 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12581 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12582 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12583 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12584 fastmip = 0;
12585 goto SOLVEAGAIN;
12586 }
12587 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12588 {
12589 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12590 * tolerance
12591 */
12592 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12593 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12594 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12595 tightprimfeastol = tightprimfeastol || !primalfeasible;
12596 tightdualfeastol = tightdualfeastol || !dualfeasible;
12597 goto SOLVEAGAIN;
12598 }
12599 else if( !fromscratch && !wasfromscratch && simplex )
12600 {
12601 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12602 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12603 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12604 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12605 fromscratch = TRUE;
12606 goto SOLVEAGAIN;
12607 }
12608 else
12609 {
12610 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12611 lp->solved = FALSE;
12613 *lperror = TRUE;
12614 }
12615 }
12616 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12617 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12618 lp->lpsolstat, lp->cutoffbound);
12619 break;
12620
12622 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12623 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->misc_exactsolve || set->lp_alwaysgetduals )
12624 {
12625 if( SCIPlpiHasDualRay(lp->lpi) )
12626 {
12627 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, &farkasvalid) );
12628 }
12629 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12630 * with the primal simplex due to numerical problems) - treat this case like an LP error
12631 */
12632 else
12633 {
12634 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12635 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12636 lp->solved = FALSE;
12638 farkasvalid = FALSE;
12639 *lperror = TRUE;
12640 }
12641 }
12642 else
12643 farkasvalid = TRUE;
12644
12645 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12646 if( !farkasvalid && !(*lperror) )
12647 {
12649
12650 if( (fastmip > 0) && simplex )
12651 {
12652 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12653 * without FASTMIP
12654 */
12655 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12656 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12657 stat->nnodes, stat->nlps);
12658 fastmip = 0;
12659 goto SOLVEAGAIN;
12660 }
12661 else if( !tightdualfeastol )
12662 {
12663 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12664 * solve again with tighter feasibility tolerance
12665 */
12666 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12667 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12668 stat->nnodes, stat->nlps);
12669 tightdualfeastol = TRUE;
12670 goto SOLVEAGAIN;
12671 }
12672 else if( !fromscratch && simplex )
12673 {
12674 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12675 * from scratch
12676 */
12677 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12678 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12679 stat->nnodes, stat->nlps);
12680 fromscratch = TRUE;
12681 goto SOLVEAGAIN;
12682 }
12683 else
12684 {
12685 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12686 * helped forget about the LP at this node and mark it to be unsolved
12687 */
12688 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12689 lp->solved = FALSE;
12691 *lperror = TRUE;
12692 }
12693 }
12694
12695 break;
12696
12698 if( set->lp_checkprimfeas )
12699 {
12700 /* get unbounded LP solution and check the solution's feasibility again */
12701 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12702
12703 lp->primalchecked = TRUE;
12704 }
12705 else
12706 {
12707 /* get unbounded LP solution believing in the feasibility of the LP solution */
12709
12710 primalfeasible = TRUE;
12711 rayfeasible = TRUE;
12712 lp->primalchecked = FALSE;
12713 }
12714
12715 /* in debug mode, check that lazy bounds (if present) are not violated */
12716 checkLazyBounds(lp, set);
12717
12718 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12719 primalfeasible, rayfeasible);
12720
12721 if( !primalfeasible || !rayfeasible )
12722 {
12724
12725 if( (fastmip > 0) && simplex )
12726 {
12727 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12728 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12729 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12730 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12731 fastmip = 0;
12732 goto SOLVEAGAIN;
12733 }
12734 else if( !tightprimfeastol )
12735 {
12736 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12737 * tolerance
12738 */
12739 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12740 "(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",
12741 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12742 tightprimfeastol = TRUE;
12743 goto SOLVEAGAIN;
12744 }
12745 else if( !fromscratch && simplex )
12746 {
12747 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12748 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12749 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12750 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12751 fromscratch = TRUE;
12752 goto SOLVEAGAIN;
12753 }
12754 else if( scaling > 0 )
12755 {
12756 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12757 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12758 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12759 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12760 scaling = 0;
12761 goto SOLVEAGAIN;
12762 }
12763 else
12764 {
12765 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12766 * forget about the LP at this node and mark it to be unsolved
12767 */
12768 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12769 lp->solved = FALSE;
12771 *lperror = TRUE;
12772 }
12773 }
12774
12775 break;
12776
12778 assert(!lpCutoffDisabled(set, prob, lp));
12779 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12780 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12781 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12782 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12783 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12784 * FASTMIP and solve again.
12785 */
12786 if( !SCIPprobAllColsInLP(prob, set, lp) )
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 )
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:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define EPSGE(x, y, eps)
Definition: def.h:201
#define SCIP_Longint
Definition: def.h:157
#define SCIP_UNUSED(x)
Definition: def.h:427
#define EPSISINT(x, eps)
Definition: def.h:209
#define SCIP_DEFAULT_SUMEPSILON
Definition: def.h:179
#define EPSP(x, eps)
Definition: def.h:203
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_DEFAULT_EPSILON
Definition: def.h:178
#define EPSLE(x, y, eps)
Definition: def.h:199
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define EPSLT(x, y, eps)
Definition: def.h:198
#define ABS(x)
Definition: def.h:234
#define SQR(x)
Definition: def.h:213
#define EPSEQ(x, y, eps)
Definition: def.h:197
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define EPSN(x, eps)
Definition: def.h:204
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_LONGINT_MAX
Definition: def.h:158
#define EPSZ(x, eps)
Definition: def.h:202
#define SCIP_CALL(x)
Definition: def.h:373
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:9124
#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:9397
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
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:3432
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:6013
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:7785
SCIP_Real SCIProwGetScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7005
int SCIProwGetLPDepth(SCIP_ROW *row)
Definition: lp.c:17512
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7721
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:5375
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:5390
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:17809
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18210
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17619
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17558
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18164
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3416
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17946
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18108
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17788
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17439
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17630
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18246
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18154
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18098
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3429
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18485
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17956
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18236
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:10880
void SCIPprintSysError(const char *message)
Definition: misc.c:10772
interval arithmetics for provable bounds
static SCIP_RETCODE lpFlushDelRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: lp.c:8176
static void rowCalcIdxsAndVals(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4827
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:3616
SCIP_Real SCIProwGetMaxval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6668
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6921
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3799
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6251
SCIP_Real SCIPcolCalcRedcost(SCIP_COL *col, SCIP_Real *dualsol)
Definition: lp.c:3844
SCIP_RETCODE SCIPlpGetBInvRow(SCIP_LP *lp, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9848
static SCIP_RETCODE lpSetRefactorInterval(SCIP_LP *lp, int refactor, SCIP_Bool *success)
Definition: lp.c:3249
SCIP_Real SCIProwGetNLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6333
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3374
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:11577
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:5336
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10098
SCIP_Real SCIProwGetPseudoFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6447
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:9870
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3754
#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:3162
SCIP_RETCODE SCIPlpInterrupt(SCIP_LP *lp, SCIP_Bool interrupt)
Definition: lp.c:10115
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:10668
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:5473
static SCIP_RETCODE lpSetFromscratch(SCIP_LP *lp, SCIP_Bool fromscratch, SCIP_Bool *success)
Definition: lp.c:2832
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:4027
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:2857
SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:10131
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:8620
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:9788
int SCIProwGetNumIntCols(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6732
static SCIP_RETCODE lpSetLPInfo(SCIP_LP *lp, SCIP_Bool lpinfo)
Definition: lp.c:3089
SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10031
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:3659
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:6505
void SCIProwRecalcPseudoActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6392
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:6271
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition: lp.c:9448
#define MAXNUMTROUBLELPMSGS
Definition: lp.c:11486
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:10055
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:6523
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:6616
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:5978
static SCIP_RETCODE lpSetPresolving(SCIP_LP *lp, SCIP_Bool presolving, SCIP_Bool *success)
Definition: lp.c:2938
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:6846
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6862
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:4177
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:8668
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:5637
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:10254
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:3510
SCIP_RETCODE rowUnlink(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:2475
#define lpCutoffDisabled(set, prob, lp)
Definition: lp.c:2646
SCIP_RETCODE SCIPlpWrite(SCIP_LP *lp, const char *fname)
Definition: lp.c:16527
int SCIProwGetMaxidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6700
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:11993
static SCIP_RETCODE lpFlushAddRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8225
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:6221
void SCIProwMarkNotRemovableLocal(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:7875
static SCIP_RETCODE lpSetPricing(SCIP_LP *lp, SCIP_PRICING pricing)
Definition: lp.c:3024
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:9631
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:3047
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:5107
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:3137
static void rowUpdateAddLP(SCIP_ROW *row)
Definition: lp.c:8900
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:9769
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:5427
SCIP_RETCODE SCIPlpGetBase(SCIP_LP *lp, int *cstat, int *rstat)
Definition: lp.c:9831
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:17797
#define FEASTOLTIGHTFAC
Definition: lp.c:11574
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:4261
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:12024
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition: lp.c:12392
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:4296
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:3465
static void rowMerge(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6046
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:4897
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:7967
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:6169
static SCIP_Bool isNewValueUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: lp.c:3641
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:6684
SCIP_RETCODE SCIPlpEndStrongbranch(SCIP_LP *lp)
Definition: lp.c:4192
SCIP_Longint SCIPcolGetStrongbranchLPAge(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4736
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:4937
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:11548
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:9578
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3695
static void colUpdateAddLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8860
SCIP_Real SCIProwGetLPSolCutoffDistance(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_LP *lp)
Definition: lp.c:6748
static SCIP_RETCODE lpSetRandomseed(SCIP_LP *lp, int randomseed, SCIP_Bool *success)
Definition: lp.c:3196
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:6463
static SCIP_RETCODE lpSetScaling(SCIP_LP *lp, int scaling, SCIP_Bool *success)
Definition: lp.c:2888
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:9368
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:10175
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:11266
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:5406
static void freeDiveChgSideArrays(SCIP_LP *lp)
Definition: lp.c:9056
SCIP_RETCODE SCIPlpGetBInvARow(SCIP_LP *lp, int r, SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9896
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:5525
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:8974
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17878
SCIP_RETCODE SCIPlpGetBasisInd(SCIP_LP *lp, int *basisind)
Definition: lp.c:9814
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6961
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lp.c:10155
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5727
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:9073
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:4768
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6805
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:8160
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:5741
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:4704
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:3444
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:3561
SCIP_Real SCIPlpGetRootLooseObjval(SCIP_LP *lp)
Definition: lp.c:17764
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:5296
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:10199
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:8732
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:11403
SCIP_Real SCIPcolGetFeasibility(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3973
#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:9703
SCIP_Bool SCIProwIsRedundant(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6637
void SCIPlpStartStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16345
static SCIP_RETCODE lpFlushDelCols(SCIP_LP *lp)
Definition: lp.c:7916
static SCIP_RETCODE lpSetRowrepswitch(SCIP_LP *lp, SCIP_Real rowrepswitch, SCIP_Bool *success)
Definition: lp.c:2963
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:8935
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:5582
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition: lp.c:16315
SCIP_Real SCIPlpGetFeastol(SCIP_LP *lp)
Definition: lp.c:10244
static SCIP_RETCODE lpSetFeastol(SCIP_LP *lp, SCIP_Real feastol, SCIP_Bool *success)
Definition: lp.c:2702
SCIP_Bool SCIProwIsSolEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Bool root)
Definition: lp.c:6905
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:9921
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:2913
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:8373
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:7830
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:5256
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:4158
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:10477
static const char * lpalgoName(SCIP_LPALGO lpalgo)
Definition: lp.c:10296
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:4079
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:9076
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:12213
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:9413
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:3949
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:7854
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:3276
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:3112
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:11495
SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4132
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:9030
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:9507
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:6716
static SCIP_Real colCalcInternalRedcost(SCIP_COL *col)
Definition: lp.c:3896
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:2788
SCIP_RETCODE SCIProwChgRhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real rhs)
Definition: lp.c:5695
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:2745
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:5744
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition: lp.c:10189
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:7894
SCIP_Real SCIProwGetPseudoActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6419
static void checkLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12303
static SCIP_RETCODE lpSetIterationLimit(SCIP_LP *lp, int itlim)
Definition: lp.c:2988
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:9008
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:5663
void SCIProwForceSort(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6156
void SCIPcolMarkNotRemovableLocal(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4748
static SCIP_RETCODE updateLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12330
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:6595
#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:12412
static const SCIP_Real scalars[]
Definition: lp.c:5740
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:4207
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:10279
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:6145
static SCIP_RETCODE lpSetSolutionPolishing(SCIP_LP *lp, SCIP_Bool polishing, SCIP_Bool *success)
Definition: lp.c:3226
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:8521
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:10319
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7797
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:9945
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:4481
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:9800
static int SCIProwGetDiscreteScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7362
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:5349
#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:8002
void SCIPcolPrint(SCIP_COL *col, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:3404
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:4091
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4367
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4246
internal miscellaneous methods
real eps
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2358
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:13943
internal methods for problem variables