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_scip.h"
62#include "scip/struct_event.h"
63#include "scip/struct_lp.h"
64#include "scip/struct_prob.h"
65#include "scip/struct_set.h"
66#include "scip/struct_stat.h"
67#include "scip/struct_var.h"
68#include "scip/var.h"
69#include <string.h>
70
71
72/* activate this to use the row activities as given by the LPI instead of recalculating
73 * using the LP solver activity is potentially faster, but may not be consistent with the SCIP_ROW calculations
74 * see also #2594 for more details on possible trouble
75 */
76/* #define SCIP_USE_LPSOLVER_ACTIVITY */
77
78/*
79 * debug messages
80 */
81
82#ifdef SCIP_DEBUG
83/** method is to print in row in case SCIP_DEBUG is defined */
84static
85void debugRowPrint(
86 SCIP_SET* set, /**< global SCIP settings */
87 SCIP_ROW* row /**< LP row */
88 )
89{
90 int i;
91
92 assert(row != NULL);
93
94 /* print row name */
95 if( row->name != NULL && row->name[0] != '\0' )
96 {
97 SCIPsetDebugMsgPrint(set, "%s: ", row->name);
98 }
99
100 /* print left hand side */
101 SCIPsetDebugMsgPrint(set, "%.15g <= ", row->lhs);
102
103 /* print coefficients */
104 if( row->len == 0 )
105 {
107 }
108 for( i = 0; i < row->len; ++i )
109 {
110 assert(row->cols[i] != NULL);
111 assert(row->cols[i]->var != NULL);
112 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
113 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
114 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
115 }
116
117 /* print constant */
119 {
120 SCIPsetDebugMsgPrint(set, "%+.15g ", row->constant);
121 }
122
123 /* print right hand side */
124 SCIPsetDebugMsgPrint(set, "<= %.15g\n", row->rhs);
125}
126#else
127#define debugRowPrint(x,y) /**/
128#endif
129
130#ifdef SCIP_DEBUG
131/** method to output column if SCIP_DEBUG is define */
132static
133void debugColPrint(
134 SCIP_SET* set, /**< global SCIP settings */
135 SCIP_COL* col /**< LP column */
136 )
137{
138 int r;
139
140 assert(col != NULL);
141 assert(col->var != NULL);
142
143 /* print bounds */
144 SCIPsetDebugMsgPrint(set, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
145
146 /* print coefficients */
147 if( col->len == 0 )
148 {
149 SCIPsetDebugMsgPrint(set, "<empty>");
150 }
151 for( r = 0; r < col->len; ++r )
152 {
153 assert(col->rows[r] != NULL);
154 assert(col->rows[r]->name != NULL);
155 SCIPsetDebugMsgPrint(set, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
156 }
158}
159#else
160#define debugColPrint(x,y) /**/
161#endif
162
163/*
164 * memory growing methods for dynamically allocated arrays
165 */
166
167/** ensures, that chgcols array can store at least num entries */
168static
170 SCIP_LP* lp, /**< current LP data */
171 SCIP_SET* set, /**< global SCIP settings */
172 int num /**< minimum number of entries to store */
173 )
174{
175 assert(lp->nchgcols <= lp->chgcolssize);
176
177 if( num > lp->chgcolssize )
178 {
179 int newsize;
180
181 newsize = SCIPsetCalcMemGrowSize(set, num);
182 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgcols, newsize) );
183 lp->chgcolssize = newsize;
184 }
185 assert(num <= lp->chgcolssize);
186
187 return SCIP_OKAY;
188}
189
190/** ensures, that chgrows array can store at least num entries */
191static
193 SCIP_LP* lp, /**< current LP data */
194 SCIP_SET* set, /**< global SCIP settings */
195 int num /**< minimum number of entries to store */
196 )
197{
198 assert(lp->nchgrows <= lp->chgrowssize);
199
200 if( num > lp->chgrowssize )
201 {
202 int newsize;
203
204 newsize = SCIPsetCalcMemGrowSize(set, num);
205 SCIP_ALLOC( BMSreallocMemoryArray(&lp->chgrows, newsize) );
206 lp->chgrowssize = newsize;
207 }
208 assert(num <= lp->chgrowssize);
209
210 return SCIP_OKAY;
211}
212
213/** ensures, that lpicols array can store at least num entries */
214static
216 SCIP_LP* lp, /**< current LP data */
217 SCIP_SET* set, /**< global SCIP settings */
218 int num /**< minimum number of entries to store */
219 )
220{
221 assert(lp->nlpicols <= lp->lpicolssize);
222
223 if( num > lp->lpicolssize )
224 {
225 int newsize;
226
227 newsize = SCIPsetCalcMemGrowSize(set, num);
228 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpicols, newsize) );
229 lp->lpicolssize = newsize;
230 }
231 assert(num <= lp->lpicolssize);
232
233 return SCIP_OKAY;
234}
235
236/** ensures, that lpirows array can store at least num entries */
237static
239 SCIP_LP* lp, /**< current LP data */
240 SCIP_SET* set, /**< global SCIP settings */
241 int num /**< minimum number of entries to store */
242 )
243{
244 assert(lp->nlpirows <= lp->lpirowssize);
245
246 if( num > lp->lpirowssize )
247 {
248 int newsize;
249
250 newsize = SCIPsetCalcMemGrowSize(set, num);
251 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lpirows, newsize) );
252 lp->lpirowssize = newsize;
253 }
254 assert(num <= lp->lpirowssize);
255
256 return SCIP_OKAY;
257}
258
259/** ensures, that cols array can store at least num entries */
260static
262 SCIP_LP* lp, /**< current LP data */
263 SCIP_SET* set, /**< global SCIP settings */
264 int num /**< minimum number of entries to store */
265 )
266{
267 assert(lp->ncols <= lp->colssize);
268
269 if( num > lp->colssize )
270 {
271 int newsize;
272
273 newsize = SCIPsetCalcMemGrowSize(set, num);
274 SCIP_ALLOC( BMSreallocMemoryArray(&lp->cols, newsize) );
275 lp->colssize = newsize;
276 }
277 assert(num <= lp->colssize);
278
279 return SCIP_OKAY;
280}
281
282/** ensures, that soldirection array can store at least num entries */
283static
285 SCIP_LP* lp, /**< current LP data */
286 int num /**< minimum number of entries to store */
287 )
288{
289 if( num > lp->soldirectionsize )
290 {
293
294 lp->soldirectionsize = num;
295 }
296
297 assert(num <= lp->soldirectionsize);
298
299 return SCIP_OKAY;
300}
301
302/** ensures, that lazy cols array can store at least num entries */
303static
305 SCIP_LP* lp, /**< current LP data */
306 SCIP_SET* set, /**< global SCIP settings */
307 int num /**< minimum number of entries to store */
308 )
309{
310 assert(lp->nlazycols <= lp->lazycolssize);
311
312 if( num > lp->lazycolssize )
313 {
314 int newsize;
315
316 newsize = SCIPsetCalcMemGrowSize(set, num);
317 SCIP_ALLOC( BMSreallocMemoryArray(&lp->lazycols, newsize) );
318 lp->lazycolssize = newsize;
319 }
320 assert(num <= lp->lazycolssize);
321
322 return SCIP_OKAY;
323}
324
325/** ensures, that rows array can store at least num entries */
326static
328 SCIP_LP* lp, /**< current LP data */
329 SCIP_SET* set, /**< global SCIP settings */
330 int num /**< minimum number of entries to store */
331 )
332{
333 assert(lp->nrows <= lp->rowssize);
334
335 if( num > lp->rowssize )
336 {
337 int newsize;
338
339 newsize = SCIPsetCalcMemGrowSize(set, num);
340 SCIP_ALLOC( BMSreallocMemoryArray(&lp->rows, newsize) );
341 lp->rowssize = newsize;
342 }
343 assert(num <= lp->rowssize);
344
345 return SCIP_OKAY;
346}
347
348/** ensures, that row array of column can store at least num entries */
349static
351 SCIP_COL* col, /**< LP column */
352 BMS_BLKMEM* blkmem, /**< block memory */
353 SCIP_SET* set, /**< global SCIP settings */
354 int num /**< minimum number of entries to store */
355 )
356{
357 assert(col != NULL);
358 assert(col->len <= col->size);
359
360 if( num > col->size )
361 {
362 int newsize;
363
364 newsize = SCIPsetCalcMemGrowSize(set, num);
365 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->rows, col->size, newsize) );
366 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->vals, col->size, newsize) );
367 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &col->linkpos, col->size, newsize) );
368 col->size = newsize;
369 }
370 assert(num <= col->size);
371
372 return SCIP_OKAY;
373}
374
375/** save current LP values dependent on the solution */
376static
378 SCIP_LP* lp, /**< LP data */
379 SCIP_STAT* stat, /**< problem statistics */
380 BMS_BLKMEM* blkmem /**< block memory */
381 )
382{
383 SCIP_LPSOLVALS* storedsolvals;
384
385 assert(lp != NULL);
386 assert(stat != NULL);
387 assert(blkmem != NULL);
388
389 /* allocate memory for storage */
390 if( lp->storedsolvals == NULL )
391 {
393 }
394 storedsolvals = lp->storedsolvals;
395
396 /* store values */
397 storedsolvals->lpsolstat = lp->lpsolstat;
398 storedsolvals->lpobjval = lp->lpobjval;
399 storedsolvals->primalfeasible = lp->primalfeasible;
400 storedsolvals->primalchecked = lp->primalchecked;
401 storedsolvals->dualfeasible = lp->dualfeasible;
402 storedsolvals->dualchecked = lp->dualchecked;
403 storedsolvals->solisbasic = lp->solisbasic;
404 storedsolvals->lpissolved = lp->solved;
405
406 return SCIP_OKAY;
407}
408
409/** restore LP solution values in column */
410static
412 SCIP_LP* lp, /**< LP data */
413 BMS_BLKMEM* blkmem, /**< block memory */
414 SCIP_Longint validlp /**< number of lp for which restored values are valid */
415 )
416{
417 SCIP_LPSOLVALS* storedsolvals;
418
419 assert(lp != NULL);
420 assert(blkmem != NULL);
421
422 /* if stored values are available, restore them */
423 storedsolvals = lp->storedsolvals;
424 if( storedsolvals != NULL )
425 {
426 lp->solved = storedsolvals->lpissolved;
427 lp->validsollp = validlp;
428
429 lp->lpsolstat = storedsolvals->lpsolstat;
430 lp->lpobjval = storedsolvals->lpobjval;
431 lp->primalfeasible = storedsolvals->primalfeasible;
432 lp->primalchecked = storedsolvals->primalchecked;
433 lp->dualfeasible = storedsolvals->dualfeasible;
434 lp->dualchecked = storedsolvals->dualchecked;
435 lp->solisbasic = storedsolvals->solisbasic;
436
437 /* solution values are stored only for LPs solved to optimality or unboundedness */
438 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL ||
444 lp->validsollp == -1);
445 }
446 /* no values available, mark LP as unsolved */
447 else
448 {
449 lp->solved = FALSE;
450 lp->validsollp = -1;
451
454 lp->primalfeasible = FALSE;
455 lp->primalchecked = FALSE;
456 lp->dualfeasible = FALSE;
457 lp->dualchecked = FALSE;
458 lp->solisbasic = FALSE;
459 lp->validfarkaslp = -1;
460 }
461
462 lp->validdegeneracylp = -1;
463
464 /* intentionally keep storage space allocated */
465
466 return SCIP_OKAY;
467}
468
469/** save current LP solution values stored in each column */
470static
472 SCIP_COL* col, /**< LP column */
473 BMS_BLKMEM* blkmem /**< block memory */
474 )
475{
476 SCIP_COLSOLVALS* storedsolvals;
477
478 assert(col != NULL);
479 assert(blkmem != NULL);
480
481 /* allocate memory for storage */
482 if( col->storedsolvals == NULL )
483 {
485 }
486 storedsolvals = col->storedsolvals;
487
488 /* store values */
489 storedsolvals->primsol = col->primsol;
490 storedsolvals->redcost = col->redcost;
491 storedsolvals->basisstatus = col->basisstatus; /*lint !e641 !e732*/
492
493 return SCIP_OKAY;
494}
495
496/** restore LP solution values in column */
497static
499 SCIP_COL* col, /**< LP column */
500 BMS_BLKMEM* blkmem, /**< block memory */
501 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
502 SCIP_Bool freebuffer /**< should buffer for LP solution values be freed? */
503 )
504{
505 SCIP_COLSOLVALS* storedsolvals;
506
507 assert(col != NULL);
508 assert(blkmem != NULL);
509
510 /* if stored values are available, restore them */
511 storedsolvals = col->storedsolvals;
512 if( storedsolvals != NULL )
513 {
514 col->primsol = storedsolvals->primsol;
515 col->redcost = storedsolvals->redcost;
516 col->validredcostlp = validlp;
517 col->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
518
519 /* we do not save the farkas coefficient, since it can be recomputed; thus, we invalidate it here */
520 col->validfarkaslp = -1;
521 }
522 /* if the column was created after performing the storage (possibly during probing), we treat it as implicitly zero;
523 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
524 */
525 else
526 {
527 col->primsol = 0.0;
528 col->validredcostlp = -1;
529 col->validfarkaslp = -1;
530 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
531 }
532
533 /* free memory */
534 if( freebuffer )
535 {
537 assert(col->storedsolvals == NULL);
538 }
539
540 return SCIP_OKAY;
541}
542
543/** save current LP solution values stored in each column */
544static
546 SCIP_ROW* row, /**< LP row */
547 BMS_BLKMEM* blkmem, /**< block memory */
548 SCIP_Bool infeasible /**< is the solution infeasible? */
549 )
550{
551 SCIP_ROWSOLVALS* storedsolvals;
552
553 assert(row != NULL);
554 assert(blkmem != NULL);
555
556 /* allocate memory for storage */
557 if( row->storedsolvals == NULL )
558 {
560 }
561 storedsolvals = row->storedsolvals;
562
563 /* store values */
564 if ( infeasible )
565 {
566 storedsolvals->dualsol = row->dualfarkas;
567 storedsolvals->activity = SCIP_INVALID;
568 storedsolvals->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
569 }
570 else
571 {
572 storedsolvals->dualsol = row->dualsol;
573 storedsolvals->activity = row->activity;
574 storedsolvals->basisstatus = row->basisstatus; /*lint !e641 !e732*/
575 }
576
577 return SCIP_OKAY;
578}
579
580/** restore LP solution values in row */
581static
583 SCIP_ROW* row, /**< LP column */
584 BMS_BLKMEM* blkmem, /**< block memory */
585 SCIP_Longint validlp, /**< number of lp for which restored values are valid */
586 SCIP_Bool freebuffer, /**< should buffer for LP solution values be freed? */
587 SCIP_Bool infeasible /**< is the solution infeasible? */
588 )
589{
590 SCIP_ROWSOLVALS* storedsolvals;
591
592 assert(row != NULL);
593 assert(blkmem != NULL);
594
595 /* if stored values are available, restore them */
596 storedsolvals = row->storedsolvals;
597 if( storedsolvals != NULL )
598 {
599 if ( infeasible )
600 row->dualfarkas = storedsolvals->dualsol;
601 else
602 row->dualsol = storedsolvals->dualsol;
603 row->activity = storedsolvals->activity;
604 row->validactivitylp = validlp;
605 row->basisstatus = storedsolvals->basisstatus; /*lint !e641 !e732*/
606 }
607 /* if the row was created after performing the storage (possibly during probing), we treat it as basic;
608 * we make sure to invalidate the reduced cost and farkas coefficient, which are not available
609 */
610 else
611 {
612 row->dualsol = 0.0;
613 row->dualfarkas = 0.0;
614 row->activity = SCIP_INVALID;
615 row->validactivitylp = -1;
616 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
617 }
618
619 /* free memory */
620 if( freebuffer )
621 {
623 assert(row->storedsolvals == NULL);
624 }
625
626 return SCIP_OKAY;
627}
628
629/** ensures, that column array of row can store at least num entries */
631 SCIP_ROW* row, /**< LP row */
632 BMS_BLKMEM* blkmem, /**< block memory */
633 SCIP_SET* set, /**< global SCIP settings */
634 int num /**< minimum number of entries to store */
635 )
636{
637 assert(row != NULL);
638 assert(row->len <= row->size);
639
640 if( num > row->size )
641 {
642 int newsize;
643
644 newsize = SCIPsetCalcMemGrowSize(set, num);
645 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols, row->size, newsize) );
646 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->cols_index, row->size, newsize) );
647 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->vals, row->size, newsize) );
648 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &row->linkpos, row->size, newsize) );
649 row->size = newsize;
650 }
651 assert(num <= row->size);
652
653 return SCIP_OKAY;
654}
655
656
657#ifdef SCIP_MORE_DEBUG /* enable this to check the sortings within rows (for debugging, very slow!) */
658static SCIP_Bool msgdisp_checkrow = FALSE;
659
660static
661void checkRow(
662 SCIP_ROW* row
663 )
664{
665 int i;
666
667 if( !msgdisp_checkrow )
668 {
669 printf("LP ROW CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
670 msgdisp_checkrow = TRUE;
671 }
672
673 /* validate sorting of LP part of row */
674 if( row->lpcolssorted && row->nlpcols > 0)
675 {
676 assert(row->cols_index[0] == row->cols[0]->index);
677 for( i = 1; i < row->nlpcols; ++i )
678 {
679 assert(row->cols_index[i] == row->cols[i]->index);
680 assert(row->cols_index[i] >= row->cols_index[i-1]);
681 }
682 }
683
684 /* validate sorting of non-LP part of row */
685 if( row->nonlpcolssorted && row->len > row->nlpcols )
686 {
687 assert(row->cols_index[row->nlpcols] == row->cols[row->nlpcols]->index);
688 for( i = row->nlpcols + 1; i < row->len; ++i )
689 {
690 assert(row->cols_index[i] == row->cols[i]->index);
691 assert(row->cols_index[i] >= row->cols_index[i-1]);
692 }
693 }
694}
695#else
696#define checkRow(row) /**/
697#endif
698
699#ifdef SCIP_MORE_DEBUG /* enable this to check norms of rows (for debugging, very slow!) */
700static
701void checkRowSqrnorm(
702 SCIP_ROW* row
703 )
704{
705 SCIP_COL** cols;
706 SCIP_Real sqrnorm;
707 int c;
708
709 cols = row->cols;
710 assert(cols != NULL || row->len == 0);
711
712 sqrnorm = 0.0;
713
714 for( c = row->len - 1; c >= 0; --c )
715 {
716 if( cols[c]->lppos >= 0 )
717 sqrnorm += SQR(row->vals[c]);
718 }
719
720 assert(ABS(sqrnorm - row->sqrnorm) < 1e-06 * MAX(1.0,sqrnorm));
721}
722
723static
724void checkRowSumnorm(
725 SCIP_ROW* row
726 )
727{
728 SCIP_COL** cols;
729 SCIP_Real sumnorm;
730 int c;
731
732 cols = row->cols;
733 assert(cols != NULL || row->len == 0);
734
735 sumnorm = 0.0;
736
737 for( c = row->len - 1; c >= 0; --c )
738 {
739 if( cols[c]->lppos >= 0 )
740 sumnorm += REALABS(row->vals[c]);
741 }
742
743 assert(ABS(sumnorm - row->sumnorm) < 1e-06 * MAX(1.0,sumnorm));
744}
745
746static
747void checkRowObjprod(
748 SCIP_ROW* row
749 )
750{
751 SCIP_COL** cols;
752 SCIP_Real objprod;
753 int c;
754
755 cols = row->cols;
756 assert(cols != NULL || row->len == 0);
757
758 objprod = 0.0;
759
760 for( c = row->len - 1; c >= 0; --c )
761 {
762 if( cols[c]->lppos >= 0 )
763 objprod += row->vals[c] * cols[c]->unchangedobj;
764 }
765
766 assert(ABS(objprod - row->objprod) < 1e-06 * MAX(1.0,objprod));
767}
768#else
769#define checkRowSqrnorm(row) /**/
770#define checkRowSumnorm(row) /**/
771#define checkRowObjprod(row) /**/
772#endif
773
774/*
775 * Local methods for pseudo and loose objective values
776 */
777
778/* recompute the loose objective value from scratch, if it was marked to be unreliable before */
779static
781 SCIP_LP* lp, /**< current LP data */
782 SCIP_SET* set, /**< global SCIP settings */
783 SCIP_PROB* prob /**< problem data */
784 )
785{
786 SCIP_VAR** vars;
787 SCIP_Real obj;
788 int nvars;
789 int v;
790
791 assert(lp != NULL);
792 assert(set != NULL);
793 assert(prob != NULL);
794 assert(!lp->looseobjvalid);
795
796 vars = prob->vars;
797 nvars = prob->nvars;
798 lp->looseobjval = 0.0;
799
800 /* iterate over all variables in the problem */
801 for( v = 0; v < nvars; ++v )
802 {
803 if( SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_LOOSE )
804 {
805 obj = SCIPvarGetObj(vars[v]);
806
807 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
809 lp->looseobjval += obj * SCIPvarGetLbLocal(vars[v]);
810 else if( SCIPsetIsNegative(set, obj) && !SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
811 lp->looseobjval += obj * SCIPvarGetUbLocal(vars[v]);
812 }
813 }
814
815 /* the recomputed value is reliable */
816 lp->rellooseobjval = lp->looseobjval;
817 lp->looseobjvalid = TRUE;
818}
819
820/* recompute the pseudo solution value from scratch, if it was marked to be unreliable before */
821static
823 SCIP_LP* lp, /**< current LP data */
824 SCIP_SET* set, /**< global SCIP settings */
825 SCIP_PROB* prob /**< problem data */
826 )
827{
828 SCIP_VAR** vars;
829 int nvars;
830 int v;
831
832 assert(lp != NULL);
833 assert(set != NULL);
834 assert(prob != NULL);
835 assert(!lp->pseudoobjvalid);
836
837 vars = prob->vars;
838 nvars = prob->nvars;
839 lp->pseudoobjval = 0.0;
840
841 /* iterate over all variables in the problem */
842 for( v = 0; v < nvars; ++v )
843 {
844 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
845 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
847 {
848 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbLocal(vars[v]);
849 }
850 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
852 {
853 lp->pseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbLocal(vars[v]);
854 }
855 }
856
857 /* the recomputed value is reliable */
859 lp->pseudoobjvalid = TRUE;
860}
861
862/* recompute the global pseudo solution value from scratch, if it was marked to be unreliable before */
863static
865 SCIP_LP* lp, /**< current LP data */
866 SCIP_SET* set, /**< global SCIP settings */
867 SCIP_PROB* prob /**< problem data */
868 )
869{
870 SCIP_VAR** vars;
871 int nvars;
872 int v;
873
874 assert(lp != NULL);
875 assert(set != NULL);
876 assert(prob != NULL);
877 assert(!lp->glbpseudoobjvalid);
878
879 vars = prob->vars;
880 nvars = prob->nvars;
881 lp->glbpseudoobjval = 0.0;
882
883 /* iterate over all variables in the problem */
884 for( v = 0; v < nvars; ++v )
885 {
886 /* we are only interested in variables with a finite impact, because the infinity counters should be correct */
887 if( SCIPsetIsPositive(set, SCIPvarGetObj(vars[v])) &&
889 {
890 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetLbGlobal(vars[v]);
891 }
892 else if( SCIPsetIsNegative(set, SCIPvarGetObj(vars[v])) &&
894 {
895 lp->glbpseudoobjval += SCIPvarGetObj(vars[v]) * SCIPvarGetUbGlobal(vars[v]);
896 }
897 }
898
899 /* the recomputed value is reliable */
902}
903
904/** gets finite part of objective value of current LP that results from LOOSE variables only */
905static
907 SCIP_LP* lp, /**< current LP data */
908 SCIP_SET* set, /**< global SCIP settings */
909 SCIP_PROB* prob /**< problem data */
910 )
911{
912 assert(lp != NULL);
913 assert(set != NULL);
914 assert(prob != NULL);
915 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
916 assert(lp->flushed);
917 assert(lp->looseobjvalinf == 0);
918
919 /* recalculate the loose objective value, if needed */
920 if( !lp->looseobjvalid )
922
923 return lp->looseobjval;
924}
925
926/** gets finite part of pseudo objective value of current LP */
927static
929 SCIP_LP* lp, /**< current LP data */
930 SCIP_SET* set, /**< global SCIP settings */
931 SCIP_PROB* prob /**< problem data */
932 )
933{
934 assert(lp != NULL);
935 assert(set != NULL);
936 assert(prob != NULL);
937
938 /* recalculate the pseudo objective value, if needed */
939 if( !lp->pseudoobjvalid )
941
942 return lp->pseudoobjval;
943}
944
945/*
946 * Sorting and searching rows and columns
947 */
948
949
950/** comparison method for sorting rows by non-decreasing index */
952{
953 assert(elem1 != NULL);
954 assert(elem2 != NULL);
955
956 if( ((SCIP_ROW*)elem1)->index < ((SCIP_ROW*)elem2)->index )
957 return -1;
958 else if( ((SCIP_ROW*)elem1)->index > ((SCIP_ROW*)elem2)->index )
959 return +1;
960 else
961 {
962 assert(SCIProwGetIndex((SCIP_ROW*)(elem1)) == SCIProwGetIndex(((SCIP_ROW*)elem2)));
963 return 0;
964 }
965}
966
967
968/** sorts column entries of linked rows currently in the LP such that lower row indices precede higher ones */
969static
971 SCIP_COL* col /**< column to be sorted */
972 )
973{
974 int i;
975
976 assert(col != NULL);
977
978 /* check, if column is already sorted in the LP part */
979 if( col->lprowssorted )
980 return;
981
982 /* sort coefficients */
983 SCIPsortPtrRealInt((void**)col->rows, col->vals, col->linkpos, SCIProwComp, col->nlprows );
984
985 /* update links */
986 for( i = 0; i < col->nlprows; ++i )
987 {
988 if( col->linkpos[i] >= 0 )
989 {
990 assert(col->rows[i]->cols[col->linkpos[i]] == col);
991 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
992 col->rows[i]->linkpos[col->linkpos[i]] = i;
993 }
994 }
995
996 col->lprowssorted = TRUE;
997}
998
999/** sorts column entries of unlinked rows or rows currently not in the LP such that lower row indices precede higher
1000 * ones
1001 */
1002static
1004 SCIP_COL* col /**< column to be sorted */
1005 )
1006{
1007 int i;
1008
1009 assert(col != NULL);
1010
1011 /* check, if column is already sorted in the non-LP part */
1012 if( col->nonlprowssorted )
1013 return;
1014
1015 /* sort coefficients */
1016 SCIPsortPtrRealInt((void**)(&(col->rows[col->nlprows])), &(col->vals[col->nlprows]), &(col->linkpos[col->nlprows]), SCIProwComp, col->len - col->nlprows);
1017
1018 /* update links */
1019 for( i = col->nlprows; i < col->len; ++i )
1020 {
1021 if( col->linkpos[i] >= 0 )
1022 {
1023 assert(col->rows[i]->cols[col->linkpos[i]] == col);
1024 assert(col->rows[i]->linkpos[col->linkpos[i]] >= 0);
1025 col->rows[i]->linkpos[col->linkpos[i]] = i;
1026 }
1027 }
1028
1029 col->nonlprowssorted = TRUE;
1030}
1031
1032/** sorts row entries of linked columns currently in the LP such that lower column indices precede higher ones */
1033static
1035 SCIP_ROW* row /**< row to be sorted */
1036 )
1037{
1038 int i;
1039
1040 assert(row != NULL);
1041
1042 /* check, if row is already sorted in the LP part, or if the sorting should be delayed */
1043 if( row->lpcolssorted || row->delaysort )
1044 return;
1045
1046 /* sort coefficients */
1047 SCIPsortIntPtrIntReal(row->cols_index, (void**)row->cols, row->linkpos, row->vals, row->nlpcols);
1048
1049 /* update links */
1050 for( i = 0; i < row->nlpcols; ++i )
1051 {
1052 if( row->linkpos[i] >= 0 )
1053 {
1054 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1055 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1056 row->cols[i]->linkpos[row->linkpos[i]] = i;
1057 }
1058 }
1059
1060 row->lpcolssorted = TRUE;
1061}
1062
1063/** sorts row entries of unlinked columns or columns currently not in the LP such that lower column indices precede
1064 * higher ones
1065 */
1066static
1068 SCIP_ROW* row /**< row to be sorted */
1069 )
1070{
1071 int i;
1072
1073 assert(row != NULL);
1074
1075 checkRow(row);
1076
1077 /* check, if row is already sorted in the non-LP part, or if the sorting should be delayed */
1078 if( row->nonlpcolssorted || row->delaysort )
1079 return;
1080
1081 /* sort coefficients */
1082 SCIPsortIntPtrIntReal(&(row->cols_index[row->nlpcols]), (void**)(&(row->cols[row->nlpcols])), &(row->linkpos[row->nlpcols]), &(row->vals[row->nlpcols]), row->len - row->nlpcols);
1083
1084 /* update links */
1085 for( i = row->nlpcols; i < row->len; ++i )
1086 {
1087 if( row->linkpos[i] >= 0 )
1088 {
1089 assert(row->cols[i]->rows[row->linkpos[i]] == row);
1090 assert(row->cols[i]->linkpos[row->linkpos[i]] >= 0);
1091 row->cols[i]->linkpos[row->linkpos[i]] = i;
1092 }
1093 }
1094
1095 checkRow(row);
1096
1097 row->nonlpcolssorted = TRUE;
1098}
1099
1100/** searches coefficient in part of the column, returns position in col vector or -1 if not found */
1101static
1103 SCIP_COL* col, /**< column to be searched in */
1104 const SCIP_ROW* row, /**< coefficient to be searched for */
1105 int minpos, /**< first position of search range */
1106 int maxpos /**< last position of search range */
1107 )
1108{
1109 int pos;
1110 int idx;
1111 int searchidx;
1112
1113 assert(col != NULL);
1114 assert(row != NULL);
1115
1116 /* binary search */
1117 searchidx = row->index;
1118 while(minpos <= maxpos)
1119 {
1120 pos = (minpos + maxpos)/2;
1121 assert(0 <= pos && pos < col->len);
1122 assert(col->rows[pos] != NULL);
1123 assert((pos < col->nlprows) == (col->rows[pos]->lppos >= 0 && col->linkpos[pos] >= 0));
1124 idx = col->rows[pos]->index;
1125 if( searchidx == idx )
1126 return pos;
1127 else if( searchidx < idx )
1128 maxpos = pos-1;
1129 else
1130 minpos = pos+1;
1131 }
1132
1133 return -1;
1134}
1135
1136/** searches coefficient in column, returns position in col vector or -1 if not found */
1137static
1139 SCIP_COL* col, /**< column to be searched in */
1140 const SCIP_ROW* row /**< coefficient to be searched for */
1141 )
1142{
1143 int pos;
1144
1145 assert(col != NULL);
1146 assert(row != NULL);
1147
1148 pos = -1;
1149
1150 /* search in the linked LP rows */
1151 if( row->lppos >= 0 )
1152 {
1153 /* column has to be sorted, such that binary search works */
1154 colSortLP(col);
1155 assert(col->lprowssorted);
1156
1157 pos = colSearchCoefPart(col, row, 0, col->nlprows-1);
1158 if( pos >= 0 )
1159 return pos;
1160 }
1161
1162 /* search in the non-LP/unlinked rows */
1163 if( row->lppos == -1 || col->nunlinked > 0 )
1164 {
1165 /* column has to be sorted, such that binary search works */
1166 colSortNonLP(col);
1167 assert(col->nonlprowssorted);
1168
1169 pos = colSearchCoefPart(col, row, col->nlprows, col->len-1);
1170 }
1171
1172 return pos;
1173}
1174
1175/** searches coefficient in part of the row, returns position in col vector or -1 if not found */
1176static
1178 SCIP_ROW* row, /**< row to be searched in */
1179 const SCIP_COL* col, /**< coefficient to be searched for */
1180 int minpos, /**< first position of search range */
1181 int maxpos /**< last position of search range */
1182 )
1183{
1184 int pos;
1185 int idx;
1186 int searchidx;
1187
1188 assert(row != NULL);
1189 assert(col != NULL);
1190
1191 /* binary search */
1192 searchidx = col->index;
1193 while(minpos <= maxpos)
1194 {
1195 pos = (minpos + maxpos)/2;
1196 assert(0 <= pos && pos < row->len);
1197 assert(row->cols[pos] != NULL);
1198 assert((pos < row->nlpcols) == (row->cols[pos]->lppos >= 0 && row->linkpos[pos] >= 0));
1199 assert(row->cols_index[pos] == row->cols[pos]->index);
1200 idx = row->cols_index[pos];
1201 if( searchidx == idx )
1202 return pos;
1203 else if( searchidx < idx )
1204 maxpos = pos-1;
1205 else
1206 minpos = pos+1;
1207 }
1208
1209 return -1;
1210}
1211
1212/** searches coefficient in row, returns position in row vector or -1 if not found;
1213 * if the sorting of the row is delayed, returns -1
1214 */
1215static
1217 SCIP_ROW* row, /**< row to be searched in */
1218 const SCIP_COL* col /**< coefficient to be searched for */
1219 )
1220{
1221 int pos;
1222
1223 assert(row != NULL);
1224 assert(col != NULL);
1225
1226 if( row->delaysort )
1227 return -1;
1228
1229 pos = -1;
1230
1231 /* search in the linked LP columns */
1232 if( col->lppos >= 0 )
1233 {
1234 /* row has to be sorted, such that binary search works */
1235 rowSortLP(row);
1236 assert(row->lpcolssorted);
1237
1238 pos = rowSearchCoefPart(row, col, 0, row->nlpcols-1);
1239 }
1240
1241 /* search in the non-LP/unlinked columns */
1242 if( pos == -1 && (col->lppos == -1 || row->nunlinked > 0) )
1243 {
1244 /* row has to be sorted, such that binary search works */
1245 rowSortNonLP(row);
1246 assert(row->nonlpcolssorted);
1247
1248 pos = rowSearchCoefPart(row, col, row->nlpcols, row->len-1);
1249 }
1250
1251#ifndef NDEBUG
1252 /* validate result */
1253 assert(-1 <= pos && pos < row->len);
1254 if( pos >= 0 )
1255 assert(row->cols[pos] == col);
1256 else
1257 {
1258 int i;
1259 for( i = 0; i < row->len; ++i )
1260 assert(row->cols[i] != col);
1261 }
1262#endif
1263
1264 return pos;
1265}
1266
1267/** moves a coefficient in a column to a different place, and updates all corresponding data structures */
1268static
1270 SCIP_COL* col, /**< LP column */
1271 int oldpos, /**< old position of coefficient */
1272 int newpos /**< new position of coefficient */
1273 )
1274{
1275 assert(col != NULL);
1276 assert(0 <= oldpos && oldpos < col->len);
1277 assert(0 <= newpos && newpos < col->len);
1278 assert(col->rows[oldpos] != NULL);
1279
1280 if( oldpos == newpos )
1281 return;
1282
1283 col->rows[newpos] = col->rows[oldpos];
1284 col->vals[newpos] = col->vals[oldpos];
1285 col->linkpos[newpos] = col->linkpos[oldpos];
1286
1287 /* update link position in row */
1288 if( col->linkpos[newpos] >= 0 )
1289 {
1290 assert(col->rows[newpos]->cols[col->linkpos[newpos]] == col);
1291 assert(col->rows[newpos]->linkpos[col->linkpos[newpos]] == oldpos);
1292
1293 col->rows[newpos]->linkpos[col->linkpos[newpos]] = newpos;
1294 }
1295
1296 /* update sorted flags */
1297 if( col->rows[newpos]->lppos >= 0 && col->linkpos[newpos] >= 0 )
1298 col->lprowssorted = FALSE;
1299 else
1300 col->nonlprowssorted = FALSE;
1301}
1302
1303/** swaps two coefficients in a column, and updates all corresponding data structures */
1304static
1306 SCIP_COL* col, /**< LP column */
1307 int pos1, /**< position of first coefficient */
1308 int pos2 /**< position of second coefficient */
1309 )
1310{
1311 SCIP_ROW* tmprow;
1312 SCIP_Real tmpval;
1313 int tmplinkpos;
1314
1315 assert(col != NULL);
1316 assert(0 <= pos1 && pos1 < col->len);
1317 assert(0 <= pos2 && pos2 < col->len);
1318 assert(col->rows[pos1] != NULL);
1319
1320 if( pos1 == pos2 )
1321 return;
1322
1323 /* swap coefficients */
1324 tmprow = col->rows[pos2];
1325 tmpval = col->vals[pos2];
1326 tmplinkpos = col->linkpos[pos2];
1327
1328 col->rows[pos2] = col->rows[pos1];
1329 col->vals[pos2] = col->vals[pos1];
1330 col->linkpos[pos2] = col->linkpos[pos1];
1331
1332 col->rows[pos1] = tmprow;
1333 col->vals[pos1] = tmpval;
1334 col->linkpos[pos1] = tmplinkpos;
1335
1336 /* update link position in rows */
1337 if( col->linkpos[pos1] >= 0 )
1338 {
1339 assert(col->rows[pos1]->cols[col->linkpos[pos1]] == col);
1340 assert(col->rows[pos1]->linkpos[col->linkpos[pos1]] == pos2);
1341
1342 col->rows[pos1]->linkpos[col->linkpos[pos1]] = pos1;
1343 }
1344 if( col->linkpos[pos2] >= 0 )
1345 {
1346 assert(col->rows[pos2]->cols[col->linkpos[pos2]] == col);
1347 assert(col->rows[pos2]->linkpos[col->linkpos[pos2]] == pos1);
1348
1349 col->rows[pos2]->linkpos[col->linkpos[pos2]] = pos2;
1350 }
1351
1352 /* update sorted flags */
1353 if( col->rows[pos1]->lppos >= 0 && col->linkpos[pos1] >= 0 )
1354 col->lprowssorted = FALSE;
1355 else
1356 col->nonlprowssorted = FALSE;
1357 if( col->rows[pos2]->lppos >= 0 && col->linkpos[pos2] >= 0 )
1358 col->lprowssorted = FALSE;
1359 else
1360 col->nonlprowssorted = FALSE;
1361}
1362
1363/** moves a coefficient in a row to a different place, and updates all corresponding data structures */
1364static
1366 SCIP_ROW* row, /**< LP row */
1367 int oldpos, /**< old position of coefficient */
1368 int newpos /**< new position of coefficient */
1369 )
1370{
1371 assert(row != NULL);
1372 assert(0 <= oldpos && oldpos < row->len);
1373 assert(0 <= newpos && newpos < row->len);
1374 assert(row->cols[oldpos] != NULL);
1375
1376 if( oldpos == newpos )
1377 return;
1378
1379 row->cols[newpos] = row->cols[oldpos];
1380 row->cols_index[newpos] = row->cols_index[oldpos];
1381 row->vals[newpos] = row->vals[oldpos];
1382 row->linkpos[newpos] = row->linkpos[oldpos];
1383
1384 /* update link position in column */
1385 if( row->linkpos[newpos] >= 0 )
1386 {
1387 assert(row->cols[newpos]->rows[row->linkpos[newpos]] == row);
1388 assert(row->cols[newpos]->linkpos[row->linkpos[newpos]] == oldpos);
1389
1390 row->cols[newpos]->linkpos[row->linkpos[newpos]] = newpos;
1391 }
1392
1393 /* update sorted flags */
1394 if( row->cols[newpos]->lppos >= 0 && row->linkpos[newpos] >= 0 )
1395 row->lpcolssorted = FALSE;
1396 else
1397 row->nonlpcolssorted = FALSE;
1398}
1399
1400/** swaps two coefficients in a row, and updates all corresponding data structures */
1401static
1403 SCIP_ROW* row, /**< LP row */
1404 int pos1, /**< position of first coefficient */
1405 int pos2 /**< position of second coefficient */
1406 )
1407{
1408 SCIP_COL* tmpcol;
1409 SCIP_Real tmpval;
1410 int tmpindex;
1411 int tmplinkpos;
1412
1413 assert(row != NULL);
1414 assert(0 <= pos1 && pos1 < row->len);
1415 assert(0 <= pos2 && pos2 < row->len);
1416 assert(row->cols[pos1] != NULL);
1417 assert(row->cols[pos1]->index == row->cols_index[pos1]);
1418
1419 if( pos1 == pos2 )
1420 return;
1421
1422 /* swap coefficients */
1423 tmpcol = row->cols[pos2];
1424 tmpindex = row->cols_index[pos2];
1425 tmpval = row->vals[pos2];
1426 tmplinkpos = row->linkpos[pos2];
1427
1428 row->cols[pos2] = row->cols[pos1];
1429 row->cols_index[pos2] = row->cols_index[pos1];
1430 row->vals[pos2] = row->vals[pos1];
1431 row->linkpos[pos2] = row->linkpos[pos1];
1432
1433 row->cols[pos1] = tmpcol;
1434 row->cols_index[pos1] = tmpindex;
1435 row->vals[pos1] = tmpval;
1436 row->linkpos[pos1] = tmplinkpos;
1437
1438 /* update link position in columns */
1439 if( row->linkpos[pos1] >= 0 )
1440 {
1441 assert(row->cols[pos1]->rows[row->linkpos[pos1]] == row);
1442 assert(row->cols[pos1]->linkpos[row->linkpos[pos1]] == pos2);
1443
1444 row->cols[pos1]->linkpos[row->linkpos[pos1]] = pos1;
1445 }
1446 if( row->linkpos[pos2] >= 0 )
1447 {
1448 assert(row->cols[pos2]->rows[row->linkpos[pos2]] == row);
1449 assert(row->cols[pos2]->linkpos[row->linkpos[pos2]] == pos1);
1450
1451 row->cols[pos2]->linkpos[row->linkpos[pos2]] = pos2;
1452 }
1453
1454 /* update sorted flags */
1455 if( row->cols[pos1]->lppos >= 0 && row->linkpos[pos1] >= 0 )
1456 row->lpcolssorted = FALSE;
1457 else
1458 row->nonlpcolssorted = FALSE;
1459 if( row->cols[pos2]->lppos >= 0 && row->linkpos[pos2] >= 0 )
1460 row->lpcolssorted = FALSE;
1461 else
1462 row->nonlpcolssorted = FALSE;
1463}
1464
1465/** issues a ROWCOEFCHANGED event on the given row */
1466static
1468 SCIP_ROW* row, /**< row which coefficient has changed */
1469 BMS_BLKMEM* blkmem, /**< block memory */
1470 SCIP_SET* set, /**< global SCIP settings */
1471 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1472 SCIP_COL* col, /**< the column which coefficient has changed */
1473 SCIP_Real oldval, /**< old value of the coefficient */
1474 SCIP_Real newval /**< new value of the coefficient */
1475 )
1476{
1477 assert(row != NULL);
1478 assert(row->eventfilter != NULL);
1479 assert(col != NULL);
1480
1481 /* check, if the row is being tracked for coefficient changes
1482 * if so, issue ROWCOEFCHANGED event
1483 */
1484 if( (row->eventfilter->len > 0 && (row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWCOEFCHANGED) != 0) )
1485 {
1486 SCIP_EVENT* event;
1487
1488 SCIP_CALL( SCIPeventCreateRowCoefChanged(&event, blkmem, row, col, oldval, newval) );
1489 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1490 }
1491
1492 return SCIP_OKAY;
1493}
1494
1495/** issues a ROWCONSTCHANGED event on the given row */
1496static
1498 SCIP_ROW* row, /**< row which coefficient has changed */
1499 BMS_BLKMEM* blkmem, /**< block memory */
1500 SCIP_SET* set, /**< global SCIP settings */
1501 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1502 SCIP_Real oldval, /**< old value of the constant */
1503 SCIP_Real newval /**< new value of the constant */
1504 )
1505{
1506 assert(row != NULL);
1507 assert(row->eventfilter != NULL);
1508
1509 /* check, if the row is being tracked for coefficient changes
1510 * if so, issue ROWCONSTCHANGED event
1511 */
1513 {
1514 SCIP_EVENT* event;
1515
1516 SCIP_CALL( SCIPeventCreateRowConstChanged(&event, blkmem, row, oldval, newval) );
1517 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1518 }
1519
1520 return SCIP_OKAY;
1521}
1522
1523/** issues a ROWSIDECHANGED event on the given row */
1524static
1526 SCIP_ROW* row, /**< row which coefficient has changed */
1527 BMS_BLKMEM* blkmem, /**< block memory */
1528 SCIP_SET* set, /**< global SCIP settings */
1529 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1530 SCIP_SIDETYPE side, /**< the side that has changed */
1531 SCIP_Real oldval, /**< old value of side */
1532 SCIP_Real newval /**< new value of side */
1533 )
1534{
1535 assert(row != NULL);
1536 assert(row->eventfilter != NULL);
1537
1538 /* check, if the row is being tracked for coefficient changes
1539 * if so, issue ROWSIDECHANGED event
1540 */
1541 if( (row->eventfilter->len > 0 && !(row->eventfilter->eventmask & SCIP_EVENTTYPE_ROWSIDECHANGED)) )
1542 {
1543 SCIP_EVENT* event;
1544
1545 SCIP_CALL( SCIPeventCreateRowSideChanged(&event, blkmem, row, side, oldval, newval) );
1546 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, row->eventfilter, &event) );
1547 }
1548
1549 return SCIP_OKAY;
1550}
1551
1552#ifdef SCIP_MORE_DEBUG /* enable this to check links between columns and rows in LP data structure (for debugging, very slow!) */
1553
1554#ifdef NDEBUG
1555#define ASSERT(x) do { if( !(x) ) abort(); } while( FALSE )
1556#else
1557#define ASSERT(x) assert(x)
1558#endif
1559
1560static SCIP_Bool msgdisp_checklinks = FALSE;
1561
1562
1563static
1564void checkLinks(
1565 SCIP_LP* lp /**< current LP data */
1566 )
1567{
1568 SCIP_COL* col;
1569 SCIP_ROW* row;
1570 int i;
1571 int j;
1572
1573 ASSERT(lp != NULL);
1574
1575 if( !msgdisp_checklinks )
1576 {
1577 printf("LP LINK CHECKING ACTIVATED! THIS IS VERY SLOW!\n");
1578 msgdisp_checklinks = TRUE;
1579 }
1580
1581 for( i = 0; i < lp->ncols; ++i )
1582 {
1583 col = lp->cols[i];
1584 ASSERT(col != NULL);
1585 ASSERT(!lp->flushed || col->lppos >= 0 || col->primsol == 0.0);
1586 ASSERT(!lp->flushed || col->lppos >= 0 || col->farkascoef == 0.0);
1587 ASSERT(col->nlprows <= col->len);
1588 ASSERT(col->lppos == -1 || col->lppos >= lp->lpifirstchgcol || col->nunlinked == 0);
1589
1590 for( j = 0; j < col->len; ++j )
1591 {
1592 row = col->rows[j];
1593 ASSERT(row != NULL);
1594 ASSERT(!lp->flushed || col->lppos == -1 || col->linkpos[j] >= 0);
1595 ASSERT(col->linkpos[j] == -1 || row->cols[col->linkpos[j]] == col);
1596 ASSERT(col->linkpos[j] == -1 || EPSEQ(row->vals[col->linkpos[j]], col->vals[j], 1e-6));
1597 ASSERT((j < col->nlprows) == (col->linkpos[j] >= 0 && row->lppos >= 0));
1598 }
1599 }
1600
1601 for( i = 0; i < lp->nrows; ++i )
1602 {
1603 row = lp->rows[i];
1604 ASSERT(row != NULL);
1605 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualsol == 0.0);
1606 ASSERT(!lp->flushed || row->lppos >= 0 || row->dualfarkas == 0.0);
1607 ASSERT(row->nlpcols <= row->len);
1608 ASSERT(row->lppos == -1 || row->lppos >= lp->lpifirstchgrow || row->nunlinked == 0);
1609
1610 for( j = 0; j < row->len; ++j )
1611 {
1612 col = row->cols[j];
1613 ASSERT(col != NULL);
1614 ASSERT(!lp->flushed || row->lppos == -1 || row->linkpos[j] >= 0);
1615 ASSERT(row->linkpos[j] == -1 || col->rows[row->linkpos[j]] == row);
1616 ASSERT(row->linkpos[j] == -1 || EPSEQ(col->vals[row->linkpos[j]], row->vals[j], 1e-6));
1617 ASSERT((j < row->nlpcols) == (row->linkpos[j] >= 0 && col->lppos >= 0));
1618 }
1619 }
1620}
1621
1622#undef ASSERT
1623
1624#else
1625#define checkLinks(lp) /**/
1626#endif
1627
1628/*
1629 * Changing announcements
1630 */
1631
1632/** announces, that the given coefficient in the constraint matrix changed */
1633static
1635 SCIP_ROW* row, /**< LP row */
1636 SCIP_COL* col, /**< LP col */
1637 SCIP_LP* lp /**< current LP data */
1638 )
1639{
1640 assert(row != NULL);
1641 assert(col != NULL);
1642 assert(lp != NULL);
1643
1644 if( row->lpipos >= 0 && col->lpipos >= 0 )
1645 {
1646 assert(row->lpipos < lp->nlpirows);
1647 assert(col->lpipos < lp->nlpicols);
1648
1649 /* we have to remember the change only in the row or in the column,
1650 * because the readdition of one vector would change the other automatically.
1651 */
1652 if( row->lpipos >= lp->lpifirstchgrow )
1653 row->coefchanged = TRUE;
1654 else if( col->lpipos >= lp->lpifirstchgcol )
1655 col->coefchanged = TRUE;
1656 else if( lp->lpifirstchgrow - row->lpipos <= lp->lpifirstchgcol - col->lpipos )
1657 {
1658 row->coefchanged = TRUE;
1659 lp->lpifirstchgrow = row->lpipos;
1660 }
1661 else
1662 {
1663 col->coefchanged = TRUE;
1664 lp->lpifirstchgcol = col->lpipos;
1665 }
1666
1667 /* mark the current LP unflushed */
1668 lp->flushed = FALSE;
1669 }
1670
1674 row->validpsactivitydomchg = -1;
1675 row->validactivitybdsdomchg = -1;
1676}
1677
1678
1679
1680/*
1681 * local column changing methods
1682 */
1683
1684/* forward declaration for colAddCoef() */
1685static
1687 SCIP_ROW* row, /**< LP row */
1688 BMS_BLKMEM* blkmem, /**< block memory */
1689 SCIP_SET* set, /**< global SCIP settings */
1690 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1691 SCIP_LP* lp, /**< current LP data */
1692 SCIP_COL* col, /**< LP column */
1693 SCIP_Real val, /**< value of coefficient */
1694 int linkpos /**< position of row in the column's row array, or -1 */
1695 );
1696
1697/** adds a previously non existing coefficient to an LP column */
1698static
1700 SCIP_COL* col, /**< LP column */
1701 BMS_BLKMEM* blkmem, /**< block memory */
1702 SCIP_SET* set, /**< global SCIP settings */
1703 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1704 SCIP_LP* lp, /**< current LP data */
1705 SCIP_ROW* row, /**< LP row */
1706 SCIP_Real val, /**< value of coefficient */
1707 int linkpos /**< position of column in the row's col array, or -1 */
1708 )
1709{
1710 int pos;
1711
1712 assert(blkmem != NULL);
1713 assert(col != NULL);
1714 assert(col->nlprows <= col->len);
1715 assert(col->var != NULL);
1716 assert(row != NULL);
1717 assert(!SCIPsetIsZero(set, val));
1718 /*assert(colSearchCoef(col, row) == -1);*/ /* this assert would lead to slight differences in the solution process */
1719
1720 SCIP_CALL( colEnsureSize(col, blkmem, set, col->len+1) );
1721 assert(col->rows != NULL);
1722 assert(col->vals != NULL);
1723 assert(col->linkpos != NULL);
1724
1725 pos = col->len;
1726 col->len++;
1727
1728 /* 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
1729 * part of the column's arrays
1730 */
1731 if( row->lppos >= 0 && linkpos >= 0 )
1732 {
1733 /* move the first non-LP/not linked row to the end */
1734 if( col->nlprows < pos )
1735 {
1736 colMoveCoef(col, col->nlprows, pos);
1737 pos = col->nlprows;
1738 }
1739 col->nlprows++;
1740 }
1741
1742 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1743 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1744
1745 /* insert the row at the correct position and update the links */
1746 col->rows[pos] = row;
1747 col->vals[pos] = val;
1748 col->linkpos[pos] = linkpos;
1749 if( linkpos == -1 )
1750 {
1751 col->nunlinked++;
1752
1753 /* if the column is in current LP, we have to link it to the row, because otherwise, the primal information
1754 * of the row is not complete
1755 */
1756 if( col->lppos >= 0 )
1757 {
1758 /* this call might swap the current row with the first non-LP/not linked row, s.t. insertion position
1759 * has to be updated
1760 */
1761 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, pos) );
1762 if( row->lppos >= 0 )
1763 pos = col->nlprows-1;
1764 linkpos = col->linkpos[pos];
1765
1766 assert(0 <= linkpos && linkpos < row->len);
1767 assert(row->cols[linkpos] == col);
1768 assert(col->rows[pos] == row);
1769 assert(col->rows[pos]->cols[col->linkpos[pos]] == col);
1770 assert(col->rows[pos]->linkpos[col->linkpos[pos]] == pos);
1771 }
1772 }
1773 else
1774 {
1775 assert(row->linkpos[linkpos] == -1);
1776 assert(row->nunlinked > 0);
1777 row->linkpos[linkpos] = pos;
1778 row->nunlinked--;
1779
1780 /* if the column is in current LP, now both conditions, row->cols[linkpos]->lppos >= 0 and row->linkpos[linkpos] >= 0
1781 * hold, so we have to move the column to the linked LP-cols part of the row's cols array
1782 */
1783 if( col->lppos >= 0 )
1784 {
1785 row->nlpcols++;
1786 rowSwapCoefs(row, linkpos, row->nlpcols-1);
1787
1788 /* if no swap was necessary, mark nonlpcols to be unsorted */
1789 if( linkpos == row->nlpcols-1 )
1790 row->lpcolssorted = FALSE;
1791 }
1792 }
1793
1794 /* update the sorted flags */
1795 if( row->lppos >= 0 && linkpos >= 0 )
1796 {
1797 assert(col->nlprows >= 1);
1798 assert(col->rows[col->nlprows-1] == row);
1799 if( col->nlprows > 1 )
1800 col->lprowssorted = col->lprowssorted && (col->rows[col->nlprows-2]->index < row->index);
1801 }
1802 else
1803 {
1804 assert(col->len - col->nlprows >= 1);
1805 assert(col->rows[col->len-1] == row);
1806 if( col->len - col->nlprows > 1 )
1807 col->nonlprowssorted = col->nonlprowssorted && (col->rows[col->len-2]->index < row->index);
1808 }
1809
1810 coefChanged(row, col, lp);
1811
1812 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to column <%s> (nunlinked=%d)\n",
1813 val, row->name, pos, col->nlprows, col->len, SCIPvarGetName(col->var), col->nunlinked);
1814
1815 return SCIP_OKAY;
1816}
1817
1818/** deletes coefficient at given position from column */
1819static
1821 SCIP_COL* col, /**< column to be changed */
1822 SCIP_SET* set, /**< global SCIP settings */
1823 SCIP_LP* lp, /**< current LP data */
1824 int pos /**< position in column vector to delete */
1825 )
1826{
1827 SCIP_ROW* row;
1828
1829 assert(col != NULL);
1830 assert(col->var != NULL);
1831 assert(set != NULL);
1832 assert(0 <= pos && pos < col->len);
1833 assert(col->rows[pos] != NULL);
1834 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1835 assert((pos < col->nlprows) == (col->linkpos[pos] >= 0 && col->rows[pos]->lppos >= 0));
1836
1837 row = col->rows[pos];
1838 assert((row->lppos >= 0) == (pos < col->nlprows));
1839
1840 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from column <%s>\n",
1841 col->vals[pos], row->name, pos, SCIPvarGetName(col->var));*/
1842
1843 if( col->linkpos[pos] == -1 )
1844 col->nunlinked--;
1845
1846 /* if row is a linked LP row, move last linked LP coefficient to position of empty slot (deleted coefficient) */
1847 if( pos < col->nlprows )
1848 {
1849 colMoveCoef(col, col->nlprows-1, pos);
1850 col->nlprows--;
1851 pos = col->nlprows;
1852 }
1853
1854 /* move last coefficient to position of empty slot */
1855 colMoveCoef(col, col->len-1, pos);
1856 col->len--;
1857
1858 coefChanged(row, col, lp);
1859
1860 return SCIP_OKAY;
1861}
1862
1863/** changes a coefficient at given position of an LP column */
1864static
1866 SCIP_COL* col, /**< LP column */
1867 SCIP_SET* set, /**< global SCIP settings */
1868 SCIP_LP* lp, /**< current LP data */
1869 int pos, /**< position in column vector to change */
1870 SCIP_Real val /**< value of coefficient */
1871 )
1872{
1873 assert(col != NULL);
1874 assert(col->var != NULL);
1875 assert(0 <= pos && pos < col->len);
1876 assert(col->rows[pos] != NULL);
1877 assert(col->linkpos[pos] == -1 || col->rows[pos]->cols[col->linkpos[pos]] == col);
1878
1879 /*debugMsg(scip, "changing coefficient %g * <%s> at position %d of column <%s> to %g\n",
1880 col->vals[pos], col->rows[pos]->name, pos, SCIPvarGetName(col->var), val);*/
1881
1882 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
1883 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
1884
1885 if( SCIPsetIsZero(set, val) )
1886 {
1887 /* delete existing coefficient */
1888 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
1889 }
1890 else if( !SCIPsetIsEQ(set, col->vals[pos], val) )
1891 {
1892 /* change existing coefficient */
1893 col->vals[pos] = val;
1894 coefChanged(col->rows[pos], col, lp);
1895 }
1896
1897 return SCIP_OKAY;
1898}
1899
1900
1901
1902
1903/*
1904 * local row changing methods
1905 */
1906
1907/** update row norms after addition of coefficient */
1908static
1910 SCIP_ROW* row, /**< LP row */
1911 SCIP_SET* set, /**< global SCIP settings */
1912 SCIP_COL* col, /**< column of added coefficient */
1913 SCIP_Real val, /**< value of added coefficient */
1914 SCIP_Bool updateidxvals /**< update min/max idx and min/max val? */
1915 )
1916{
1917 SCIP_Real absval;
1918
1919 assert(row != NULL);
1920 assert(row->nummaxval >= 0);
1921 assert(row->numminval >= 0);
1922 assert(set != NULL);
1923 assert(col != NULL);
1924
1925 absval = REALABS(val);
1926 assert(!SCIPsetIsZero(set, absval));
1927
1928 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
1929 if( col->lppos >= 0 )
1930 {
1931 /* update squared Euclidean norm and sum norm */
1932 row->sqrnorm += SQR(absval);
1933 row->sumnorm += absval;
1934
1935 /* update objective function scalar product */
1936 row->objprod += val * col->unchangedobj;
1937 }
1938
1939 if( updateidxvals )
1940 {
1941 /* update min/maxidx */
1942 row->minidx = MIN(row->minidx, col->index);
1943 row->maxidx = MAX(row->maxidx, col->index);
1944
1945 /* update maximal and minimal non-zero value */
1946 if( row->nummaxval > 0 )
1947 {
1948 if( SCIPsetIsGT(set, absval, row->maxval) )
1949 {
1950 row->maxval = absval;
1951 row->nummaxval = 1;
1952 }
1953 else if( SCIPsetIsGE(set, absval, row->maxval) )
1954 {
1955 /* make sure the maxval is always exactly the same */
1956 row->maxval = MAX(absval, row->maxval);
1957 row->nummaxval++;
1958 }
1959 }
1960 if( row->numminval > 0 )
1961 {
1962 if( SCIPsetIsLT(set, absval, row->minval) )
1963 {
1964 row->minval = absval;
1965 row->numminval = 1;
1966 }
1967 else if( SCIPsetIsLE(set, absval, row->minval) )
1968 {
1969 /* make sure the minval is always exactly the same */
1970 row->minval = MIN(absval, row->minval);
1971 row->numminval++;
1972 }
1973 }
1974 }
1975 else
1976 {
1977 assert(row->minidx <= col->index);
1978 assert(row->maxidx >= col->index);
1979 assert(row->numminval <= 0 || absval >= row->minval);
1980 assert(row->nummaxval <= 0 || absval <= row->maxval);
1981 }
1982}
1983
1984/** update row norms after deletion of coefficient */
1985static
1987 SCIP_ROW* row, /**< LP row */
1988 SCIP_SET* set, /**< global SCIP settings */
1989 SCIP_COL* col, /**< column of deleted coefficient */
1990 SCIP_Real val, /**< value of deleted coefficient */
1991 SCIP_Bool forcenormupdate, /**< should the norms be updated even if lppos of column is -1? */
1992 SCIP_Bool updateindex, /**< should the minimal/maximal column index of row be updated? */
1993 SCIP_Bool updateval /**< should the minimal/maximal value of row be updated? */
1994 )
1995{
1996 SCIP_Real absval;
1997
1998 assert(row != NULL);
1999 assert(row->nummaxval >= 0);
2000 assert(row->numminval >= 0);
2001 assert(set != NULL);
2002 assert(col != NULL);
2003
2004 absval = REALABS(val);
2005 assert(!SCIPsetIsZero(set, absval));
2006 assert(row->nummaxval == 0 || row->maxval >= absval);
2007 assert(row->numminval == 0 || row->minval <= absval);
2008
2009 /* update min/maxidx validity */
2010 if( updateindex && (col->index == row->minidx || col->index == row->maxidx) )
2011 row->validminmaxidx = FALSE;
2012
2013 /* Euclidean norm, sum norm, and objective function scalar product only take LP columns into account */
2014 if( forcenormupdate || col->lppos >= 0 )
2015 {
2016 /* update squared Euclidean norm and sum norm */
2017 row->sqrnorm -= SQR(absval);
2018 row->sqrnorm = MAX(row->sqrnorm, 0.0);
2019 row->sumnorm -= absval;
2020 row->sumnorm = MAX(row->sumnorm, 0.0);
2021
2022 /* update objective function scalar product */
2023 row->objprod -= val * col->unchangedobj;
2024 }
2025
2026 if( updateval )
2027 {
2028 /* update maximal and minimal non-zero value */
2029 if( row->nummaxval > 0 )
2030 {
2031 if( SCIPsetIsGE(set, absval, row->maxval) )
2032 row->nummaxval--;
2033 }
2034 if( row->numminval > 0 )
2035 {
2036 if( SCIPsetIsLE(set, absval, row->minval) )
2037 row->numminval--;
2038 }
2039 }
2040}
2041
2042/** adds a previously non existing coefficient to an LP row */
2043static
2045 SCIP_ROW* row, /**< LP row */
2046 BMS_BLKMEM* blkmem, /**< block memory */
2047 SCIP_SET* set, /**< global SCIP settings */
2048 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2049 SCIP_LP* lp, /**< current LP data */
2050 SCIP_COL* col, /**< LP column */
2051 SCIP_Real val, /**< value of coefficient */
2052 int linkpos /**< position of row in the column's row array, or -1 */
2053 )
2054{
2055 int pos;
2056
2057 assert(row != NULL);
2058 assert(row->nlpcols <= row->len);
2059 assert(blkmem != NULL);
2060 assert(col != NULL);
2061 assert(col->var != NULL);
2062 assert(col->var_probindex == SCIPvarGetProbindex(col->var));
2063 assert(!SCIPsetIsZero(set, val));
2064 /*assert(rowSearchCoef(row, col) == -1);*/ /* this assert would lead to slight differences in the solution process */
2065
2066 if( row->nlocks > 0 )
2067 {
2068 SCIPerrorMessage("cannot add a coefficient to the locked unmodifiable row <%s>\n", row->name);
2069 return SCIP_INVALIDDATA;
2070 }
2071
2072 SCIP_CALL( SCIProwEnsureSize(row, blkmem, set, row->len+1) );
2073 assert(row->cols != NULL);
2074 assert(row->vals != NULL);
2075
2076 pos = row->len;
2077 row->len++;
2078
2079 /* 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
2080 * part of the row's arrays
2081 */
2082 if( col->lppos >= 0 && linkpos >= 0 )
2083 {
2084 /* move the first non-LP/not linked column to the end */
2085 if( row->nlpcols < pos )
2086 {
2087 rowMoveCoef(row, row->nlpcols, pos);
2088 pos = row->nlpcols;
2089 }
2090 row->nlpcols++;
2091 }
2092
2093 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2094 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2095
2096 /* insert the column at the correct position and update the links */
2097 row->cols[pos] = col;
2098 row->cols_index[pos] = col->index;
2099 row->vals[pos] = val;
2100 row->linkpos[pos] = linkpos;
2101 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2102 if( linkpos == -1 )
2103 {
2104 row->nunlinked++;
2105
2106 /* if the row is in current LP, we have to link it to the column, because otherwise, the dual information
2107 * of the column is not complete
2108 */
2109 if( row->lppos >= 0 )
2110 {
2111 /* this call might swap the current column with the first non-LP/not linked column, s.t. insertion position
2112 * has to be updated
2113 */
2114 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, pos) );
2115 if( col->lppos >= 0 )
2116 pos = row->nlpcols-1;
2117 linkpos = row->linkpos[pos];
2118
2119 assert(0 <= linkpos && linkpos < col->len);
2120 assert(col->rows[linkpos] == row);
2121 assert(row->cols[pos] == col);
2122 assert(row->cols[pos]->rows[row->linkpos[pos]] == row);
2123 assert(row->cols[pos]->linkpos[row->linkpos[pos]] == pos);
2124 }
2125 }
2126 else
2127 {
2128 assert(col->linkpos[linkpos] == -1);
2129 assert(col->nunlinked > 0);
2130 col->linkpos[linkpos] = pos;
2131 col->nunlinked--;
2132
2133 /* if the row is in current LP, now both conditions, col->rows[linkpos]->lppos >= 0 and col->linkpos[linkpos] >= 0
2134 * hold, so we have to move the row to the linked LP-rows part of the column's rows array
2135 */
2136 if( row->lppos >= 0 )
2137 {
2138 col->nlprows++;
2139 colSwapCoefs(col, linkpos, col->nlprows-1);
2140
2141 /* if no swap was necessary, mark lprows to be unsorted */
2142 if( linkpos == col->nlprows-1 )
2143 col->lprowssorted = FALSE;
2144 }
2145 }
2146
2147 /* update the sorted flags */
2148 if( col->lppos >= 0 && linkpos >= 0 )
2149 {
2150 assert(row->nlpcols >= 1);
2151 assert(row->cols[row->nlpcols-1] == col);
2152 if( row->nlpcols > 1 )
2153 {
2154 assert(row->cols_index[row->nlpcols-2] == row->cols[row->nlpcols-2]->index);
2155 row->lpcolssorted = row->lpcolssorted && (row->cols_index[row->nlpcols-2] < col->index);
2156 }
2157 }
2158 else
2159 {
2160 assert(row->len - row->nlpcols >= 1);
2161 assert(row->cols[row->len-1] == col);
2162 if( row->len - row->nlpcols > 1 )
2163 {
2164 assert(row->cols_index[row->len-2] == row->cols[row->len-2]->index);
2165 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[row->len-2] < col->index);
2166 }
2167 }
2168
2169 /* update row norm */
2170 rowAddNorms(row, set, col, val, TRUE);
2171
2172 coefChanged(row, col, lp);
2173
2174 SCIPsetDebugMsg(set, "added coefficient %g * <%s> at position %d (%d/%d) to row <%s> (nunlinked=%d)\n",
2175 val, SCIPvarGetName(col->var), pos, row->nlpcols, row->len, row->name, row->nunlinked);
2176
2177 /* issue row coefficient changed event */
2178 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, 0.0, val) );
2179
2180 return SCIP_OKAY;
2181}
2182
2183/** deletes coefficient at given position from row */
2184static
2186 SCIP_ROW* row, /**< row to be changed */
2187 BMS_BLKMEM* blkmem, /**< block memory */
2188 SCIP_SET* set, /**< global SCIP settings */
2189 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2190 SCIP_LP* lp, /**< current LP data */
2191 int pos /**< position in row vector to delete */
2192 )
2193{
2194 SCIP_COL* col;
2195 SCIP_Real val;
2196
2197 assert(row != NULL);
2198 assert(set != NULL);
2199 assert(0 <= pos && pos < row->len);
2200 assert(row->cols[pos] != NULL);
2201 assert((pos < row->nlpcols) == (row->linkpos[pos] >= 0 && row->cols[pos]->lppos >= 0));
2202
2203 col = row->cols[pos];
2204 val = row->vals[pos];
2205 assert((pos < row->nlpcols) == (col->lppos >= 0 && row->linkpos[pos] >= 0));
2206
2207 /*SCIPsetDebugMsg(set, "deleting coefficient %g * <%s> at position %d from row <%s>\n",
2208 val, SCIPvarGetName(col->var), pos, row->name);*/
2209
2210 if( row->nlocks > 0 )
2211 {
2212 SCIPerrorMessage("cannot delete a coefficient from the locked unmodifiable row <%s>\n", row->name);
2213 return SCIP_INVALIDDATA;
2214 }
2215
2216 if( row->linkpos[pos] == -1 )
2217 row->nunlinked--;
2218
2219 /* if column is a linked LP column, move last linked LP coefficient to position of empty slot (deleted coefficient) */
2220 if( pos < row->nlpcols )
2221 {
2222 rowMoveCoef(row, row->nlpcols-1, pos);
2223 assert(!row->lpcolssorted);
2224 row->nlpcols--;
2225 pos = row->nlpcols;
2226 }
2227
2228 /* move last coefficient to position of empty slot */
2229 rowMoveCoef(row, row->len-1, pos);
2230 row->len--;
2231
2232 /* update norms */
2233 rowDelNorms(row, set, col, val, FALSE, TRUE, TRUE);
2234
2235 coefChanged(row, col, lp);
2236
2237 /* issue row coefficient changed event */
2238 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, val, 0.0) );
2239
2240 return SCIP_OKAY;
2241}
2242
2243/** changes a coefficient at given position of an LP row */
2244static
2246 SCIP_ROW* row, /**< LP row */
2247 BMS_BLKMEM* blkmem, /**< block memory */
2248 SCIP_SET* set, /**< global SCIP settings */
2249 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2250 SCIP_LP* lp, /**< current LP data */
2251 int pos, /**< position in row vector to change */
2252 SCIP_Real val /**< value of coefficient */
2253 )
2254{
2255 SCIP_COL* col;
2256
2257 assert(row != NULL);
2258 assert(0 <= pos && pos < row->len);
2259
2260 /*SCIPsetDebugMsg(set, "changing coefficient %g * <%s> at position %d of row <%s> to %g\n",
2261 row->vals[pos], SCIPvarGetName(row->cols[pos]->var), pos, row->name, val);*/
2262
2263 if( row->nlocks > 0 )
2264 {
2265 SCIPerrorMessage("cannot change a coefficient of the locked unmodifiable row <%s>\n", row->name);
2266 return SCIP_INVALIDDATA;
2267 }
2268
2269 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
2270 val = SCIPsetIsIntegral(set, val) ? SCIPsetRound(set, val) : val;
2271 col = row->cols[pos];
2272 assert(row->cols[pos] != NULL);
2273
2274 if( SCIPsetIsZero(set, val) )
2275 {
2276 /* delete existing coefficient */
2277 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
2278 }
2279 else if( !SCIPsetIsEQ(set, row->vals[pos], val) )
2280 {
2281 SCIP_Real oldval;
2282
2283 oldval = row->vals[pos];
2284
2285 /* change existing coefficient */
2286 rowDelNorms(row, set, col, row->vals[pos], FALSE, FALSE, TRUE);
2287 row->vals[pos] = val;
2288 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
2289 rowAddNorms(row, set, col, row->vals[pos], TRUE);
2290 coefChanged(row, col, lp);
2291
2292 /* issue row coefficient changed event */
2293 SCIP_CALL( rowEventCoefChanged(row, blkmem, set, eventqueue, col, oldval, val) );
2294 }
2295
2296 return SCIP_OKAY;
2297}
2298
2299/** notifies LP row, that its sides were changed */
2300static
2302 SCIP_ROW* row, /**< LP row */
2303 SCIP_SET* set, /**< global SCIP settings */
2304 SCIP_LP* lp, /**< current LP data */
2305 SCIP_SIDETYPE sidetype /**< type of side: left or right hand side */
2306 )
2307{
2308 assert(row != NULL);
2309 assert(lp != NULL);
2310
2311 if( row->lpipos >= 0 )
2312 {
2313 /* insert row in the chgrows list (if not already there) */
2314 if( !row->lhschanged && !row->rhschanged )
2315 {
2316 SCIP_CALL( ensureChgrowsSize(lp, set, lp->nchgrows+1) );
2317 lp->chgrows[lp->nchgrows] = row;
2318 lp->nchgrows++;
2319 }
2320
2321 /* mark side change in the row */
2322 switch( sidetype )
2323 {
2324 case SCIP_SIDETYPE_LEFT:
2325 row->lhschanged = TRUE;
2326 break;
2328 row->rhschanged = TRUE;
2329 break;
2330 default:
2331 SCIPerrorMessage("unknown row side type\n");
2332 SCIPABORT();
2333 return SCIP_INVALIDDATA; /*lint !e527*/
2334 }
2335
2336 /* mark the current LP unflushed */
2337 lp->flushed = FALSE;
2338
2339 assert(lp->nchgrows > 0);
2340 }
2341
2342 return SCIP_OKAY;
2343}
2344
2345
2346
2347
2348/*
2349 * double linked coefficient matrix methods
2350 */
2351
2352/** insert column coefficients in corresponding rows */
2354 SCIP_COL* col, /**< column data */
2355 BMS_BLKMEM* blkmem, /**< block memory */
2356 SCIP_SET* set, /**< global SCIP settings */
2357 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2358 SCIP_LP* lp /**< current LP data */
2359 )
2360{
2361 int i;
2362
2363 assert(col != NULL);
2364 assert(col->var != NULL);
2365 assert(blkmem != NULL);
2366 assert(set != NULL);
2367 assert(lp != NULL);
2368
2369 if( col->nunlinked > 0 )
2370 {
2371 SCIPsetDebugMsg(set, "linking column <%s>\n", SCIPvarGetName(col->var));
2372
2373 /* unlinked rows can only be in the non-LP/unlinked rows part of the rows array */
2374 for( i = col->nlprows; i < col->len; ++i )
2375 {
2376 assert(!SCIPsetIsZero(set, col->vals[i]));
2377 if( col->linkpos[i] == -1 )
2378 {
2379 /* this call might swap the current row with the first non-LP/not linked row, but this is of no harm */
2380 SCIP_CALL( rowAddCoef(col->rows[i], blkmem, set, eventqueue, lp, col, col->vals[i], i) );
2381 }
2382 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2383 assert(col->rows[i]->linkpos[col->linkpos[i]] == i);
2384 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->cols[col->linkpos[col->nlprows-1]] == col);
2385 assert(col->nlprows == 0 || col->rows[col->nlprows-1]->linkpos[col->linkpos[col->nlprows-1]] == col->nlprows-1);
2386 }
2387 }
2388 assert(col->nunlinked == 0);
2389
2390 checkLinks(lp);
2391
2392 return SCIP_OKAY;
2393}
2394
2395/** removes column coefficients from corresponding rows */
2397 SCIP_COL* col, /**< column data */
2398 BMS_BLKMEM* blkmem, /**< block memory */
2399 SCIP_SET* set, /**< global SCIP settings */
2400 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2401 SCIP_LP* lp /**< current LP data */
2402 )
2403{
2404 int i;
2405
2406 assert(col != NULL);
2407 assert(col->var != NULL);
2408 assert(blkmem != NULL);
2409 assert(set != NULL);
2410 assert(lp != NULL);
2411
2412 if( col->nunlinked < col->len )
2413 {
2414 SCIPsetDebugMsg(set, "unlinking column <%s>\n", SCIPvarGetName(col->var));
2415 for( i = 0; i < col->len; ++i )
2416 {
2417 if( col->linkpos[i] >= 0 )
2418 {
2419 assert(col->rows[i]->cols[col->linkpos[i]] == col);
2420 SCIP_CALL( rowDelCoefPos(col->rows[i], blkmem, set, eventqueue, lp, col->linkpos[i]) );
2421 col->linkpos[i] = -1;
2422 col->nunlinked++;
2423 }
2424 }
2425 }
2426 assert(col->nunlinked == col->len);
2427
2428 checkLinks(lp);
2429
2430 return SCIP_OKAY;
2431}
2432
2433/** insert row coefficients in corresponding columns */
2435 SCIP_ROW* row, /**< row data */
2436 BMS_BLKMEM* blkmem, /**< block memory */
2437 SCIP_SET* set, /**< global SCIP settings */
2438 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2439 SCIP_LP* lp /**< current LP data */
2440 )
2441{
2442 int i;
2443
2444 assert(row != NULL);
2445 assert(blkmem != NULL);
2446 assert(set != NULL);
2447 assert(lp != NULL);
2448
2449 if( row->nunlinked > 0 )
2450 {
2451 SCIPsetDebugMsg(set, "linking row <%s>\n", row->name);
2452
2453 /* unlinked columns can only be in the non-LP/unlinked columns part of the cols array */
2454 for( i = row->nlpcols; i < row->len; ++i )
2455 {
2456 assert(!SCIPsetIsZero(set, row->vals[i]));
2457 if( row->linkpos[i] == -1 )
2458 {
2459 /* this call might swap the current column with the first non-LP/not linked column, but this is of no harm */
2460 SCIP_CALL( colAddCoef(row->cols[i], blkmem, set, eventqueue, lp, row, row->vals[i], i) );
2461 }
2462 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2463 assert(row->cols[i]->linkpos[row->linkpos[i]] == i);
2464 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->rows[row->linkpos[row->nlpcols-1]] == row);
2465 assert(row->nlpcols == 0 || row->cols[row->nlpcols-1]->linkpos[row->linkpos[row->nlpcols-1]] == row->nlpcols-1);
2466 }
2467 }
2468 assert(row->nunlinked == 0);
2469
2470 checkLinks(lp);
2471
2472 return SCIP_OKAY;
2473}
2474
2475/** removes row coefficients from corresponding columns */
2477 SCIP_ROW* row, /**< row data */
2478 SCIP_SET* set, /**< global SCIP settings */
2479 SCIP_LP* lp /**< current LP data */
2480 )
2481{
2482 int i;
2483
2484 assert(row != NULL);
2485 assert(set != NULL);
2486 assert(lp != NULL);
2487
2488 if( row->nunlinked < row->len )
2489 {
2490 SCIPsetDebugMsg(set, "unlinking row <%s>\n", row->name);
2491 for( i = 0; i < row->len; ++i )
2492 {
2493 if( row->linkpos[i] >= 0 )
2494 {
2495 assert(row->cols[i]->rows[row->linkpos[i]] == row);
2496 SCIP_CALL( colDelCoefPos(row->cols[i], set, lp, row->linkpos[i]) );
2497 row->nunlinked++;
2498 }
2499 }
2500 }
2501 assert(row->nunlinked == row->len);
2502
2503 return SCIP_OKAY;
2504}
2505
2506
2507
2508
2509/*
2510 * local LP parameter methods
2511 */
2512
2513/** sets parameter of type int in LP solver, ignoring unknown parameters */
2514static
2516 SCIP_LP* lp, /**< current LP data */
2517 SCIP_LPPARAM lpparam, /**< LP parameter */
2518 int value, /**< value to set parameter to */
2519 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2520 )
2521{
2522 SCIP_RETCODE retcode;
2523
2524 assert(lp != NULL);
2525 assert(success != NULL);
2526
2527 retcode = SCIPlpiSetIntpar(lp->lpi, lpparam, value);
2528
2529 /* check, if parameter is unknown */
2530 if( retcode == SCIP_PARAMETERUNKNOWN )
2531 {
2532 *success = FALSE;
2533 return SCIP_OKAY;
2534 }
2535 *success = TRUE;
2536
2537 return retcode;
2538}
2539
2540/** sets parameter of type SCIP_Bool in LP solver, ignoring unknown parameters */
2541static
2543 SCIP_LP* lp, /**< current LP data */
2544 SCIP_LPPARAM lpparam, /**< LP parameter */
2545 SCIP_Bool value, /**< value to set parameter to */
2546 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2547 )
2548{
2549 return lpSetIntpar(lp, lpparam, (int)value, success);
2550}
2551
2552/** sets parameter of type SCIP_Real in LP solver, ignoring unknown parameters */
2553static
2555 SCIP_LP* lp, /**< current LP data */
2556 SCIP_LPPARAM lpparam, /**< LP parameter */
2557 SCIP_Real value, /**< value to set parameter to */
2558 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2559 )
2560{
2561 SCIP_RETCODE retcode;
2562
2563 assert(lp != NULL);
2564 assert(success != NULL);
2565
2566 retcode = SCIPlpiSetRealpar(lp->lpi, lpparam, value);
2567
2568 /* check, if parameter is unknown */
2569 if( retcode == SCIP_PARAMETERUNKNOWN )
2570 {
2571 *success = FALSE;
2572 return SCIP_OKAY;
2573 }
2574 *success = TRUE;
2575
2576 return retcode;
2577}
2578
2579#ifndef NDEBUG
2580/** checks, that parameter of type int in LP solver has the given value, ignoring unknown parameters */
2581static
2583 SCIP_LP* lp, /**< current LP data */
2584 SCIP_LPPARAM lpparam, /**< LP parameter */
2585 int value /**< value parameter should have */
2586 )
2587{
2588 SCIP_RETCODE retcode;
2589 int lpivalue;
2590
2591 assert(lp != NULL);
2592
2593 retcode = SCIPlpiGetIntpar(lp->lpi, lpparam, &lpivalue);
2594
2595 /* ignore unknown parameter error */
2596 if( retcode == SCIP_PARAMETERUNKNOWN )
2597 return SCIP_OKAY;
2598
2599 /* check value */
2600 assert(lpivalue == value);
2601
2602 return retcode;
2603}
2604
2605/** checks, that parameter of type SCIP_Bool in LP solver has the given value, ignoring unknown parameters */
2606static
2608 SCIP_LP* lp, /**< current LP data */
2609 SCIP_LPPARAM lpparam, /**< LP parameter */
2610 SCIP_Bool value /**< value parameter should have */
2611 )
2612{
2613 return lpCheckIntpar(lp, lpparam, (int)value);
2614}
2615
2616/** checks, that parameter of type SCIP_Real in LP solver has the given value, ignoring unknown parameters */
2617static
2619 SCIP_LP* lp, /**< current LP data */
2620 SCIP_LPPARAM lpparam, /**< LP parameter */
2621 SCIP_Real value /**< value parameter should have */
2622 )
2623{
2624 SCIP_RETCODE retcode;
2625 SCIP_Real lpivalue;
2626
2627 assert(lp != NULL);
2628
2629 retcode = SCIPlpiGetRealpar(lp->lpi, lpparam, &lpivalue);
2630
2631 /* ignore unknown parameter error */
2632 if( retcode == SCIP_PARAMETERUNKNOWN )
2633 return SCIP_OKAY;
2634
2635 /* check value */
2636 assert(lpivalue == value); /*lint !e777*/
2637
2638 return retcode;
2639}
2640#else
2641#define lpCheckIntpar(lp, lpparam, value) SCIP_OKAY
2642#define lpCheckBoolpar(lp, lpparam, value) SCIP_OKAY
2643#define lpCheckRealpar(lp, lpparam, value) SCIP_OKAY
2644#endif
2645
2646/** should the objective limit of the LP solver be disabled */
2647#define lpCutoffDisabled(set, prob, lp) (set->lp_disablecutoff == 1 || (set->lp_disablecutoff == 2 && !SCIPprobAllColsInLP(prob, set, lp)) || set->misc_exactsolve)
2648
2649/** sets the objective limit of the LP solver
2650 *
2651 * Note that we are always minimizing.
2652 */
2653static
2655 SCIP_LP* lp, /**< current LP data */
2656 SCIP_SET* set, /**< global SCIP settings */
2657 SCIP_PROB* prob, /**< problem data */
2658 SCIP_Real objlim, /**< new objective limit */
2659 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2660 )
2661{
2662 assert(lp != NULL);
2663 assert(set != NULL);
2664 assert(success != NULL);
2665
2666 *success = FALSE;
2667
2668 /* if the objective limit is disabled or SCIP infinity, make sure that the LP objective limit is deactivated by
2669 * setting it to the LP-solver infinity
2670 */
2671 if( lpCutoffDisabled(set, prob, lp) || SCIPsetIsInfinity(set, objlim) )
2672 objlim = SCIPlpiInfinity(lp->lpi);
2673
2675
2676 if( objlim != lp->lpiobjlim ) /*lint !e777*/
2677 {
2678 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, objlim, success) );
2679 if( *success )
2680 {
2681 SCIP_Real actualobjlim;
2682
2683 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2684 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_OBJLIM, &actualobjlim) );
2685 if( actualobjlim != lp->lpiobjlim ) /*lint !e777*/
2686 {
2687 /* mark the current solution invalid */
2688 lp->solved = FALSE;
2689 lp->primalfeasible = FALSE;
2690 lp->primalchecked = FALSE;
2691 lp->lpobjval = SCIP_INVALID;
2693 }
2694 lp->lpiobjlim = actualobjlim;
2695 }
2696 }
2697
2698 return SCIP_OKAY;
2699}
2700
2701/** sets the feasibility tolerance of the LP solver */
2702static
2704 SCIP_LP* lp, /**< current LP data */
2705 SCIP_Real feastol, /**< new feasibility tolerance */
2706 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2707 )
2708{
2709 assert(lp != NULL);
2710 assert(feastol >= 0.0);
2711 assert(success != NULL);
2712
2714
2715 if( feastol != lp->lpifeastol ) /*lint !e777*/
2716 {
2717 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_FEASTOL, feastol, success) );
2718 if( *success )
2719 {
2720 SCIP_Real actualfeastol;
2721
2722 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2723 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_FEASTOL, &actualfeastol) );
2724 if( lp->nrows > 0 && actualfeastol < lp->lpifeastol )
2725 {
2726 /* mark the current solution invalid */
2727 lp->solved = FALSE;
2728 lp->primalfeasible = FALSE;
2729 lp->primalchecked = FALSE;
2730 lp->lpobjval = SCIP_INVALID;
2732 }
2733 else
2734 *success = FALSE;
2735 lp->lpifeastol = actualfeastol;
2736 }
2737 }
2738 else
2739 *success = FALSE;
2740
2741 return SCIP_OKAY;
2742}
2743
2744/** sets the reduced costs feasibility tolerance of the LP solver */
2745static
2747 SCIP_LP* lp, /**< current LP data */
2748 SCIP_Real dualfeastol, /**< new reduced costs feasibility tolerance */
2749 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2750 )
2751{
2752 assert(lp != NULL);
2753 assert(dualfeastol >= 0.0);
2754 assert(success != NULL);
2755
2757
2758 if( dualfeastol != lp->lpidualfeastol ) /*lint !e777*/
2759 {
2760 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_DUALFEASTOL, dualfeastol, success) );
2761 if( *success )
2762 {
2763 SCIP_Real actualdualfeastol;
2764
2765 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2766 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_DUALFEASTOL, &actualdualfeastol) );
2767 if( lp->nrows > 0 && actualdualfeastol < lp->lpidualfeastol )
2768 {
2769 /* mark the current solution invalid */
2770 lp->solved = FALSE;
2771 lp->dualfeasible = FALSE;
2772 lp->dualchecked = FALSE;
2773 lp->lpobjval = SCIP_INVALID;
2775 }
2776 else
2777 *success = FALSE;
2778 lp->lpidualfeastol = actualdualfeastol;
2779 }
2780 }
2781 else
2782 *success = FALSE;
2783
2784 return SCIP_OKAY;
2785}
2786
2787/** sets the convergence tolerance used in barrier algorithm of the LP solver */
2788static
2790 SCIP_LP* lp, /**< current LP data */
2791 SCIP_Real barrierconvtol, /**< new convergence tolerance used in barrier algorithm */
2792 SCIP_Bool* success /**< pointer to store whether the parameter was actually changed */
2793 )
2794{
2795 assert(lp != NULL);
2796 assert(barrierconvtol >= 0.0);
2797 assert(success != NULL);
2798
2800
2801 if( barrierconvtol != lp->lpibarrierconvtol ) /*lint !e777*/
2802 {
2803 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_BARRIERCONVTOL, barrierconvtol, success) );
2804 if( *success )
2805 {
2806 SCIP_Real actualbarrierconvtol;
2807
2808 /* check whether the parameter was actually changed or already was at the boundary of the LP solver's parameter range */
2809 SCIP_CALL( SCIPlpiGetRealpar(lp->lpi, SCIP_LPPAR_BARRIERCONVTOL, &actualbarrierconvtol) );
2810 if( lp->nrows > 0 && actualbarrierconvtol < lp->lpibarrierconvtol
2812 {
2813 /* mark the current solution invalid */
2814 lp->solved = FALSE;
2815 lp->dualfeasible = FALSE;
2816 lp->dualchecked = FALSE;
2817 lp->lpobjval = SCIP_INVALID;
2819 }
2820 else
2821 *success = FALSE;
2822 lp->lpibarrierconvtol = actualbarrierconvtol;
2823 }
2824 }
2825 else
2826 *success = FALSE;
2827
2828 return SCIP_OKAY;
2829}
2830
2831/** sets the FROMSCRATCH setting of the LP solver */
2832static
2834 SCIP_LP* lp, /**< current LP data */
2835 SCIP_Bool fromscratch, /**< new FROMSCRATCH setting */
2836 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2837 )
2838{
2839 assert(lp != NULL);
2840 assert(success != NULL);
2841
2843
2844 if( fromscratch != lp->lpifromscratch )
2845 {
2846 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_FROMSCRATCH, fromscratch, success) );
2847 if( *success )
2848 lp->lpifromscratch = fromscratch;
2849 }
2850 else
2851 *success = FALSE;
2852
2853 return SCIP_OKAY;
2854}
2855
2856/** sets the FASTMIP setting of the LP solver */
2857static
2859 SCIP_LP* lp, /**< current LP data */
2860 int fastmip, /**< new FASTMIP setting */
2861 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2862 )
2863{
2864 assert(lp != NULL);
2865 assert(success != NULL);
2866 assert(0 <= fastmip && fastmip <= 1);
2867
2869
2870 if( fastmip != lp->lpifastmip )
2871 {
2872 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_FASTMIP, fastmip, success) );
2873 if( *success )
2874 {
2875 lp->lpifastmip = fastmip;
2876 lp->solved = FALSE;
2877 /* We might only set lp->solved to false if fastmip is turned off, since the latter should be the more
2878 * demanding setting; however, in the current code, this should have not effect. */
2879 }
2880 }
2881 else
2882 *success = FALSE;
2883
2884 return SCIP_OKAY;
2885}
2886
2887/** sets the SCALING setting of the LP solver */
2888static
2890 SCIP_LP* lp, /**< current LP data */
2891 int scaling, /**< new SCALING setting */
2892 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2893 )
2894{
2895 assert(lp != NULL);
2896 assert(success != NULL);
2897
2899
2900 if( scaling != lp->lpiscaling )
2901 {
2902 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_SCALING, scaling, success) );
2903 if( *success )
2904 lp->lpiscaling = scaling;
2905 }
2906 else
2907 *success = FALSE;
2908
2909 return SCIP_OKAY;
2910}
2911
2912/** sets the number of THREADS of the LP solver */
2913static
2915 SCIP_LP* lp, /**< current LP data */
2916 int threads, /**< new number of threads used to solve the LP */
2917 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2918 )
2919{
2920 assert(lp != NULL);
2921 assert(success != NULL);
2922
2924
2925 if( threads != lp->lpithreads )
2926 {
2927 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_THREADS, threads, success) );
2928 if( *success )
2929 lp->lpithreads = threads;
2930 }
2931 else
2932 *success = FALSE;
2933
2934 return SCIP_OKAY;
2935}
2936
2937/** sets the PRESOLVING setting of the LP solver */
2938static
2940 SCIP_LP* lp, /**< current LP data */
2941 SCIP_Bool presolving, /**< new PRESOLVING setting */
2942 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2943 )
2944{
2945 assert(lp != NULL);
2946 assert(success != NULL);
2947
2949
2950 if( presolving != lp->lpipresolving )
2951 {
2952 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_PRESOLVING, presolving, success) );
2953 if( *success )
2954 lp->lpipresolving = presolving;
2955 }
2956 else
2957 *success = FALSE;
2958
2959 return SCIP_OKAY;
2960}
2961
2962/** sets the ROWREPSWITCH setting of the LP solver */
2963static
2965 SCIP_LP* lp, /**< current LP data */
2966 SCIP_Real rowrepswitch, /**< new ROWREPSWITCH value */
2967 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
2968 )
2969{
2970 assert(lp != NULL);
2971 assert(success != NULL);
2972
2974
2975 if( rowrepswitch != lp->lpirowrepswitch ) /*lint !e777*/
2976 {
2977 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_ROWREPSWITCH, rowrepswitch, success) );
2978 if( *success )
2979 lp->lpirowrepswitch = rowrepswitch;
2980 }
2981 else
2982 *success = FALSE;
2983
2984 return SCIP_OKAY;
2985}
2986
2987/** sets the iteration limit of the LP solver */
2988static
2990 SCIP_LP* lp, /**< current LP data */
2991 int itlim /**< maximal number of LP iterations to perform, or -1 for no limit */
2992 )
2993{
2994 SCIP_Bool success;
2995
2996 assert(lp != NULL);
2997 assert(itlim >= -1);
2998
2999 if( itlim == -1 )
3000 itlim = INT_MAX;
3001
3003
3004 if( itlim != lp->lpiitlim )
3005 {
3006 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_LPITLIM, itlim, &success) );
3007 if( success )
3008 {
3009 if( itlim > lp->lpiitlim )
3010 {
3011 /* mark the current solution invalid */
3012 lp->solved = FALSE;
3013 lp->lpobjval = SCIP_INVALID;
3015 }
3016 lp->lpiitlim = itlim;
3017 }
3018 }
3019
3020 return SCIP_OKAY;
3021}
3022
3023/** sets the pricing strategy of the LP solver */
3024static
3026 SCIP_LP* lp, /**< current LP data */
3027 SCIP_PRICING pricing /**< pricing strategy */
3028 )
3029{
3030 SCIP_Bool success;
3031
3032 assert(lp != NULL);
3033
3035
3036 if( pricing != lp->lpipricing )
3037 {
3038 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_PRICING, (int)pricing, &success) );
3039 if( success )
3040 lp->lpipricing = pricing;
3041 }
3042
3043 return SCIP_OKAY;
3044}
3045
3046/** sets the pricing strategy of the LP solver (given the character representation of the strategy) */
3047static
3049 SCIP_LP* lp, /**< current LP data */
3050 char pricingchar /**< character representing the pricing strategy */
3051 )
3052{
3053 SCIP_PRICING pricing;
3054
3055 switch( pricingchar )
3056 {
3057 case 'l':
3058 pricing = SCIP_PRICING_LPIDEFAULT;
3059 break;
3060 case 'a':
3061 pricing = SCIP_PRICING_AUTO;
3062 break;
3063 case 'f':
3064 pricing = SCIP_PRICING_FULL;
3065 break;
3066 case 'p':
3067 pricing = SCIP_PRICING_PARTIAL;
3068 break;
3069 case 's':
3070 pricing = SCIP_PRICING_STEEP;
3071 break;
3072 case 'q':
3073 pricing = SCIP_PRICING_STEEPQSTART;
3074 break;
3075 case 'd':
3076 pricing = SCIP_PRICING_DEVEX;
3077 break;
3078 default:
3079 SCIPerrorMessage("invalid LP pricing parameter <%c>\n", pricingchar);
3080 return SCIP_INVALIDDATA;
3081 }
3082
3083 SCIP_CALL( lpSetPricing(lp, pricing) );
3084
3085 return SCIP_OKAY;
3086}
3087
3088/** sets the verbosity of the LP solver */
3089static
3091 SCIP_LP* lp, /**< current LP data */
3092 SCIP_Bool lpinfo /**< should the LP solver display status messages? */
3093 )
3094{
3095 SCIP_Bool success;
3096
3097 assert(lp != NULL);
3098
3100
3101 if( lpinfo != lp->lpilpinfo )
3102 {
3103 SCIP_CALL( lpSetBoolpar(lp, SCIP_LPPAR_LPINFO, lpinfo, &success) );
3104 if( success )
3105 lp->lpilpinfo = lpinfo;
3106 }
3107
3108 return SCIP_OKAY;
3109}
3110
3111/** sets the CONDITIONLIMIT setting of the LP solver */
3112static
3114 SCIP_LP* lp, /**< current LP data */
3115 SCIP_Real condlimit, /**< new CONDITIONLIMIT value */
3116 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3117 )
3118{
3119 assert(lp != NULL);
3120 assert(success != NULL);
3121
3123
3124 if( condlimit != lp->lpiconditionlimit ) /*lint !e777*/
3125 {
3126 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_CONDITIONLIMIT, condlimit, success) );
3127 if( *success )
3128 lp->lpiconditionlimit = condlimit;
3129 }
3130 else
3131 *success = FALSE;
3132
3133 return SCIP_OKAY;
3134}
3135
3136/** sets the MARKOWITZ setting of the LP solver */
3137static
3139 SCIP_LP* lp, /**< current LP data */
3140 SCIP_Real threshhold, /**< new MARKOWITZ value */
3141 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3142 )
3143{
3144 assert(lp != NULL);
3145 assert(success != NULL);
3146
3148
3149 if( threshhold != lp->lpimarkowitz ) /*lint !e777*/
3150 {
3151 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_MARKOWITZ, threshhold, success) );
3152 if( *success )
3153 lp->lpimarkowitz = threshhold;
3154 }
3155 else
3156 *success = FALSE;
3157
3158 return SCIP_OKAY;
3159}
3160
3161/** sets the type of timer of the LP solver */
3162static
3164 SCIP_LP* lp, /**< current LP data */
3165 SCIP_CLOCKTYPE timing, /**< new timing value */
3166 SCIP_Bool enabled, /**< is timing enabled? */
3167 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3168 )
3169{
3170 int lptiming;
3171
3172 assert(lp != NULL);
3173 assert(success != NULL);
3174 assert((int) SCIP_CLOCKTYPE_CPU == 1 && (int) SCIP_CLOCKTYPE_WALL == 2); /*lint !e506*//*lint !e1564*/
3175
3177
3178 if( !enabled )
3179 lptiming = 0;
3180 else
3181 lptiming = (int) timing;
3182
3183 if( lptiming != lp->lpitiming ) /*lint !e777*/
3184 {
3185 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_TIMING, lptiming, success) );
3186 if( *success )
3187 lp->lpitiming = lptiming;
3188 }
3189 else
3190 *success = FALSE;
3191
3192 return SCIP_OKAY;
3193}
3194
3195/** sets the initial random seed of the LP solver */
3196static
3198 SCIP_LP* lp, /**< current LP data */
3199 int randomseed, /**< new initial random seed */
3200 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3201 )
3202{
3203 assert(lp != NULL);
3204 assert(success != NULL);
3205
3206 /* we don't check this parameter because SoPlex will always return its current random seed, not the initial one */
3207
3208 if( randomseed == 0 )
3209 {
3210 lp->lpirandomseed = randomseed;
3211 *success = TRUE;
3212 }
3213 else if( randomseed != lp->lpirandomseed ) /*lint !e777*/
3214 {
3215 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_RANDOMSEED, randomseed, success) );
3216 if( *success )
3217 lp->lpirandomseed = randomseed;
3218 }
3219 else
3220 *success = FALSE;
3221
3222 return SCIP_OKAY;
3223}
3224
3225/** sets the LP solution polishing method */
3226static
3228 SCIP_LP* lp, /**< current LP data */
3229 SCIP_Bool polishing, /**< LP solution polishing activated (0: disabled, 1: enabled) */
3230 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3231 )
3232{
3233 assert(lp != NULL);
3234 assert(success != NULL);
3235
3236 if( polishing != lp->lpisolutionpolishing )
3237 {
3238 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_POLISHING, (polishing ? 1 : 0), success) );
3239 if( *success )
3240 lp->lpisolutionpolishing = polishing;
3241 }
3242 else
3243 *success = FALSE;
3244
3245 return SCIP_OKAY;
3246}
3247
3248/** sets the LP refactorization interval */
3249static
3251 SCIP_LP* lp, /**< current LP data */
3252 int refactor, /**< LP refactorization interval (0: automatic) */
3253 SCIP_Bool* success /**< pointer to store whether the parameter was successfully changed */
3254 )
3255{
3256 assert(lp != NULL);
3257 assert(success != NULL);
3258
3259 if( refactor != lp->lpirefactorinterval )
3260 {
3261 SCIP_CALL( lpSetIntpar(lp, SCIP_LPPAR_REFACTOR, refactor, success) );
3262 if( *success )
3263 lp->lpirefactorinterval = refactor;
3264 }
3265 else
3266 *success = FALSE;
3267
3268 return SCIP_OKAY;
3269}
3270
3271
3272/*
3273 * Column methods
3274 */
3275
3276/** creates an LP column */
3278 SCIP_COL** col, /**< pointer to column data */
3279 BMS_BLKMEM* blkmem, /**< block memory */
3280 SCIP_SET* set, /**< global SCIP settings */
3281 SCIP_STAT* stat, /**< problem statistics */
3282 SCIP_VAR* var, /**< variable, this column represents */
3283 int len, /**< number of nonzeros in the column */
3284 SCIP_ROW** rows, /**< array with rows of column entries */
3285 SCIP_Real* vals, /**< array with coefficients of column entries */
3286 SCIP_Bool removable /**< should the column be removed from the LP due to aging or cleanup? */
3287 )
3288{
3289 int i;
3290
3291 assert(col != NULL);
3292 assert(blkmem != NULL);
3293 assert(set != NULL);
3294 assert(stat != NULL);
3295 assert(var != NULL);
3296 assert(len >= 0);
3297 assert(len == 0 || (rows != NULL && vals != NULL));
3298
3299 SCIP_ALLOC( BMSallocBlockMemory(blkmem, col) );
3300
3301 if( len > 0 )
3302 {
3303 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->rows, rows, len) );
3304 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*col)->vals, vals, len) );
3305 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*col)->linkpos, len) );
3306
3307 for( i = 0; i < len; ++i )
3308 {
3309 assert(rows[i] != NULL);
3310 assert(!SCIPsetIsZero(set, vals[i]));
3311 (*col)->linkpos[i] = -1;
3312 }
3313 }
3314 else
3315 {
3316 (*col)->rows = NULL;
3317 (*col)->vals = NULL;
3318 (*col)->linkpos = NULL;
3319 }
3320
3321 (*col)->var = var;
3322 (*col)->obj = SCIPvarGetObj(var);
3323 (*col)->unchangedobj = SCIPvarGetUnchangedObj(var);
3324 (*col)->lb = SCIPvarGetLbLocal(var);
3325 (*col)->ub = SCIPvarGetUbLocal(var);
3326 (*col)->flushedobj = 0.0;
3327 (*col)->flushedlb = 0.0;
3328 (*col)->flushedub = 0.0;
3329 (*col)->index = stat->ncolidx;
3330 SCIPstatIncrement(stat, set, ncolidx);
3331 (*col)->size = len;
3332 (*col)->len = len;
3333 (*col)->nlprows = 0;
3334 (*col)->nunlinked = len;
3335 (*col)->lppos = -1;
3336 (*col)->lpipos = -1;
3337 (*col)->lpdepth = -1;
3338 (*col)->primsol = 0.0;
3339 (*col)->redcost = SCIP_INVALID;
3340 (*col)->farkascoef = SCIP_INVALID;
3341 (*col)->minprimsol = (*col)->ub;
3342 (*col)->maxprimsol = (*col)->lb;
3343 (*col)->sbdown = SCIP_INVALID;
3344 (*col)->sbup = SCIP_INVALID;
3345 (*col)->sbsolval = SCIP_INVALID;
3346 (*col)->sblpobjval = SCIP_INVALID;
3347 (*col)->sbnode = -1;
3348 (*col)->validredcostlp = -1;
3349 (*col)->validfarkaslp = -1;
3350 (*col)->validsblp = -1;
3351 (*col)->sbitlim = -1;
3352 (*col)->nsbcalls = 0;
3353 (*col)->age = 0;
3354 (*col)->obsoletenode = -1;
3355 (*col)->var_probindex = SCIPvarGetProbindex(var);
3356 (*col)->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
3357 (*col)->lprowssorted = TRUE;
3358 (*col)->nonlprowssorted = (len <= 1);
3359 (*col)->objchanged = FALSE;
3360 (*col)->lbchanged = FALSE;
3361 (*col)->ubchanged = FALSE;
3362 (*col)->coefchanged = FALSE;
3363 (*col)->integral = SCIPvarIsIntegral(var);
3364 (*col)->removable = removable;
3365 (*col)->sbdownvalid = FALSE;
3366 (*col)->sbupvalid = FALSE;
3367 (*col)->lazylb = SCIPvarGetLbLazy(var);
3368 (*col)->lazyub = SCIPvarGetUbLazy(var);
3369 (*col)->storedsolvals = NULL;
3370
3371 return SCIP_OKAY;
3372}
3373
3374/** frees an LP column */
3376 SCIP_COL** col, /**< pointer to LP column */
3377 BMS_BLKMEM* blkmem, /**< block memory */
3378 SCIP_SET* set, /**< global SCIP settings */
3379 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3380 SCIP_LP* lp /**< current LP data */
3381 )
3382{
3383 assert(blkmem != NULL);
3384 assert(col != NULL);
3385 assert(*col != NULL);
3386 assert((*col)->var != NULL);
3387 assert(SCIPvarGetStatus((*col)->var) == SCIP_VARSTATUS_COLUMN);
3388 assert(&(*col)->var->data.col == col); /* SCIPcolFree() has to be called from SCIPvarFree() */
3389 assert((*col)->lppos == -1);
3390 assert((*col)->lpipos == -1);
3391
3392 /* remove column indices from corresponding rows */
3393 SCIP_CALL( colUnlink(*col, blkmem, set, eventqueue, lp) );
3394
3395 BMSfreeBlockMemoryNull(blkmem, &(*col)->storedsolvals);
3396 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->rows, (*col)->size);
3397 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->vals, (*col)->size);
3398 BMSfreeBlockMemoryArrayNull(blkmem, &(*col)->linkpos, (*col)->size);
3399 BMSfreeBlockMemory(blkmem, col);
3400
3401 return SCIP_OKAY;
3402}
3403
3404/** output column to file stream */
3406 SCIP_COL* col, /**< LP column */
3407 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
3408 FILE* file /**< output file (or NULL for standard output) */
3409 )
3410{
3411 int r;
3412
3413 assert(col != NULL);
3414 assert(col->var != NULL);
3415
3416 /* print bounds */
3417 SCIPmessageFPrintInfo(messagehdlr, file, "(obj: %.15g) [%.15g,%.15g], ", col->obj, col->lb, col->ub);
3418
3419 /* print coefficients */
3420 if( col->len == 0 )
3421 SCIPmessageFPrintInfo(messagehdlr, file, "<empty>");
3422 for( r = 0; r < col->len; ++r )
3423 {
3424 assert(col->rows[r] != NULL);
3425 assert(col->rows[r]->name != NULL);
3426 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", col->vals[r], col->rows[r]->name);
3427 }
3428 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3429}
3430
3431/** sorts column entries such that LP rows precede non-LP rows and inside both parts lower row indices precede higher ones
3432 */
3434 SCIP_COL* col /**< column to be sorted */
3435 )
3436{
3437 /* sort LP rows */
3438 colSortLP(col);
3439
3440 /* sort non-LP rows */
3441 colSortNonLP(col);
3442}
3443
3444/** adds a previously non existing coefficient to an LP column */
3446 SCIP_COL* col, /**< LP column */
3447 BMS_BLKMEM* blkmem, /**< block memory */
3448 SCIP_SET* set, /**< global SCIP settings */
3449 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3450 SCIP_LP* lp, /**< current LP data */
3451 SCIP_ROW* row, /**< LP row */
3452 SCIP_Real val /**< value of coefficient */
3453 )
3454{
3455 assert(lp != NULL);
3456 assert(!lp->diving);
3457
3458 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3459
3460 checkLinks(lp);
3461
3462 return SCIP_OKAY;
3463}
3464
3465/** deletes existing coefficient from column */
3467 SCIP_COL* col, /**< column to be changed */
3468 BMS_BLKMEM* blkmem, /**< block memory */
3469 SCIP_SET* set, /**< global SCIP settings */
3470 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3471 SCIP_LP* lp, /**< current LP data */
3472 SCIP_ROW* row /**< coefficient to be deleted */
3473 )
3474{
3475 int pos;
3476
3477 assert(col != NULL);
3478 assert(col->var != NULL);
3479 assert(lp != NULL);
3480 assert(!lp->diving);
3481 assert(row != NULL);
3482
3483 /* search the position of the row in the column's row vector */
3484 pos = colSearchCoef(col, row);
3485 if( pos == -1 )
3486 {
3487 SCIPerrorMessage("coefficient for row <%s> doesn't exist in column <%s>\n", row->name, SCIPvarGetName(col->var));
3488 return SCIP_INVALIDDATA;
3489 }
3490 assert(0 <= pos && pos < col->len);
3491 assert(col->rows[pos] == row);
3492
3493 /* if row knows of the column, remove the column from the row's col vector */
3494 if( col->linkpos[pos] >= 0 )
3495 {
3496 assert(row->cols[col->linkpos[pos]] == col);
3497 assert(row->cols_index[col->linkpos[pos]] == col->index);
3498 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3499 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos]) );
3500 }
3501
3502 /* delete the row from the column's row vector */
3503 SCIP_CALL( colDelCoefPos(col, set, lp, pos) );
3504
3505 checkLinks(lp);
3506
3507 return SCIP_OKAY;
3508}
3509
3510/** changes or adds a coefficient to an LP column */
3512 SCIP_COL* col, /**< LP column */
3513 BMS_BLKMEM* blkmem, /**< block memory */
3514 SCIP_SET* set, /**< global SCIP settings */
3515 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3516 SCIP_LP* lp, /**< current LP data */
3517 SCIP_ROW* row, /**< LP row */
3518 SCIP_Real val /**< value of coefficient */
3519 )
3520{
3521 int pos;
3522
3523 assert(col != NULL);
3524 assert(lp != NULL);
3525 assert(!lp->diving);
3526 assert(row != NULL);
3527
3528 /* search the position of the row in the column's row vector */
3529 pos = colSearchCoef(col, row);
3530
3531 /* check, if row already exists in the column's row vector */
3532 if( pos == -1 )
3533 {
3534 /* add previously not existing coefficient */
3535 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, val, -1) );
3536 }
3537 else
3538 {
3539 /* modify already existing coefficient */
3540 assert(0 <= pos && pos < col->len);
3541 assert(col->rows[pos] == row);
3542
3543 /* if row knows of the column, change the corresponding coefficient in the row */
3544 if( col->linkpos[pos] >= 0 )
3545 {
3546 assert(row->cols[col->linkpos[pos]] == col);
3547 assert(row->cols_index[col->linkpos[pos]] == col->index);
3548 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3549 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], val) );
3550 }
3551
3552 /* change the coefficient in the column */
3553 SCIP_CALL( colChgCoefPos(col, set, lp, pos, val) );
3554 }
3555
3556 checkLinks(lp);
3557
3558 return SCIP_OKAY;
3559}
3560
3561/** increases value of an existing or non-existing coefficient in an LP column */
3563 SCIP_COL* col, /**< LP column */
3564 BMS_BLKMEM* blkmem, /**< block memory */
3565 SCIP_SET* set, /**< global SCIP settings */
3566 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3567 SCIP_LP* lp, /**< current LP data */
3568 SCIP_ROW* row, /**< LP row */
3569 SCIP_Real incval /**< value to add to the coefficient */
3570 )
3571{
3572 int pos;
3573
3574 assert(col != NULL);
3575 assert(lp != NULL);
3576 assert(!lp->diving);
3577 assert(row != NULL);
3578
3579 if( SCIPsetIsZero(set, incval) )
3580 return SCIP_OKAY;
3581
3582 /* search the position of the row in the column's row vector */
3583 pos = colSearchCoef(col, row);
3584
3585 /* check, if row already exists in the column's row vector */
3586 if( pos == -1 )
3587 {
3588 /* add previously not existing coefficient */
3589 SCIP_CALL( colAddCoef(col, blkmem, set, eventqueue, lp, row, incval, -1) );
3590 }
3591 else
3592 {
3593 /* modify already existing coefficient */
3594 assert(0 <= pos && pos < col->len);
3595 assert(col->rows[pos] == row);
3596
3597 /* if row knows of the column, change the corresponding coefficient in the row */
3598 if( col->linkpos[pos] >= 0 )
3599 {
3600 assert(row->cols[col->linkpos[pos]] == col);
3601 assert(row->cols_index[col->linkpos[pos]] == col->index);
3602 assert(SCIPsetIsEQ(set, row->vals[col->linkpos[pos]], col->vals[pos]));
3603 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, col->linkpos[pos], col->vals[pos] + incval) );
3604 }
3605
3606 /* change the coefficient in the column */
3607 SCIP_CALL( colChgCoefPos(col, set, lp, pos, col->vals[pos] + incval) );
3608 }
3609
3610 checkLinks(lp);
3611
3612 return SCIP_OKAY;
3613}
3614
3615/** insert column in the chgcols list (if not already there) */
3616static
3618 SCIP_COL* col, /**< LP column to change */
3619 SCIP_SET* set, /**< global SCIP settings */
3620 SCIP_LP* lp /**< current LP data */
3621 )
3622{
3623 if( !col->objchanged && !col->lbchanged && !col->ubchanged )
3624 {
3625 SCIP_CALL( ensureChgcolsSize(lp, set, lp->nchgcols+1) );
3626 lp->chgcols[lp->nchgcols] = col;
3627 lp->nchgcols++;
3628 }
3629
3630 /* mark the current LP unflushed */
3631 lp->flushed = FALSE;
3632
3633 return SCIP_OKAY;
3634}
3635
3636/** Is the new value reliable or may we have cancellation?
3637 *
3638 * @note: Here we only consider cancellations which can occur during decreasing the oldvalue to newvalue; not the
3639 * cancellations which can occur during increasing the oldvalue to the newvalue
3640 */
3641static
3643 SCIP_SET* set, /**< global SCIP settings */
3644 SCIP_Real newvalue, /**< new value */
3645 SCIP_Real oldvalue /**< old reliable value */
3646 )
3647{
3648 SCIP_Real quotient;
3649
3650 assert(set != NULL);
3651 assert(oldvalue != SCIP_INVALID); /*lint !e777*/
3652
3653 quotient = (REALABS(newvalue)+1.0) / (REALABS(oldvalue) + 1.0);
3654
3655 return SCIPsetIsZero(set, quotient);
3656}
3657
3658/** update norms of objective function vector */
3659static
3661 SCIP_LP* lp, /**< current LP data */
3662 SCIP_SET* set, /**< global SCIP settings */
3663 SCIP_Real oldobj, /**< old objective value of variable */
3664 SCIP_Real newobj /**< new objective value of variable */
3665 )
3666{
3667 if( REALABS(newobj) != REALABS(oldobj) ) /*lint !e777*/
3668 {
3669 if( !lp->objsqrnormunreliable )
3670 {
3671 SCIP_Real oldvalue;
3672
3673 oldvalue = lp->objsqrnorm;
3674 lp->objsqrnorm += SQR(newobj) - SQR(oldobj);
3675
3676 /* due to numerical cancellations, we recalculate lp->objsqrnorm using all variables */
3677 if( SCIPsetIsLT(set, lp->objsqrnorm, 0.0) || isNewValueUnreliable(set, lp->objsqrnorm, oldvalue) )
3679 else
3680 {
3681 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
3682
3683 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
3684 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
3685
3686 assert(lp->objsqrnorm >= 0.0);
3687 }
3688 }
3689
3690 lp->objsumnorm += REALABS(newobj) - REALABS(oldobj);
3691 lp->objsumnorm = MAX(lp->objsumnorm, 0.0);
3692 }
3693}
3694
3695/** changes objective value of column */
3697 SCIP_COL* col, /**< LP column to change */
3698 SCIP_SET* set, /**< global SCIP settings */
3699 SCIP_LP* lp, /**< current LP data */
3700 SCIP_Real newobj /**< new objective value */
3701 )
3702{
3703 assert(col != NULL);
3704 assert(col->var != NULL);
3706 assert(SCIPvarGetCol(col->var) == col);
3707 assert(lp != NULL);
3708
3709 SCIPsetDebugMsg(set, "changing objective value of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->obj, newobj);
3710
3711 /* only add actual changes */
3712 if( !SCIPsetIsEQ(set, col->obj, newobj) )
3713 {
3714 /* only variables with a real position in the LPI can be inserted */
3715 if( col->lpipos >= 0 )
3716 {
3717 /* insert column in the chgcols list (if not already there) */
3718 SCIP_CALL( insertColChgcols(col, set, lp) );
3719
3720 /* mark objective value change in the column */
3721 col->objchanged = TRUE;
3722
3723 assert(lp->nchgcols > 0);
3724 }
3725 /* in any case, when the sign of the objective (and thereby the best bound) changes, the variable has to enter the
3726 * LP and the LP has to be flushed
3727 */
3728 else if( (col->obj < 0.0 && newobj >= 0.0 && SCIPsetIsZero(set, col->ub))
3729 || (col->obj >= 0.0 && newobj < 0.0 && SCIPsetIsZero(set, col->lb)) )
3730 {
3731 /* mark the LP unflushed */
3732 lp->flushed = FALSE;
3733 }
3734 }
3735
3736 /* store new objective function value */
3737 col->obj = newobj;
3738
3739 /* update original objective value, as long as we are not in diving or probing and changed objective values */
3740 if( !lp->divingobjchg )
3741 {
3742 SCIP_Real oldobj = col->unchangedobj;
3743
3744 assert(SCIPsetIsEQ(set, newobj, SCIPvarGetUnchangedObj(col->var)));
3745 col->unchangedobj = newobj;
3746
3747 /* update the objective function vector norms */
3748 lpUpdateObjNorms(lp, set, oldobj, newobj);
3749 }
3750
3751 return SCIP_OKAY;
3752}
3753
3754/** changes lower bound of column */
3756 SCIP_COL* col, /**< LP column to change */
3757 SCIP_SET* set, /**< global SCIP settings */
3758 SCIP_LP* lp, /**< current LP data */
3759 SCIP_Real newlb /**< new lower bound value */
3760 )
3761{
3762 assert(col != NULL);
3763 assert(col->var != NULL);
3765 assert(SCIPvarGetCol(col->var) == col);
3766 assert(lp != NULL);
3767
3768 SCIPsetDebugMsg(set, "changing lower bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->lb, newlb);
3769
3770 /* only add actual changes */
3771 if( !SCIPsetIsEQ(set, col->lb, newlb) )
3772 {
3773 /* only variables with a real position in the LPI can be inserted */
3774 if( col->lpipos >= 0 )
3775 {
3776 /* insert column in the chgcols list (if not already there) */
3777 SCIP_CALL( insertColChgcols(col, set, lp) );
3778
3779 /* mark bound change in the column */
3780 col->lbchanged = TRUE;
3781
3782 assert(lp->nchgcols > 0);
3783 }
3784 /* 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
3785 * flushed
3786 */
3787 else if( col->obj >= 0.0 && SCIPsetIsZero(set, col->lb) )
3788 {
3789 /* mark the LP unflushed */
3790 lp->flushed = FALSE;
3791 }
3792 }
3793
3794 col->lb = newlb;
3795
3796 return SCIP_OKAY;
3797}
3798
3799/** changes upper bound of column */
3801 SCIP_COL* col, /**< LP column to change */
3802 SCIP_SET* set, /**< global SCIP settings */
3803 SCIP_LP* lp, /**< current LP data */
3804 SCIP_Real newub /**< new upper bound value */
3805 )
3806{
3807 assert(col != NULL);
3808 assert(col->var != NULL);
3810 assert(SCIPvarGetCol(col->var) == col);
3811 assert(lp != NULL);
3812
3813 SCIPsetDebugMsg(set, "changing upper bound of column <%s> from %f to %f\n", SCIPvarGetName(col->var), col->ub, newub);
3814
3815 /* only add actual changes */
3816 if( !SCIPsetIsEQ(set, col->ub, newub) )
3817 {
3818 /* only variables with a real position in the LPI can be inserted */
3819 if( col->lpipos >= 0 )
3820 {
3821 /* insert column in the chgcols list (if not already there) */
3822 SCIP_CALL( insertColChgcols(col, set, lp) );
3823
3824 /* mark bound change in the column */
3825 col->ubchanged = TRUE;
3826
3827 assert(lp->nchgcols > 0);
3828 }
3829 /* 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
3830 * flushed
3831 */
3832 else if( col->obj < 0.0 && SCIPsetIsZero(set, col->ub) )
3833 {
3834 /* mark the LP unflushed */
3835 lp->flushed = FALSE;
3836 }
3837 }
3838
3839 col->ub = newub;
3840
3841 return SCIP_OKAY;
3842}
3843
3844/** calculates the reduced costs of a column using the given dual solution vector */
3846 SCIP_COL* col, /**< LP column */
3847 SCIP_Real* dualsol /**< dual solution vector for current LP rows */
3848 )
3849{
3850 SCIP_ROW* row;
3851 SCIP_Real redcost;
3852 int i;
3853
3854 assert(col != NULL);
3856 assert(SCIPvarGetCol(col->var) == col);
3857 assert(dualsol != NULL);
3858
3859 redcost = col->obj;
3860 for( i = 0; i < col->nlprows; ++i )
3861 {
3862 row = col->rows[i];
3863 assert(row != NULL);
3864 assert(row->lppos >= 0);
3865 redcost -= col->vals[i] * dualsol[row->lppos];
3866 }
3867
3868 if( col->nunlinked > 0 )
3869 {
3870 for( i = col->nlprows; i < col->len; ++i )
3871 {
3872 row = col->rows[i];
3873 assert(row != NULL);
3874 assert(row->lppos == -1 || col->linkpos[i] == -1);
3875 if( row->lppos >= 0 )
3876 redcost -= col->vals[i] * dualsol[row->lppos];
3877 }
3878 }
3879#ifndef NDEBUG
3880 else
3881 {
3882 for( i = col->nlprows; i < col->len; ++i )
3883 {
3884 row = col->rows[i];
3885 assert(row != NULL);
3886 assert(row->lppos == -1);
3887 assert(col->linkpos[i] >= 0);
3888 }
3889 }
3890#endif
3891
3892 return redcost;
3893}
3894
3895/** calculates the reduced costs of a column using the dual solution stored in the rows */
3896static
3898 SCIP_COL* col /**< LP column */
3899 )
3900{
3901 SCIP_ROW* row;
3902 SCIP_Real redcost;
3903 int i;
3904
3905 assert(col != NULL);
3907 assert(SCIPvarGetCol(col->var) == col);
3908
3909 redcost = col->obj;
3910 for( i = 0; i < col->nlprows; ++i )
3911 {
3912 row = col->rows[i];
3913 assert(row != NULL);
3914 assert(row->dualsol != SCIP_INVALID); /*lint !e777*/
3915 assert(row->lppos >= 0);
3916 assert(col->linkpos[i] >= 0);
3917 redcost -= col->vals[i] * row->dualsol;
3918 }
3919
3920 if( col->nunlinked > 0 )
3921 {
3922 for( i = col->nlprows; i < col->len; ++i )
3923 {
3924 row = col->rows[i];
3925 assert(row != NULL);
3926 assert(row->lppos >= 0 || row->dualsol == 0.0);
3927 assert(row->lppos == -1 || col->linkpos[i] == -1);
3928 if( row->lppos >= 0 )
3929 redcost -= col->vals[i] * row->dualsol;
3930 }
3931 }
3932#ifndef NDEBUG
3933 else
3934 {
3935 for( i = col->nlprows; i < col->len; ++i )
3936 {
3937 row = col->rows[i];
3938 assert(row != NULL);
3939 assert(row->dualsol == 0.0);
3940 assert(row->lppos == -1);
3941 assert(col->linkpos[i] >= 0);
3942 }
3943 }
3944#endif
3945
3946 return redcost;
3947}
3948
3949/** gets the reduced costs of a column in last LP or after recalculation */
3951 SCIP_COL* col, /**< LP column */
3952 SCIP_STAT* stat, /**< problem statistics */
3953 SCIP_LP* lp /**< current LP data */
3954 )
3955{
3956 assert(col != NULL);
3957 assert(stat != NULL);
3958 assert(lp != NULL);
3959 assert(col->validredcostlp <= stat->lpcount);
3960 assert(lp->validsollp == stat->lpcount);
3961
3962 if( col->validredcostlp < stat->lpcount )
3963 {
3964 col->redcost = colCalcInternalRedcost(col);
3965 col->validredcostlp = stat->lpcount;
3966 }
3967 assert(col->validredcostlp == stat->lpcount);
3968 assert(col->redcost != SCIP_INVALID); /*lint !e777*/
3969
3970 return col->redcost;
3971}
3972
3973/** gets the feasibility of (the dual row of) a column in last LP or after recalculation */
3975 SCIP_COL* col, /**< LP column */
3976 SCIP_SET* set, /**< global SCIP settings */
3977 SCIP_STAT* stat, /**< problem statistics */
3978 SCIP_LP* lp /**< current LP data */
3979 )
3980{
3981 assert(col != NULL);
3982 assert(set != NULL);
3983 assert(stat != NULL);
3984 assert(lp != NULL);
3985 assert(lp->validsollp == stat->lpcount);
3986
3987 /* A column's reduced cost is defined as
3988 * redcost = obj - activity, activity = y^T * col. (activity = obj - redcost)
3989 * The activity is equal to the activity of the corresponding row in the dual LP.
3990 * The column's feasibility is the feasibility of the corresponding row in the dual LP.
3991 * The sides of the dual row depend on the bounds of the column:
3992 * - lb == ub : dual row is a free row with infinite sides
3993 * - 0 <= lb < ub: activity <= obj => 0 <= redcost
3994 * - lb < 0 < ub: obj <= activity <= obj => 0 <= redcost <= 0
3995 * - lb < ub <= 0: obj <= activity => redcost <= 0
3996 */
3997 if( SCIPsetIsEQ(set, col->lb, col->ub) )
3998 {
3999 /* dual row is free */
4000 return SCIPsetInfinity(set);
4001 }
4002 else
4003 {
4004 SCIP_Real redcost;
4005
4006 /* calculate reduced costs */
4007 redcost = SCIPcolGetRedcost(col, stat, lp);
4008
4009 if( !SCIPsetIsNegative(set, col->lb) )
4010 {
4011 /* dual row is activity <= obj <=> redcost >= 0 */
4012 return redcost;
4013 }
4014 else if( SCIPsetIsPositive(set, col->ub) )
4015 {
4016 /* dual row is activity == obj <=> redcost == 0 */
4017 return -REALABS(redcost);
4018 }
4019 else
4020 {
4021 /* dual row is activity >= obj <=> redcost <= 0 */
4022 return -redcost;
4023 }
4024 }
4025}
4026
4027/** calculates the Farkas coefficient y^T A_i of a column i using the given dual Farkas vector y */
4029 SCIP_COL* col, /**< LP column */
4030 SCIP_Real* dualfarkas /**< dense dual Farkas vector for current LP rows */
4031 )
4032{
4033 SCIP_ROW* row;
4034 SCIP_Real farkas;
4035 int i;
4036
4037 assert(col != NULL);
4039 assert(SCIPvarGetCol(col->var) == col);
4040 assert(dualfarkas != NULL);
4041
4042 farkas = 0.0;
4043 for( i = 0; i < col->nlprows; ++i )
4044 {
4045 row = col->rows[i];
4046 assert(row != NULL);
4047 assert(row->lppos >= 0);
4048 farkas += col->vals[i] * dualfarkas[row->lppos];
4049 }
4050
4051 if( col->nunlinked > 0 )
4052 {
4053 for( i = col->nlprows; i < col->len; ++i )
4054 {
4055 row = col->rows[i];
4056 assert(row != NULL);
4057 assert(row->lppos == -1 || col->linkpos[i] == -1);
4058 if( row->lppos >= 0 )
4059 farkas += col->vals[i] * dualfarkas[row->lppos];
4060 }
4061 }
4062#ifndef NDEBUG
4063 else
4064 {
4065 for( i = col->nlprows; i < col->len; ++i )
4066 {
4067 row = col->rows[i];
4068 assert(row != NULL);
4069 assert(row->lppos == -1);
4070 assert(col->linkpos[i] >= 0);
4071 }
4072 }
4073#endif
4074
4075 return farkas;
4076}
4077
4078/** gets the Farkas coefficient y^T A_i of a column i in last LP (which must be infeasible) */
4079static
4081 SCIP_COL* col /**< LP column */
4082 )
4083{
4084 SCIP_ROW* row;
4085 SCIP_Real farkas;
4086 int i;
4087
4088 assert(col != NULL);
4090 assert(SCIPvarGetCol(col->var) == col);
4091
4092 farkas = 0.0;
4093 for( i = 0; i < col->nlprows; ++i )
4094 {
4095 row = col->rows[i];
4096 assert(row != NULL);
4097 assert(row->dualfarkas != SCIP_INVALID); /*lint !e777*/
4098 assert(row->lppos >= 0);
4099 assert(col->linkpos[i] >= 0);
4100 farkas += col->vals[i] * row->dualfarkas;
4101 }
4102
4103 if( col->nunlinked > 0 )
4104 {
4105 for( i = col->nlprows; i < col->len; ++i )
4106 {
4107 row = col->rows[i];
4108 assert(row != NULL);
4109 assert(row->lppos >= 0 || row->dualfarkas == 0.0);
4110 assert(row->lppos == -1 || col->linkpos[i] == -1);
4111 if( row->lppos >= 0 )
4112 farkas += col->vals[i] * row->dualfarkas;
4113 }
4114 }
4115#ifndef NDEBUG
4116 else
4117 {
4118 for( i = col->nlprows; i < col->len; ++i )
4119 {
4120 row = col->rows[i];
4121 assert(row != NULL);
4122 assert(row->dualfarkas == 0.0);
4123 assert(row->lppos == -1);
4124 assert(col->linkpos[i] >= 0);
4125 }
4126 }
4127#endif
4128
4129 return farkas;
4130}
4131
4132/** gets the Farkas coefficient of a column in last LP (which must be infeasible) */
4134 SCIP_COL* col, /**< LP column */
4135 SCIP_STAT* stat, /**< problem statistics */
4136 SCIP_LP* lp /**< current LP data */
4137 )
4138{
4139 assert(col != NULL);
4140 assert(stat != NULL);
4141 assert(lp != NULL);
4142 assert(col->validfarkaslp <= stat->lpcount);
4143 assert(lp->validfarkaslp == stat->lpcount);
4144
4145 if( col->validfarkaslp < stat->lpcount )
4146 {
4148 col->validfarkaslp = stat->lpcount;
4149 }
4150 assert(col->validfarkaslp == stat->lpcount);
4151 assert(col->farkascoef != SCIP_INVALID); /*lint !e777*/
4152
4153 return col->farkascoef;
4154}
4155
4156/** gets the Farkas value of a column in last LP (which must be infeasible), i.e. the Farkas coefficient y^T A_i times
4157 * the best bound for this coefficient, i.e. max{y^T A_i x_i | lb <= x_i <= ub}
4158 */
4160 SCIP_COL* col, /**< LP column */
4161 SCIP_STAT* stat, /**< problem statistics */
4162 SCIP_LP* lp /**< current LP data */
4163 )
4164{
4165 SCIP_Real farkascoef;
4166
4167 assert(col != NULL);
4168
4169 farkascoef = SCIPcolGetFarkasCoef(col, stat, lp);
4170
4171 if( farkascoef > 0.0 )
4172 return col->ub * farkascoef;
4173 else
4174 return col->lb * farkascoef;
4175}
4176
4177/** start strong branching - call before any strong branching */
4179 SCIP_LP* lp /**< LP data */
4180 )
4181{
4182 assert(lp != NULL);
4183 assert(!lp->strongbranching);
4184
4185 lp->strongbranching = TRUE;
4186 SCIPdebugMessage("starting strong branching ...\n");
4188
4189 return SCIP_OKAY;
4190}
4191
4192/** end strong branching - call after any strong branching */
4194 SCIP_LP* lp /**< LP data */
4195 )
4196{
4197 assert(lp != NULL);
4198 assert(lp->strongbranching);
4199
4200 lp->strongbranching = FALSE;
4201 SCIPdebugMessage("ending strong branching ...\n");
4203
4204 return SCIP_OKAY;
4205}
4206
4207/** sets strong branching information for a column variable */
4209 SCIP_COL* col, /**< LP column */
4210 SCIP_SET* set, /**< global SCIP settings */
4211 SCIP_STAT* stat, /**< dynamic problem statistics */
4212 SCIP_LP* lp, /**< LP data */
4213 SCIP_Real lpobjval, /**< objective value of the current LP */
4214 SCIP_Real primsol, /**< primal solution value of the column in the current LP */
4215 SCIP_Real sbdown, /**< dual bound after branching column down */
4216 SCIP_Real sbup, /**< dual bound after branching column up */
4217 SCIP_Bool sbdownvalid, /**< is the returned down value a valid dual bound? */
4218 SCIP_Bool sbupvalid, /**< is the returned up value a valid dual bound? */
4219 SCIP_Longint iter, /**< total number of strong branching iterations */
4220 int itlim /**< iteration limit applied to the strong branching call */
4221 )
4222{
4223 assert(col != NULL);
4224 assert(col->var != NULL);
4225 assert(SCIPcolIsIntegral(col));
4226 assert(SCIPvarIsIntegral(col->var));
4228 assert(SCIPvarGetCol(col->var) == col);
4229 assert(col->lpipos >= 0);
4230 assert(col->lppos >= 0);
4231 assert(set != NULL);
4232 assert(stat != NULL);
4233 assert(lp != NULL);
4234 assert(lp->strongbranchprobing);
4235 assert(col->lppos < lp->ncols);
4236 assert(lp->cols[col->lppos] == col);
4237 assert(itlim >= 1);
4238
4239 col->sblpobjval = lpobjval;
4240 col->sbsolval = primsol;
4241 col->validsblp = stat->nlps;
4242 col->sbnode = stat->nnodes;
4243
4244 col->sbitlim = itlim;
4245 col->nsbcalls++;
4246
4247 col->sbdown = MIN(sbdown, lp->cutoffbound);
4248 col->sbup = MIN(sbup, lp->cutoffbound);
4249 col->sbdownvalid = sbdownvalid;
4250 col->sbupvalid = sbupvalid;
4251
4252 SCIPstatIncrement(stat, set, nstrongbranchs);
4253 SCIPstatAdd(stat, set, nsblpiterations, iter);
4254 if( stat->nnodes == 1 )
4255 {
4256 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4257 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4258 }
4259}
4260
4261/** invalidates strong branching information for a column variable */
4263 SCIP_COL* col, /**< LP column */
4264 SCIP_SET* set, /**< global SCIP settings */
4265 SCIP_STAT* stat, /**< dynamic problem statistics */
4266 SCIP_LP* lp /**< LP data */
4267 )
4268{
4269 assert(col != NULL);
4270 assert(col->var != NULL);
4271 assert(SCIPcolIsIntegral(col));
4272 assert(SCIPvarIsIntegral(col->var));
4274 assert(SCIPvarGetCol(col->var) == col);
4275 assert(col->lpipos >= 0);
4276 assert(col->lppos >= 0);
4277 assert(set != NULL);
4278 assert(stat != NULL);
4279 assert(lp != NULL);
4280 assert(lp->strongbranchprobing);
4281 assert(col->lppos < lp->ncols);
4282 assert(lp->cols[col->lppos] == col);
4283
4284 col->sbdown = SCIP_INVALID;
4285 col->sbup = SCIP_INVALID;
4286 col->sbdownvalid = FALSE;
4287 col->sbupvalid = FALSE;
4288 col->validsblp = -1;
4289 col->sbsolval = SCIP_INVALID;
4290 col->sblpobjval = SCIP_INVALID;
4291 col->sbnode = -1;
4292 col->sbitlim = -1;
4293}
4294
4295
4296/** gets strong branching information on a column variable */
4298 SCIP_COL* col, /**< LP column */
4299 SCIP_Bool integral, /**< should integral strong branching be performed? */
4300 SCIP_SET* set, /**< global SCIP settings */
4301 SCIP_STAT* stat, /**< dynamic problem statistics */
4302 SCIP_PROB* prob, /**< problem data */
4303 SCIP_LP* lp, /**< LP data */
4304 int itlim, /**< iteration limit for strong branchings */
4305 SCIP_Bool updatecol, /**< should col be updated, or should it stay in its current state ? */
4306 SCIP_Bool updatestat, /**< should stat be updated, or should it stay in its current state ? */
4307 SCIP_Real* down, /**< stores dual bound after branching column down */
4308 SCIP_Real* up, /**< stores dual bound after branching column up */
4309 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4310 * otherwise, it can only be used as an estimate value */
4311 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4312 * otherwise, it can only be used as an estimate value */
4313 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4314 )
4315{
4316 SCIP_Real sbdown;
4317 SCIP_Real sbup;
4318 SCIP_Bool sbdownvalid;
4319 SCIP_Bool sbupvalid;
4320 SCIP_Longint validsblp;
4321 SCIP_Real sbsolval;
4322 SCIP_Real sblpobjval;
4323 SCIP_Longint sbnode;
4324 int sbitlim;
4325 int nsbcalls;
4326
4327 assert(col != NULL);
4328 assert(col->var != NULL);
4329 assert(SCIPcolIsIntegral(col));
4330 assert(SCIPvarIsIntegral(col->var));
4332 assert(SCIPvarGetCol(col->var) == col);
4333 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4334 assert(col->lpipos >= 0);
4335 assert(col->lppos >= 0);
4336 assert(set != NULL);
4337 assert(stat != NULL);
4338 assert(lp != NULL);
4339 assert(lp->flushed);
4340 assert(lp->solved);
4341 assert(lp->strongbranching);
4342 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4343 assert(lp->validsollp == stat->lpcount);
4344 assert(col->lppos < lp->ncols);
4345 assert(lp->cols[col->lppos] == col);
4346 assert(itlim >= 1);
4347 /* assert(down != NULL);
4348 * assert(up != NULL); temporary hack for cloud branching
4349 */
4350 assert(lperror != NULL);
4351
4352 *lperror = FALSE;
4353
4354 sbdown = col->sbdown;
4355 sbup = col->sbup;
4356 sbdownvalid = col->sbdownvalid;
4357 sbupvalid = col->sbupvalid;
4358 sbitlim = col->sbitlim;
4359 nsbcalls = col->nsbcalls;
4360
4361 validsblp = stat->nlps;
4362 sbsolval = col->primsol;
4363 sblpobjval = SCIPlpGetObjval(lp, set, prob);
4364 sbnode = stat->nnodes;
4365 assert(integral || !SCIPsetIsFeasIntegral(set, col->primsol));
4366
4367 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4368 if( lp->looseobjvalinf > 0 )
4369 {
4370 sbdown = -SCIPsetInfinity(set);
4371 sbup = -SCIPsetInfinity(set);
4372 sbdownvalid = FALSE;
4373 sbupvalid = FALSE;
4374 }
4375 else
4376 {
4377 SCIP_RETCODE retcode;
4378 int iter;
4379
4380 SCIPsetDebugMsg(set, "performing strong branching on variable <%s>(%g) with %d iterations\n",
4381 SCIPvarGetName(col->var), col->primsol, itlim);
4382
4383 /* start timing */
4385
4386 /* call LPI strong branching */
4387 sbitlim = itlim;
4388 nsbcalls++;
4389
4390 sbdown = lp->lpobjval;
4391 sbup = lp->lpobjval;
4392
4393 if( integral )
4394 retcode = SCIPlpiStrongbranchInt(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4395 else
4396 {
4397 assert( ! SCIPsetIsIntegral(set, col->primsol) );
4398 retcode = SCIPlpiStrongbranchFrac(lp->lpi, col->lpipos, col->primsol, itlim, down == NULL ? NULL : &sbdown, up == NULL ? NULL : &sbup, &sbdownvalid, &sbupvalid, &iter);
4399 }
4400
4401 /* check return code for errors */
4402 if( retcode == SCIP_LPERROR )
4403 {
4404 *lperror = TRUE;
4405 sbdown = SCIP_INVALID;
4406 sbup = SCIP_INVALID;
4407 sbdownvalid = FALSE;
4408 sbupvalid = FALSE;
4409 validsblp = -1;
4410 sbsolval = SCIP_INVALID;
4411 sblpobjval = SCIP_INVALID;
4412 sbnode = -1;
4413 }
4414 else
4415 {
4416 SCIP_Real looseobjval;
4417
4418 *lperror = FALSE;
4419 SCIP_CALL( retcode );
4420
4421 looseobjval = getFiniteLooseObjval(lp, set, prob);
4422 sbdown = MIN(sbdown + looseobjval, lp->cutoffbound);
4423 sbup = MIN(sbup + looseobjval, lp->cutoffbound);
4424
4425 /* update strong branching statistics */
4426 if( updatestat )
4427 {
4428 if( iter == -1 )
4429 {
4430 /* calculate average iteration number */
4431 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4432 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4433 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4434 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4435 : 0;
4436 if( iter/2 >= itlim )
4437 iter = 2*itlim;
4438 }
4439 SCIPstatIncrement(stat, set, nstrongbranchs);
4440 SCIPstatAdd(stat, set, nsblpiterations, iter);
4441 if( stat->nnodes == 1 )
4442 {
4443 SCIPstatIncrement(stat, set, nrootstrongbranchs);
4444 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4445 }
4446 }
4447 }
4448
4449 /* stop timing */
4451 }
4452 assert(*lperror || sbdown != SCIP_INVALID); /*lint !e777*/
4453 assert(*lperror || sbup != SCIP_INVALID); /*lint !e777*/
4454
4455 if( down != NULL)
4456 *down = sbdown;
4457 if( up != NULL )
4458 *up = sbup;
4459 if( downvalid != NULL )
4460 *downvalid = sbdownvalid;
4461 if( upvalid != NULL )
4462 *upvalid = sbupvalid;
4463
4464 if( updatecol )
4465 {
4466 col->sbdown = sbdown;
4467 col->sbup = sbup;
4468 col->sbdownvalid = sbdownvalid;
4469 col->sbupvalid = sbupvalid;
4470 col->validsblp = validsblp;
4471 col->sbsolval = sbsolval;
4472 col->sblpobjval = sblpobjval;
4473 col->sbnode = sbnode;
4474 col->sbitlim = sbitlim;
4475 col->nsbcalls = nsbcalls;
4476 }
4477
4478 return SCIP_OKAY;
4479}
4480
4481/** gets strong branching information on column variables */
4483 SCIP_COL** cols, /**< LP columns */
4484 int ncols, /**< number of columns */
4485 SCIP_Bool integral, /**< should integral strong branching be performed? */
4486 SCIP_SET* set, /**< global SCIP settings */
4487 SCIP_STAT* stat, /**< dynamic problem statistics */
4488 SCIP_PROB* prob, /**< problem data */
4489 SCIP_LP* lp, /**< LP data */
4490 int itlim, /**< iteration limit for strong branchings */
4491 SCIP_Real* down, /**< stores dual bounds after branching columns down */
4492 SCIP_Real* up, /**< stores dual bounds after branching columns up */
4493 SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds, or NULL;
4494 * otherwise, they can only be used as an estimate value */
4495 SCIP_Bool* upvalid, /**< stores whether the returned up values are valid dual bounds, or NULL;
4496 * otherwise, they can only be used as an estimate value */
4497 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
4498 )
4499{
4500 SCIP_RETCODE retcode;
4501 SCIP_Real* sbdown;
4502 SCIP_Real* sbup;
4503 SCIP_Bool* sbdownvalid;
4504 SCIP_Bool* sbupvalid;
4505 SCIP_Real* primsols;
4506 SCIP_COL** subcols;
4507 int* lpipos;
4508 int* subidx;
4509 int nsubcols;
4510 int iter;
4511 int j;
4512
4513 assert(cols != NULL);
4514 assert(set != NULL);
4515 assert(stat != NULL);
4516 assert(lp != NULL);
4517 assert(lp->flushed);
4518 assert(lp->solved);
4519 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
4520 assert(lp->validsollp == stat->lpcount);
4521 assert(itlim >= 1);
4522 assert(down != NULL);
4523 assert(up != NULL);
4524 assert(lperror != NULL);
4525
4526 *lperror = FALSE;
4527
4528 if ( ncols <= 0 )
4529 return SCIP_OKAY;
4530
4531 /* start timing */
4533
4534 /* initialize storage */
4535 SCIP_CALL( SCIPsetAllocBufferArray(set, &subcols, ncols) );
4536 SCIP_CALL( SCIPsetAllocBufferArray(set, &subidx, ncols) );
4537 SCIP_CALL( SCIPsetAllocBufferArray(set, &lpipos, ncols) );
4538 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsols, ncols) );
4539 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdown, ncols) );
4540 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbup, ncols) );
4541 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbdownvalid, ncols) );
4542 SCIP_CALL( SCIPsetAllocBufferArray(set, &sbupvalid, ncols) );
4543
4544 nsubcols = 0;
4545 for( j = 0; j < ncols; ++j )
4546 {
4547 SCIP_COL* col;
4548 col = cols[j];
4549
4550 assert(col->lppos < lp->ncols);
4551 assert(lp->cols[col->lppos] == col);
4552 assert(SCIPcolIsIntegral(col));
4553 assert(SCIPvarIsIntegral(col->var));
4555 assert(SCIPvarGetCol(col->var) == col);
4556 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
4557 assert(col->lpipos >= 0);
4558 assert(col->lppos >= 0);
4559
4560 col->validsblp = stat->nlps;
4561 col->sbsolval = col->primsol;
4562 col->sblpobjval = SCIPlpGetObjval(lp, set, prob);
4563 col->sbnode = stat->nnodes;
4564 assert(!SCIPsetIsFeasIntegral(set, col->primsol));
4565
4566 /* if a loose variables has an infinite best bound, the LP bound is -infinity and no gain can be achieved */
4567 if( lp->looseobjvalinf > 0 )
4568 {
4569 /* directly set up column and result vectors*/
4570 col->sbdown = -SCIPsetInfinity(set);
4571 col->sbup = -SCIPsetInfinity(set);
4572 col->sbdownvalid = FALSE;
4573 col->sbupvalid = FALSE;
4574 down[j] = col->sbdown;
4575 up[j] = col->sbup;
4576 if( downvalid != NULL )
4577 downvalid[j] = col->sbdownvalid;
4578 if( upvalid != NULL )
4579 upvalid[j] = col->sbupvalid;
4580 }
4581 else
4582 {
4583 col->sbitlim = itlim;
4584 col->nsbcalls++;
4585
4586 lpipos[nsubcols] = col->lpipos;
4587 primsols[nsubcols] = col->primsol;
4588 assert( integral || ! SCIPsetIsFeasIntegral(set, col->primsol) );
4589 subidx[nsubcols] = j;
4590 subcols[nsubcols++] = col;
4591 }
4592 }
4593
4594 SCIPsetDebugMsg(set, "performing strong branching on %d variables with %d iterations\n", ncols, itlim);
4595
4596 /* call LPI strong branching */
4597 if ( integral )
4598 retcode = SCIPlpiStrongbranchesInt(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4599 else
4600 retcode = SCIPlpiStrongbranchesFrac(lp->lpi, lpipos, nsubcols, primsols, itlim, sbdown, sbup, sbdownvalid, sbupvalid, &iter);
4601
4602 /* check return code for errors */
4603 if( retcode == SCIP_LPERROR )
4604 {
4605 *lperror = TRUE;
4606
4607 for( j = 0; j < nsubcols; ++j )
4608 {
4609 SCIP_COL* col;
4610 int idx;
4611
4612 col = subcols[j];
4613 idx = subidx[j];
4614
4615 col->sbdown = SCIP_INVALID;
4616 col->sbup = SCIP_INVALID;
4617 col->sbdownvalid = FALSE;
4618 col->sbupvalid = FALSE;
4619 col->validsblp = -1;
4620 col->sbsolval = SCIP_INVALID;
4621 col->sblpobjval = SCIP_INVALID;
4622 col->sbnode = -1;
4623
4624 down[idx] = col->sbdown;
4625 up[idx] = col->sbup;
4626 if( downvalid != NULL )
4627 downvalid[idx] = col->sbdownvalid;
4628 if( upvalid != NULL )
4629 upvalid[idx] = col->sbupvalid;
4630 }
4631 }
4632 else
4633 {
4634 SCIP_Real looseobjval;
4635
4636 *lperror = FALSE;
4637 SCIP_CALL( retcode );
4638
4639 looseobjval = getFiniteLooseObjval(lp, set, prob);
4640
4641 for( j = 0; j < nsubcols; ++j )
4642 {
4643 SCIP_COL* col;
4644 int idx;
4645
4646 col = subcols[j];
4647 idx = subidx[j];
4648
4649 assert( col->sbdown != SCIP_INVALID); /*lint !e777*/
4650 assert( col->sbup != SCIP_INVALID); /*lint !e777*/
4651
4652 col->sbdown = MIN(sbdown[j] + looseobjval, lp->cutoffbound);
4653 col->sbup = MIN(sbup[j] + looseobjval, lp->cutoffbound);
4654 col->sbdownvalid = sbdownvalid[j];
4655 col->sbupvalid = sbupvalid[j];
4656
4657 down[idx] = col->sbdown;
4658 up[idx] = col->sbup;
4659 if( downvalid != NULL )
4660 downvalid[idx] = col->sbdownvalid;
4661 if( upvalid != NULL )
4662 upvalid[idx] = col->sbupvalid;
4663 }
4664
4665 /* update strong branching statistics */
4666 if( iter == -1 )
4667 {
4668 /* calculate average iteration number */
4669 iter = stat->ndualresolvelps > 0 ? (int)(2*stat->ndualresolvelpiterations / stat->ndualresolvelps)
4670 : stat->nduallps > 0 ? (int)((stat->nduallpiterations / stat->nduallps) / 5)
4671 : stat->nprimalresolvelps > 0 ? (int)(2*stat->nprimalresolvelpiterations / stat->nprimalresolvelps)
4672 : stat->nprimallps > 0 ? (int)((stat->nprimallpiterations / stat->nprimallps) / 5)
4673 : 0;
4674 if( iter/2 >= itlim )
4675 iter = 2*itlim;
4676 }
4677 SCIPstatAdd(stat, set, nstrongbranchs, ncols);
4678 SCIPstatAdd(stat, set, nsblpiterations, iter);
4679 if( stat->nnodes == 1 )
4680 {
4681 SCIPstatAdd(stat, set, nrootstrongbranchs, ncols);
4682 SCIPstatAdd(stat, set, nrootsblpiterations, iter);
4683 }
4684 }
4685
4686 SCIPsetFreeBufferArray(set, &sbupvalid);
4687 SCIPsetFreeBufferArray(set, &sbdownvalid);
4689 SCIPsetFreeBufferArray(set, &sbdown);
4690 SCIPsetFreeBufferArray(set, &primsols);
4691 SCIPsetFreeBufferArray(set, &lpipos);
4692 SCIPsetFreeBufferArray(set, &subidx);
4693 SCIPsetFreeBufferArray(set, &subcols);
4694
4695 /* stop timing */
4697
4698 return SCIP_OKAY;
4699}
4700
4701/** gets last strong branching information available for a column variable;
4702 * returns values of SCIP_INVALID, if strong branching was not yet called on the given column;
4703 * keep in mind, that the returned old values may have nothing to do with the current LP solution
4704 */
4706 SCIP_COL* col, /**< LP column */
4707 SCIP_Real* down, /**< stores dual bound after branching column down, or NULL */
4708 SCIP_Real* up, /**< stores dual bound after branching column up, or NULL */
4709 SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound, or NULL;
4710 * otherwise, it can only be used as an estimate value */
4711 SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound, or NULL;
4712 * otherwise, it can only be used as an estimate value */
4713 SCIP_Real* solval, /**< stores LP solution value of column at last strong branching call, or NULL */
4714 SCIP_Real* lpobjval /**< stores LP objective value at last strong branching call, or NULL */
4715 )
4716{
4717 assert(col != NULL);
4718
4719 if( down != NULL )
4720 *down = col->sbdown;
4721 if( up != NULL )
4722 *up = col->sbup;
4723 if( downvalid != NULL )
4724 *downvalid = col->sbdownvalid;
4725 if( upvalid != NULL )
4726 *upvalid = col->sbupvalid;
4727 if( solval != NULL )
4728 *solval = col->sbsolval;
4729 if( lpobjval != NULL )
4730 *lpobjval = col->sblpobjval;
4731}
4732
4733/** if strong branching was already applied on the column at the current node, returns the number of LPs solved after
4734 * the LP where the strong branching on this column was applied;
4735 * if strong branching was not yet applied on the column at the current node, returns INT_MAX
4736 */
4738 SCIP_COL* col, /**< LP column */
4739 SCIP_STAT* stat /**< dynamic problem statistics */
4740 )
4741{
4742 assert(col != NULL);
4743 assert(stat != NULL);
4744
4745 return (col->sbnode != stat->nnodes ? SCIP_LONGINT_MAX : stat->nlps - col->validsblp);
4746}
4747
4748/** marks a column to be not removable from the LP in the current node because it became obsolete */
4750 SCIP_COL* col, /**< LP column */
4751 SCIP_STAT* stat /**< problem statistics */
4752 )
4753{
4754 assert(col != NULL);
4755 assert(stat != NULL);
4756 assert(stat->nnodes > 0);
4757
4758 /* lpRemoveObsoleteCols() does not remove a column if the node number stored in obsoletenode equals the current node number */
4759 col->obsoletenode = stat->nnodes;
4760}
4761
4762
4763/*
4764 * Row methods
4765 */
4766
4767/** calculates row norms and min/maxidx from scratch, and checks for sorting */
4768static
4770 SCIP_ROW* row, /**< LP row */
4771 SCIP_SET* set /**< global SCIP settings */
4772 )
4773{
4774 int i;
4775
4776 assert(row != NULL);
4777 assert(set != NULL);
4778
4779 row->sqrnorm = 0.0;
4780 row->sumnorm = 0.0;
4781 row->objprod = 0.0;
4782 row->maxval = 0.0;
4783 row->nummaxval = 1;
4784 row->minval = SCIPsetInfinity(set);
4785 row->numminval = 1;
4786 row->minidx = INT_MAX;
4787 row->maxidx = INT_MIN;
4788 row->validminmaxidx = TRUE;
4789 row->lpcolssorted = TRUE;
4790 row->nonlpcolssorted = TRUE;
4791
4792 /* check, if row is sorted
4793 * calculate sqrnorm, sumnorm, maxval, minval, minidx, and maxidx
4794 */
4795 for( i = 0; i < row->nlpcols; ++i )
4796 {
4797 assert(row->cols[i] != NULL);
4798 assert(!SCIPsetIsZero(set, row->vals[i]));
4799 assert(row->cols[i]->lppos >= 0);
4800 assert(row->linkpos[i] >= 0);
4801 assert(row->cols[i]->index == row->cols_index[i]);
4802
4803 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4804 if( i > 0 )
4805 {
4806 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4807 row->lpcolssorted = row->lpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4808 }
4809 }
4810 for( i = row->nlpcols; i < row->len; ++i )
4811 {
4812 assert(row->cols[i] != NULL);
4813 assert(!SCIPsetIsZero(set, row->vals[i]));
4814 assert(row->cols[i]->lppos == -1 || row->linkpos[i] == -1);
4815 assert(row->cols[i]->index == row->cols_index[i]);
4816
4817 rowAddNorms(row, set, row->cols[i], row->vals[i], TRUE);
4818 if( i > row->nlpcols )
4819 {
4820 assert(row->cols[i-1]->index == row->cols_index[i-1]);
4821 row->nonlpcolssorted = row->nonlpcolssorted && (row->cols_index[i-1] < row->cols_index[i]);
4822 }
4823 }
4824}
4825
4826/** calculates min/maxval and min/maxidx from scratch */
4827static
4829 SCIP_ROW* row, /**< LP row */
4830 SCIP_SET* set /**< global SCIP settings */
4831 )
4832{
4833 SCIP_COL* col;
4834 SCIP_Real absval;
4835 int i;
4836
4837 assert(row != NULL);
4838 assert(set != NULL);
4839
4840 row->maxval = 0.0;
4841 row->nummaxval = 1;
4842 row->numintcols = 0;
4843 row->minval = SCIPsetInfinity(set);
4844 row->numminval = 1;
4845 row->minidx = INT_MAX;
4846 row->maxidx = INT_MIN;
4847 row->validminmaxidx = TRUE;
4848
4849 /* calculate maxval, minval, minidx, and maxidx */
4850 for( i = 0; i < row->len; ++i )
4851 {
4852 col = row->cols[i];
4853 assert(col != NULL);
4854 assert(!SCIPsetIsZero(set, row->vals[i]));
4855
4856 absval = REALABS(row->vals[i]);
4857 assert(!SCIPsetIsZero(set, absval));
4858
4859 /* update min/maxidx */
4860 row->minidx = MIN(row->minidx, col->index);
4861 row->maxidx = MAX(row->maxidx, col->index);
4862 row->numintcols += SCIPcolIsIntegral(col); /*lint !e713*/
4863
4864 /* update maximal and minimal non-zero value */
4865 if( row->nummaxval > 0 )
4866 {
4867 if( SCIPsetIsGT(set, absval, row->maxval) )
4868 {
4869 row->maxval = absval;
4870 row->nummaxval = 1;
4871 }
4872 else if( SCIPsetIsGE(set, absval, row->maxval) )
4873 {
4874 /* make sure the maxval is always exactly the same */
4875 row->maxval = MAX(absval, row->maxval);
4876 row->nummaxval++;
4877 }
4878 }
4879 if( row->numminval > 0 )
4880 {
4881 if( SCIPsetIsLT(set, absval, row->minval) )
4882 {
4883 row->minval = absval;
4884 row->numminval = 1;
4885 }
4886 else if( SCIPsetIsLE(set, absval, row->minval) )
4887 {
4888 /* make sure the minval is always exactly the same */
4889 row->minval = MIN(absval, row->minval);
4890 row->numminval++;
4891 }
4892 }
4893 }
4894}
4895
4896/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
4897static
4899 SCIP_Real val, /**< value that should be scaled to an integral value */
4900 SCIP_Real scalar, /**< scalar that should be tried */
4901 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
4902 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
4903 SCIP_Real* intval /**< pointer to store the scaled integral value, or NULL */
4904 )
4905{
4906 SCIP_Real sval;
4907 SCIP_Real downval;
4908 SCIP_Real upval;
4909
4910 assert(mindelta <= 0.0);
4911 assert(maxdelta >= 0.0);
4912
4913 sval = val * scalar;
4914 downval = floor(sval);
4915 upval = ceil(sval);
4916
4917 if( SCIPrelDiff(sval, downval) <= maxdelta )
4918 {
4919 if( intval != NULL )
4920 *intval = downval;
4921 return TRUE;
4922 }
4923 else if( SCIPrelDiff(sval, upval) >= mindelta )
4924 {
4925 if( intval != NULL )
4926 *intval = upval;
4927 return TRUE;
4928 }
4929
4930 return FALSE;
4931}
4932
4933/** scales row with given factor, and rounds coefficients to integers if close enough;
4934 * the constant is automatically moved to the sides;
4935 * if the row's activity is proven to be integral, the sides are automatically rounded to the next integer
4936 */
4937static
4939 SCIP_ROW* row, /**< LP row */
4940 BMS_BLKMEM* blkmem, /**< block memory */
4941 SCIP_SET* set, /**< global SCIP settings */
4942 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4943 SCIP_STAT* stat, /**< problem statistics */
4944 SCIP_LP* lp, /**< current LP data */
4945 SCIP_Real scaleval, /**< value to scale row with */
4946 SCIP_Bool integralcontvars, /**< should the coefficients of the continuous variables also be made integral,
4947 * if they are close to integral values? */
4948 SCIP_Real minrounddelta, /**< minimal relative difference of scaled coefficient s*c and integral i,
4949 * upto which the integral is used instead of the scaled real coefficient */
4950 SCIP_Real maxrounddelta /**< maximal relative difference of scaled coefficient s*c and integral i
4951 * upto which the integral is used instead of the scaled real coefficient */
4952 )
4953{
4954 SCIP_COL* col;
4955 SCIP_Real val;
4956 SCIP_Real newval;
4957 SCIP_Real intval;
4958 SCIP_Real mindelta;
4959 SCIP_Real maxdelta;
4960 SCIP_Real lb;
4961 SCIP_Real ub;
4962 SCIP_Bool mindeltainf;
4963 SCIP_Bool maxdeltainf;
4964 int oldlen;
4965 int c;
4966
4967 assert(row != NULL);
4968 assert(row->len == 0 || row->cols != NULL);
4969 assert(row->len == 0 || row->vals != NULL);
4970 assert(SCIPsetIsPositive(set, scaleval));
4971 assert(-1.0 < minrounddelta && minrounddelta <= 0.0);
4972 assert(0.0 <= maxrounddelta && maxrounddelta < 1.0);
4973
4974 SCIPsetDebugMsg(set, "scale row <%s> with %g (tolerance=[%g,%g])\n", row->name, scaleval, minrounddelta, maxrounddelta);
4975
4976 mindelta = 0.0;
4977 maxdelta = 0.0;
4978 mindeltainf = FALSE;
4979 maxdeltainf = FALSE;
4980 oldlen = row->len;
4981
4982 /* scale the row coefficients, thereby recalculating whether the row's activity is always integral;
4983 * if the row coefficients are rounded to the nearest integer value, calculate the maximal activity difference,
4984 * this rounding can lead to
4985 */
4986 row->integral = TRUE;
4987
4988 c = 0;
4989 while( c < row->len )
4990 {
4991 col = row->cols[c];
4992 val = row->vals[c];
4993 assert(!SCIPsetIsZero(set, val));
4994
4995 /* get local or global bounds for column, depending on the local or global feasibility of the row */
4996 if( row->local )
4997 {
4998 lb = col->lb;
4999 ub = col->ub;
5000 }
5001 else
5002 {
5003 lb = SCIPvarGetLbGlobal(col->var);
5004 ub = SCIPvarGetUbGlobal(col->var);
5005 }
5006
5007 /* calculate scaled coefficient */
5008 newval = val * scaleval;
5009 if( (integralcontvars || SCIPcolIsIntegral(col) || SCIPsetIsIntegral(set, newval))
5010 && isIntegralScalar(val, scaleval, minrounddelta, maxrounddelta, &intval) )
5011 {
5012 if( !SCIPsetIsEQ(set, intval, newval) )
5013 {
5014 if( intval < newval )
5015 {
5016 mindelta += (intval - newval)*ub;
5017 maxdelta += (intval - newval)*lb;
5018 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, ub);
5019 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, -lb);
5020 }
5021 else
5022 {
5023 mindelta += (intval - newval)*lb;
5024 maxdelta += (intval - newval)*ub;
5025 mindeltainf = mindeltainf || SCIPsetIsInfinity(set, -lb);
5026 maxdeltainf = maxdeltainf || SCIPsetIsInfinity(set, ub);
5027 }
5028 }
5029 newval = intval;
5030 }
5031
5032 if( !SCIPsetIsEQ(set, val, newval) )
5033 {
5034 /* if column knows of the row, change the corresponding coefficient in the column */
5035 if( row->linkpos[c] >= 0 )
5036 {
5037 assert(col->rows[row->linkpos[c]] == row);
5038 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[c]], row->vals[c]));
5039 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[c], newval) );
5040 }
5041
5042 /* change the coefficient in the row, and update the norms and integrality status */
5043 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, c, newval) );
5044
5045 /* current coefficient has been deleted from the row because it was almost zero */
5046 if( oldlen != row->len )
5047 {
5048 assert(row->len == oldlen - 1);
5049 c--;
5050 oldlen = row->len;
5051 }
5052 }
5053 else
5054 row->integral = row->integral && SCIPcolIsIntegral(col) && SCIPsetIsIntegral(set, val);
5055
5056 ++c;
5057 }
5058
5059 /* scale the row sides, and move the constant to the sides; relax the sides with accumulated delta in order
5060 * to not destroy feasibility due to rounding
5061 */
5062 /**@todo ensure that returned cut does not have infinite lhs and rhs */
5063 if( !SCIPsetIsInfinity(set, -row->lhs) )
5064 {
5065 if( mindeltainf )
5066 newval = -SCIPsetInfinity(set);
5067 else
5068 {
5069 newval = (row->lhs - row->constant) * scaleval + mindelta;
5070 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5071 newval = SCIPsetSumCeil(set, newval);
5072 }
5073 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, newval) );
5074 }
5075 if( !SCIPsetIsInfinity(set, row->rhs) )
5076 {
5077 if( maxdeltainf )
5078 newval = SCIPsetInfinity(set);
5079 else
5080 {
5081 newval = (row->rhs - row->constant) * scaleval + maxdelta;
5082 if( SCIPsetIsIntegral(set, newval) || (row->integral && !row->modifiable) )
5083 newval = SCIPsetSumFloor(set, newval);
5084 }
5085 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, newval) );
5086 }
5087
5088 /* clear the row constant */
5089 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, 0.0) );
5090
5091 SCIPsetDebugMsg(set, "scaled row <%s> (integral: %u)\n", row->name, row->integral);
5092 debugRowPrint(set, row);
5093
5094#ifdef SCIP_DEBUG
5095 /* check integrality status of row */
5096 for( c = 0; c < row->len && SCIPcolIsIntegral(row->cols[c]) && SCIPsetIsIntegral(set, row->vals[c]); ++c )
5097 {}
5098 assert(row->integral == (c == row->len));
5099#endif
5100
5101 /* invalid the activity */
5102 row->validactivitylp = -1;
5103
5104 return SCIP_OKAY;
5105}
5106
5107/** creates and captures an LP row */
5109 SCIP_ROW** row, /**< pointer to LP row data */
5110 BMS_BLKMEM* blkmem, /**< block memory */
5111 SCIP_SET* set, /**< global SCIP settings */
5112 SCIP_STAT* stat, /**< problem statistics */
5113 const char* name, /**< name of row */
5114 int len, /**< number of nonzeros in the row */
5115 SCIP_COL** cols, /**< array with columns of row entries */
5116 SCIP_Real* vals, /**< array with coefficients of row entries */
5117 SCIP_Real lhs, /**< left hand side of row */
5118 SCIP_Real rhs, /**< right hand side of row */
5119 SCIP_ROWORIGINTYPE origintype, /**< type of origin of row */
5120 void* origin, /**< pointer to constraint handler or separator who created the row (NULL if unkown) */
5121 SCIP_Bool local, /**< is row only valid locally? */
5122 SCIP_Bool modifiable, /**< is row modifiable during node processing (subject to column generation)? */
5123 SCIP_Bool removable /**< should the row be removed from the LP due to aging or cleanup? */
5124 )
5125{
5126 assert(row != NULL);
5127 assert(blkmem != NULL);
5128 assert(stat != NULL);
5129 assert(len >= 0);
5130 assert(len == 0 || (cols != NULL && vals != NULL));
5131 /* note, that the assert tries to avoid numerical troubles in the LP solver.
5132 * in case, for example, lhs > rhs but they are equal with tolerances, one could pass lhs=rhs=lhs+rhs/2 to
5133 * SCIProwCreate() (see cons_linear.c: detectRedundantConstraints())
5134 */
5135 assert(lhs <= rhs);
5136
5137 SCIP_ALLOC( BMSallocBlockMemory(blkmem, row) );
5138
5139 (*row)->integral = TRUE;
5140 if( len > 0 )
5141 {
5142 SCIP_VAR* var;
5143 int i;
5144
5145 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->cols, cols, len) );
5146 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->vals, vals, len) );
5147 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->cols_index, len) );
5148 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*row)->linkpos, len) );
5149
5150 for( i = 0; i < len; ++i )
5151 {
5152 assert(cols[i] != NULL);
5153 assert(!SCIPsetIsZero(set, vals[i]));
5154
5155 var = cols[i]->var;
5156 (*row)->cols_index[i] = cols[i]->index;
5157 (*row)->linkpos[i] = -1;
5158 if( SCIPsetIsIntegral(set, (*row)->vals[i]) )
5159 {
5160 (*row)->vals[i] = SCIPsetRound(set, (*row)->vals[i]);
5161 (*row)->integral = (*row)->integral && SCIPvarIsIntegral(var);
5162 }
5163 else
5164 {
5165 (*row)->integral = FALSE;
5166 }
5167 }
5168 }
5169 else
5170 {
5171 (*row)->cols = NULL;
5172 (*row)->cols_index = NULL;
5173 (*row)->vals = NULL;
5174 (*row)->linkpos = NULL;
5175 }
5176
5177 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*row)->name, name, strlen(name)+1) );
5178 (*row)->constant = 0.0;
5179 (*row)->lhs = lhs;
5180 (*row)->rhs = rhs;
5181 (*row)->flushedlhs = -SCIPsetInfinity(set);
5182 (*row)->flushedrhs = SCIPsetInfinity(set);
5183 (*row)->sqrnorm = 0.0;
5184 (*row)->sumnorm = 0.0;
5185 (*row)->objprod = 0.0;
5186 (*row)->maxval = 0.0;
5187 (*row)->minval = SCIPsetInfinity(set);
5188 (*row)->dualsol = 0.0;
5189 (*row)->activity = SCIP_INVALID;
5190 (*row)->dualfarkas = 0.0;
5191 (*row)->pseudoactivity = SCIP_INVALID;
5192 (*row)->minactivity = SCIP_INVALID;
5193 (*row)->maxactivity = SCIP_INVALID;
5194 (*row)->origin = origin;
5195 (*row)->eventfilter = NULL;
5196 (*row)->index = stat->nrowidx;
5197 SCIPstatIncrement(stat, set, nrowidx);
5198 (*row)->size = len;
5199 (*row)->len = len;
5200 (*row)->nlpcols = 0;
5201 (*row)->nunlinked = len;
5202 (*row)->nuses = 0;
5203 (*row)->lppos = -1;
5204 (*row)->lpipos = -1;
5205 (*row)->lpdepth = -1;
5206 (*row)->minidx = INT_MAX;
5207 (*row)->maxidx = INT_MIN;
5208 (*row)->nummaxval = 0;
5209 (*row)->numminval = 0;
5210 (*row)->numintcols = -1;
5211 (*row)->validactivitylp = -1;
5212 (*row)->validpsactivitydomchg = -1;
5213 (*row)->validactivitybdsdomchg = -1;
5214 (*row)->nlpsaftercreation = 0L;
5215 (*row)->activeinlpcounter = 0L;
5216 (*row)->age = 0;
5217 (*row)->rank = 0;
5218 (*row)->obsoletenode = -1;
5219 (*row)->fromcutpool = FALSE;
5220 (*row)->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
5221 (*row)->lpcolssorted = TRUE;
5222 (*row)->nonlpcolssorted = (len <= 1);
5223 (*row)->delaysort = FALSE;
5224 (*row)->validminmaxidx = FALSE;
5225 (*row)->lhschanged = FALSE;
5226 (*row)->rhschanged = FALSE;
5227 (*row)->coefchanged = FALSE;
5228 (*row)->local = local;
5229 (*row)->modifiable = modifiable;
5230 (*row)->nlocks = 0;
5231 (*row)->origintype = origintype; /*lint !e641*/
5232 (*row)->removable = removable;
5233 (*row)->inglobalcutpool = FALSE;
5234 (*row)->storedsolvals = NULL;
5235
5236 /* calculate row norms and min/maxidx, and check if row is sorted */
5237 rowCalcNorms(*row, set);
5238
5239 /* capture the row */
5240 SCIProwCapture(*row);
5241
5242 /* create event filter */
5243 SCIP_CALL( SCIPeventfilterCreate(&(*row)->eventfilter, blkmem) );
5244
5245 /* capture origin constraint if available */
5246 if( origintype == SCIP_ROWORIGINTYPE_CONS )
5247 {
5248 SCIP_CONS* cons = (SCIP_CONS*) origin;
5249 assert(cons != NULL);
5250 SCIPconsCapture(cons);
5251 }
5252
5253 return SCIP_OKAY;
5254} /*lint !e715*/
5255
5256/** frees an LP row */
5258 SCIP_ROW** row, /**< pointer to LP row */
5259 BMS_BLKMEM* blkmem, /**< block memory */
5260 SCIP_SET* set, /**< global SCIP settings */
5261 SCIP_LP* lp /**< current LP data */
5262 )
5263{
5264 assert(blkmem != NULL);
5265 assert(row != NULL);
5266 assert(*row != NULL);
5267 assert((*row)->nuses == 0);
5268 assert((*row)->lppos == -1);
5269 assert((*row)->eventfilter != NULL);
5270
5271 /* release constraint that has been used for creating the row */
5272 if( (SCIP_ROWORIGINTYPE) (*row)->origintype == SCIP_ROWORIGINTYPE_CONS )
5273 {
5274 SCIP_CONS* cons = (SCIP_CONS*) (*row)->origin;
5275 assert(cons != NULL);
5276 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) );
5277 }
5278
5279 /* remove column indices from corresponding rows */
5280 SCIP_CALL( rowUnlink(*row, set, lp) );
5281
5282 /* free event filter */
5283 SCIP_CALL( SCIPeventfilterFree(&(*row)->eventfilter, blkmem, set) );
5284
5285 BMSfreeBlockMemoryNull(blkmem, &(*row)->storedsolvals);
5286 BMSfreeBlockMemoryArray(blkmem, &(*row)->name, strlen((*row)->name)+1);
5287 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols, (*row)->size);
5288 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->cols_index, (*row)->size);
5289 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->vals, (*row)->size);
5290 BMSfreeBlockMemoryArrayNull(blkmem, &(*row)->linkpos, (*row)->size);
5291 BMSfreeBlockMemory(blkmem, row);
5292
5293 return SCIP_OKAY;
5294}
5295
5296/** output row to file stream */
5298 SCIP_ROW* row, /**< LP row */
5299 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
5300 FILE* file /**< output file (or NULL for standard output) */
5301 )
5302{
5303 int i;
5304
5305 assert(row != NULL);
5306
5307 /* print row name */
5308 if( row->name != NULL && row->name[0] != '\0' )
5309 {
5310 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", row->name);
5311 }
5312
5313 /* print left hand side */
5314 SCIPmessageFPrintInfo(messagehdlr, file, "%.15g <= ", row->lhs);
5315
5316 /* print coefficients */
5317 if( row->len == 0 )
5318 SCIPmessageFPrintInfo(messagehdlr, file, "0 ");
5319 for( i = 0; i < row->len; ++i )
5320 {
5321 assert(row->cols[i] != NULL);
5322 assert(row->cols[i]->var != NULL);
5323 assert(SCIPvarGetName(row->cols[i]->var) != NULL);
5324 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
5325 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", row->vals[i], SCIPvarGetName(row->cols[i]->var));
5326 }
5327
5328 /* print constant */
5330 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g ", row->constant);
5331
5332 /* print right hand side */
5333 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g\n", row->rhs);
5334}
5335
5336/** increases usage counter of LP row */
5338 SCIP_ROW* row /**< LP row */
5339 )
5340{
5341 assert(row != NULL);
5342 assert(row->nuses >= 0);
5343 assert(row->nlocks <= (unsigned int)(row->nuses)); /*lint !e574*/
5344
5345 SCIPdebugMessage("capture row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5346 row->nuses++;
5347}
5348
5349/** decreases usage counter of LP row, and frees memory if necessary */
5351 SCIP_ROW** row, /**< pointer to LP row */
5352 BMS_BLKMEM* blkmem, /**< block memory */
5353 SCIP_SET* set, /**< global SCIP settings */
5354 SCIP_LP* lp /**< current LP data */
5355 )
5356{
5357 assert(blkmem != NULL);
5358 assert(row != NULL);
5359 assert(*row != NULL);
5360 assert((*row)->nuses >= 1);
5361 assert((*row)->nlocks < (unsigned int)((*row)->nuses)); /*lint !e574*/
5362
5363 SCIPsetDebugMsg(set, "release row <%s> with nuses=%d and nlocks=%u\n", (*row)->name, (*row)->nuses, (*row)->nlocks);
5364 (*row)->nuses--;
5365 if( (*row)->nuses == 0 )
5366 {
5367 SCIP_CALL( SCIProwFree(row, blkmem, set, lp) );
5368 }
5369
5370 *row = NULL;
5371
5372 return SCIP_OKAY;
5373}
5374
5375/** locks an unmodifiable row, which forbids further changes; has no effect on modifiable rows */
5377 SCIP_ROW* row /**< LP row */
5378 )
5379{
5380 assert(row != NULL);
5381
5382 /* check, if row is modifiable */
5383 if( !row->modifiable )
5384 {
5385 SCIPdebugMessage("lock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5386 row->nlocks++;
5387 }
5388}
5389
5390/** unlocks a lock of an unmodifiable row; a row with no sealed lock may be modified; has no effect on modifiable rows */
5392 SCIP_ROW* row /**< LP row */
5393 )
5394{
5395 assert(row != NULL);
5396
5397 /* check, if row is modifiable */
5398 if( !row->modifiable )
5399 {
5400 SCIPdebugMessage("unlock row <%s> with nuses=%d and nlocks=%u\n", row->name, row->nuses, row->nlocks);
5401 assert(row->nlocks > 0);
5402 row->nlocks--;
5403 }
5404}
5405
5406/** adds a previously non existing coefficient to an LP row */
5408 SCIP_ROW* row, /**< LP row */
5409 BMS_BLKMEM* blkmem, /**< block memory */
5410 SCIP_SET* set, /**< global SCIP settings */
5411 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5412 SCIP_LP* lp, /**< current LP data */
5413 SCIP_COL* col, /**< LP column */
5414 SCIP_Real val /**< value of coefficient */
5415 )
5416{
5417 assert(lp != NULL);
5418 assert(!lp->diving || row->lppos == -1);
5419
5420 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5421
5422 checkLinks(lp);
5423
5424 return SCIP_OKAY;
5425}
5426
5427/** deletes coefficient from row */
5429 SCIP_ROW* row, /**< row to be changed */
5430 BMS_BLKMEM* blkmem, /**< block memory */
5431 SCIP_SET* set, /**< global SCIP settings */
5432 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5433 SCIP_LP* lp, /**< current LP data */
5434 SCIP_COL* col /**< coefficient to be deleted */
5435 )
5436{
5437 int pos;
5438
5439 assert(row != NULL);
5440 assert(!row->delaysort);
5441 assert(lp != NULL);
5442 assert(!lp->diving || row->lppos == -1);
5443 assert(col != NULL);
5444 assert(col->var != NULL);
5445
5446 /* search the position of the column in the row's col vector */
5447 pos = rowSearchCoef(row, col);
5448 if( pos == -1 )
5449 {
5450 SCIPerrorMessage("coefficient for column <%s> doesn't exist in row <%s>\n", SCIPvarGetName(col->var), row->name);
5451 return SCIP_INVALIDDATA;
5452 }
5453 assert(0 <= pos && pos < row->len);
5454 assert(row->cols[pos] == col);
5455 assert(row->cols_index[pos] == col->index);
5456
5457 /* if column knows of the row, remove the row from the column's row vector */
5458 if( row->linkpos[pos] >= 0 )
5459 {
5460 assert(col->rows[row->linkpos[pos]] == row);
5461 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5462 SCIP_CALL( colDelCoefPos(col, set, lp, row->linkpos[pos]) );
5463 }
5464
5465 /* delete the column from the row's col vector */
5466 SCIP_CALL( rowDelCoefPos(row, blkmem, set, eventqueue, lp, pos) );
5467
5468 checkLinks(lp);
5469
5470 return SCIP_OKAY;
5471}
5472
5473/** changes or adds a coefficient to an LP row */
5475 SCIP_ROW* row, /**< LP row */
5476 BMS_BLKMEM* blkmem, /**< block memory */
5477 SCIP_SET* set, /**< global SCIP settings */
5478 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5479 SCIP_LP* lp, /**< current LP data */
5480 SCIP_COL* col, /**< LP column */
5481 SCIP_Real val /**< value of coefficient */
5482 )
5483{
5484 int pos;
5485
5486 assert(row != NULL);
5487 assert(!row->delaysort);
5488 assert(lp != NULL);
5489 assert(!lp->diving || row->lppos == -1);
5490 assert(col != NULL);
5491
5492 /* search the position of the column in the row's col vector */
5493 pos = rowSearchCoef(row, col);
5494
5495 /* check, if column already exists in the row's col vector */
5496 if( pos == -1 )
5497 {
5498 /* add previously not existing coefficient */
5499 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, val, -1) );
5500 }
5501 else
5502 {
5503 /* modify already existing coefficient */
5504 assert(0 <= pos && pos < row->len);
5505 assert(row->cols[pos] == col);
5506 assert(row->cols_index[pos] == col->index);
5507
5508 /* if column knows of the row, change the corresponding coefficient in the column */
5509 if( row->linkpos[pos] >= 0 )
5510 {
5511 assert(col->rows[row->linkpos[pos]] == row);
5512 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5513 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], val) );
5514 }
5515
5516 /* change the coefficient in the row */
5517 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, val) );
5518 }
5519
5520 checkLinks(lp);
5521
5522 return SCIP_OKAY;
5523}
5524
5525/** increases value of an existing or non-existing coefficient in an LP row */
5527 SCIP_ROW* row, /**< LP row */
5528 BMS_BLKMEM* blkmem, /**< block memory */
5529 SCIP_SET* set, /**< global SCIP settings */
5530 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5531 SCIP_LP* lp, /**< current LP data */
5532 SCIP_COL* col, /**< LP column */
5533 SCIP_Real incval /**< value to add to the coefficient */
5534 )
5535{
5536 int pos;
5537
5538 assert(row != NULL);
5539 assert(lp != NULL);
5540 assert(!lp->diving || row->lppos == -1);
5541 assert(col != NULL);
5542
5543 if( SCIPsetIsZero(set, incval) )
5544 return SCIP_OKAY;
5545
5546 /* search the position of the column in the row's col vector */
5547 pos = rowSearchCoef(row, col);
5548
5549 /* check, if column already exists in the row's col vector */
5550 if( pos == -1 )
5551 {
5552 /* coefficient doesn't exist, or sorting is delayed: add coefficient to the end of the row's arrays */
5553 SCIP_CALL( rowAddCoef(row, blkmem, set, eventqueue, lp, col, incval, -1) );
5554 }
5555 else
5556 {
5557 /* modify already existing coefficient */
5558 assert(0 <= pos && pos < row->len);
5559 assert(row->cols[pos] == col);
5560 assert(row->cols_index[pos] == col->index);
5561
5562 /* if column knows of the row, change the corresponding coefficient in the column */
5563 if( row->linkpos[pos] >= 0 )
5564 {
5565 assert(col->rows[row->linkpos[pos]] == row);
5566 assert(SCIPsetIsEQ(set, col->vals[row->linkpos[pos]], row->vals[pos]));
5567 SCIP_CALL( colChgCoefPos(col, set, lp, row->linkpos[pos], row->vals[pos] + incval) );
5568 }
5569
5570 /* change the coefficient in the row */
5571 SCIP_CALL( rowChgCoefPos(row, blkmem, set, eventqueue, lp, pos, row->vals[pos] + incval) );
5572 }
5573
5574 checkLinks(lp);
5575
5576 /* invalid the activity */
5577 row->validactivitylp = -1;
5578
5579 return SCIP_OKAY;
5580}
5581
5582/** changes constant value of a row */
5584 SCIP_ROW* row, /**< LP row */
5585 BMS_BLKMEM* blkmem, /**< block memory */
5586 SCIP_SET* set, /**< global SCIP settings */
5587 SCIP_STAT* stat, /**< problem statistics */
5588 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5589 SCIP_LP* lp, /**< current LP data */
5590 SCIP_Real constant /**< new constant value */
5591 )
5592{
5593 assert(row != NULL);
5594 assert(row->lhs <= row->rhs);
5595 assert(!SCIPsetIsInfinity(set, REALABS(constant)));
5596 assert(stat != NULL);
5597 assert(lp != NULL);
5598 assert(!lp->diving || row->lppos == -1);
5599
5600 if( !SCIPsetIsEQ(set, constant, row->constant) )
5601 {
5602 SCIP_Real oldconstant;
5603
5604 if( row->validpsactivitydomchg == stat->domchgcount )
5605 {
5606 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
5607 row->pseudoactivity += constant - row->constant;
5608 }
5609 if( row->validactivitybdsdomchg == stat->domchgcount )
5610 {
5611 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
5612 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
5613 row->minactivity += constant - row->constant;
5614 row->maxactivity += constant - row->constant;
5615 }
5616
5617 if( !SCIPsetIsInfinity(set, -row->lhs) )
5618 {
5620 }
5621 if( !SCIPsetIsInfinity(set, row->rhs) )
5622 {
5624 }
5625
5626 oldconstant = row->constant;
5627
5628 row->constant = constant;
5629
5630 /* issue row constant changed event */
5631 SCIP_CALL( rowEventConstantChanged(row, blkmem, set, eventqueue, oldconstant, constant) );
5632 }
5633
5634 return SCIP_OKAY;
5635}
5636
5637/** add constant value to a row */
5639 SCIP_ROW* row, /**< LP row */
5640 BMS_BLKMEM* blkmem, /**< block memory */
5641 SCIP_SET* set, /**< global SCIP settings */
5642 SCIP_STAT* stat, /**< problem statistics */
5643 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5644 SCIP_LP* lp, /**< current LP data */
5645 SCIP_Real addval /**< constant value to add to the row */
5646 )
5647{
5648 assert(row != NULL);
5649 assert(row->lhs <= row->rhs);
5650 assert(!SCIPsetIsInfinity(set, REALABS(addval)));
5651 assert(stat != NULL);
5652 assert(lp != NULL);
5653 assert(!lp->diving || row->lppos == -1);
5654
5655 if( !SCIPsetIsZero(set, addval) )
5656 {
5657 SCIP_CALL( SCIProwChgConstant(row, blkmem, set, stat, eventqueue, lp, row->constant + addval) );
5658 }
5659
5660 return SCIP_OKAY;
5661}
5662
5663/** changes left hand side of LP row */
5665 SCIP_ROW* row, /**< LP row */
5666 BMS_BLKMEM* blkmem, /**< block memory */
5667 SCIP_SET* set, /**< global SCIP settings */
5668 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5669 SCIP_LP* lp, /**< current LP data */
5670 SCIP_Real lhs /**< new left hand side */
5671 )
5672{
5673 assert(row != NULL);
5674 assert(lp != NULL);
5675
5676 if( !SCIPsetIsEQ(set, row->lhs, lhs) )
5677 {
5678 SCIP_Real oldlhs;
5679
5680 oldlhs = row->lhs;
5681
5682 row->lhs = lhs;
5684
5685 if( !lp->diving )
5686 {
5687 /* issue row side changed event */
5688 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_LEFT, oldlhs, lhs) );
5689 }
5690 }
5691
5692 return SCIP_OKAY;
5693}
5694
5695/** changes right hand side of LP row */
5697 SCIP_ROW* row, /**< LP row */
5698 BMS_BLKMEM* blkmem, /**< block memory */
5699 SCIP_SET* set, /**< global SCIP settings */
5700 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5701 SCIP_LP* lp, /**< current LP data */
5702 SCIP_Real rhs /**< new right hand side */
5703 )
5704{
5705 assert(row != NULL);
5706 assert(lp != NULL);
5707
5708 if( !SCIPsetIsEQ(set, row->rhs, rhs) )
5709 {
5710 SCIP_Real oldrhs;
5711
5712 oldrhs = row->rhs;
5713
5714 row->rhs = rhs;
5716
5717 if( !lp->diving )
5718 {
5719 /* issue row side changed event */
5720 SCIP_CALL( rowEventSideChanged(row, blkmem, set, eventqueue, SCIP_SIDETYPE_RIGHT, oldrhs, rhs) );
5721 }
5722 }
5723
5724 return SCIP_OKAY;
5725}
5726
5727/** changes the local flag of LP row */
5729 SCIP_ROW* row, /**< LP row */
5730 SCIP_Bool local /**< new value for local flag */
5731 )
5732{
5733 assert(row != NULL);
5734
5735 row->local = local;
5736
5737 return SCIP_OKAY;
5738}
5739
5740/** additional scalars that are tried in integrality scaling */
5741static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
5742static const int nscalars = 9;
5743
5744/** tries to find a value, such that all row coefficients, if scaled with this value become integral */
5746 SCIP_ROW* row, /**< LP row */
5747 SCIP_SET* set, /**< global SCIP settings */
5748 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5749 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5750 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5751 SCIP_Real maxscale, /**< maximal allowed scalar */
5752 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5753 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
5754 SCIP_Bool* success /**< stores whether returned value is valid */
5755 )
5756{
5757#ifndef NDEBUG
5758 SCIP_COL* col;
5759#endif
5760 SCIP_Longint gcd;
5761 SCIP_Longint scm;
5762 SCIP_Longint numerator;
5763 SCIP_Longint denominator;
5764 SCIP_Real val;
5765 SCIP_Real absval;
5766 SCIP_Real minval;
5767 SCIP_Real scaleval;
5768 SCIP_Real twomultval;
5769 SCIP_Bool scalable;
5770 SCIP_Bool twomult;
5771 SCIP_Bool rational;
5772 int c;
5773 int s;
5774
5775 /**@todo call misc.c:SCIPcalcIntegralScalar() instead - if usecontvars == FALSE, filter the integer variables first */
5776 assert(row != NULL);
5777 assert(row->len == 0 || row->cols != NULL);
5778 assert(row->len == 0 || row->cols_index != NULL);
5779 assert(row->len == 0 || row->vals != NULL);
5780 assert(maxdnom >= 1);
5781 assert(mindelta < 0.0);
5782 assert(maxdelta > 0.0);
5783 assert(success != NULL);
5784
5785 SCIPsetDebugMsg(set, "trying to find rational representation for row <%s> (contvars: %u)\n", SCIProwGetName(row), usecontvars);
5786 SCIPdebug( val = 0; ); /* avoid warning "val might be used uninitialized; see SCIPdebugMessage lastval=%g below */
5787
5788 if( intscalar != NULL )
5789 *intscalar = SCIP_INVALID;
5790 *success = FALSE;
5791
5792 /* get minimal absolute non-zero value */
5793 minval = SCIP_REAL_MAX;
5794 for( c = 0; c < row->len; ++c )
5795 {
5796#ifndef NDEBUG
5797 col = row->cols[c];
5798 assert(col != NULL);
5799 assert(col->var != NULL);
5801 assert(SCIPvarGetCol(col->var) == col);
5802#endif
5803 val = row->vals[c];
5804 assert(!SCIPsetIsZero(set, val));
5805
5806 if( val < mindelta || val > maxdelta )
5807 {
5808 absval = REALABS(val);
5809 minval = MIN(minval, absval);
5810 }
5811 }
5812 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
5813 {
5814 /* all coefficients are zero (inside tolerances) */
5815 if( intscalar != NULL )
5816 *intscalar = 1.0;
5817 *success = TRUE;
5818 SCIPsetDebugMsg(set, " -> all values are zero (inside tolerances)\n");
5819
5820 return SCIP_OKAY;
5821 }
5822 assert(minval > MIN(-mindelta, maxdelta));
5823 assert(SCIPsetIsPositive(set, minval));
5824 assert(!SCIPsetIsInfinity(set, minval));
5825
5826 /* try, if row coefficients can be made integral by multiplying them with the reciprocal of the smallest coefficient
5827 * and a power of 2
5828 */
5829 scaleval = 1.0/minval;
5830 scalable = (scaleval <= maxscale);
5831 for( c = 0; c < row->len && scalable; ++c )
5832 {
5833 /* don't look at continuous variables, if we don't have to */
5834 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5835 continue;
5836
5837 /* check, if the coefficient can be scaled with a simple scalar */
5838 val = row->vals[c];
5839 absval = REALABS(val);
5840 while( scaleval <= maxscale
5841 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta, NULL)) )
5842 {
5843 for( s = 0; s < nscalars; ++s )
5844 {
5845 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta, NULL) )
5846 {
5847 scaleval *= scalars[s];
5848 break;
5849 }
5850 }
5851 if( s >= nscalars )
5852 scaleval *= 2.0;
5853 }
5854 scalable = (scaleval <= maxscale);
5855 SCIPsetDebugMsg(set, " -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n", val, scaleval, val*scaleval, scalable);
5856 }
5857 if( scalable )
5858 {
5859 /* make row coefficients integral by dividing them by the smallest coefficient
5860 * (and multiplying them with a power of 2)
5861 */
5862 assert(scaleval <= maxscale);
5863 if( intscalar != NULL )
5864 *intscalar = scaleval;
5865 *success = TRUE;
5866 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (minval=%g)\n", scaleval, minval);
5867
5868 return SCIP_OKAY;
5869 }
5870
5871 /* try, if row coefficients can be made integral by multiplying them by a power of 2 */
5872 twomultval = 1.0;
5873 twomult = (twomultval <= maxscale);
5874 for( c = 0; c < row->len && twomult; ++c )
5875 {
5876 /* don't look at continuous variables, if we don't have to */
5877 if( !usecontvars && !SCIPcolIsIntegral(row->cols[c]) )
5878 continue;
5879
5880 /* check, if the coefficient can be scaled with a simple scalar */
5881 val = row->vals[c];
5882 absval = REALABS(val);
5883 while( twomultval <= maxscale
5884 && (absval * twomultval < 0.5 || !isIntegralScalar(val, twomultval, mindelta, maxdelta, NULL)) )
5885 {
5886 for( s = 0; s < nscalars; ++s )
5887 {
5888 if( isIntegralScalar(val, twomultval * scalars[s], mindelta, maxdelta, NULL) )
5889 {
5890 twomultval *= scalars[s];
5891 break;
5892 }
5893 }
5894 if( s >= nscalars )
5895 twomultval *= 2.0;
5896 }
5897 twomult = (twomultval <= maxscale);
5898 SCIPsetDebugMsg(set, " -> val=%g, twomult=%g, val*twomult=%g, twomultable=%u\n",
5899 val, twomultval, val*twomultval, twomult);
5900 }
5901 if( twomult )
5902 {
5903 /* make row coefficients integral by multiplying them with a power of 2 */
5904 assert(twomultval <= maxscale);
5905 if( intscalar != NULL )
5906 *intscalar = twomultval;
5907 *success = TRUE;
5908 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (power of 2)\n", twomultval);
5909
5910 return SCIP_OKAY;
5911 }
5912
5913 /* convert each coefficient into a rational number, calculate the greatest common divisor of the numerators
5914 * and the smallest common multiple of the denominators
5915 */
5916 gcd = 1;
5917 scm = 1;
5918 rational = (maxdnom > 1);
5919
5920 /* first coefficient (to initialize gcd) */
5921 for( c = 0; c < row->len && rational; ++c )
5922 {
5923 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5924 {
5925 val = row->vals[c];
5926 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
5927 if( rational && numerator != 0 )
5928 {
5929 assert(denominator > 0);
5930 gcd = ABS(numerator);
5931 scm = denominator;
5932 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5933 SCIPsetDebugMsg(set, " -> first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5934 val, numerator, denominator, gcd, scm, rational);
5935 break;
5936 }
5937 }
5938 }
5939
5940 /* remaining coefficients */
5941 for( ++c; c < row->len && rational; ++c )
5942 {
5943 if( usecontvars || SCIPcolIsIntegral(row->cols[c]) )
5944 {
5945 val = row->vals[c];
5946 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
5947 if( rational && numerator != 0 )
5948 {
5949 assert(denominator > 0);
5950 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
5951 scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
5952 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5953 SCIPsetDebugMsg(set, " -> next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
5954 val, numerator, denominator, gcd, scm, rational);
5955 }
5956 }
5957 }
5958
5959 if( rational )
5960 {
5961 /* make row coefficients integral by multiplying them with the smallest common multiple of the denominators */
5962 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
5963 if( intscalar != NULL )
5964 *intscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
5965 *success = TRUE;
5966 SCIPsetDebugMsg(set, " -> integrality can be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
5967 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
5968 }
5969 else
5970 {
5971 assert(!(*success));
5972 SCIPsetDebugMsg(set, " -> rationalizing failed: gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", lastval=%g\n", gcd, scm, val); /*lint !e771*/
5973 }
5974
5975 return SCIP_OKAY;
5976}
5977
5978/** tries to scale row, s.t. all coefficients become integral */
5980 SCIP_ROW* row, /**< LP row */
5981 BMS_BLKMEM* blkmem, /**< block memory */
5982 SCIP_SET* set, /**< global SCIP settings */
5983 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5984 SCIP_STAT* stat, /**< problem statistics */
5985 SCIP_LP* lp, /**< current LP data */
5986 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
5987 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
5988 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
5989 SCIP_Real maxscale, /**< maximal value to scale row with */
5990 SCIP_Bool usecontvars, /**< should the coefficients of the continuous variables also be made integral? */
5991 SCIP_Bool* success /**< stores whether row could be made rational */
5992 )
5993{
5994 SCIP_Real intscalar;
5995
5996 assert(success != NULL);
5997
5998 /* calculate scalar to make coefficients integral */
5999 SCIP_CALL( SCIProwCalcIntegralScalar(row, set, mindelta, maxdelta, maxdnom, maxscale, usecontvars,
6000 &intscalar, success) );
6001
6002 if( *success )
6003 {
6004 /* scale the row */
6005 SCIP_CALL( rowScale(row, blkmem, set, eventqueue, stat, lp, intscalar, usecontvars, mindelta, maxdelta) );
6006 }
6007
6008 return SCIP_OKAY;
6009}
6010
6011/** sorts row entries such that LP columns precede non-LP columns and inside both parts lower column indices precede
6012 * higher ones
6013 */
6015 SCIP_ROW* row /**< row to be sorted */
6016 )
6017{
6018 assert(row != NULL);
6019
6020 /* sort LP columns */
6021 rowSortLP(row);
6022
6023 /* sort non-LP columns */
6024 rowSortNonLP(row);
6025
6026#ifdef SCIP_MORE_DEBUG
6027 /* check the sorting */
6028 {
6029 int c;
6030 if( !row->delaysort )
6031 {
6032 for( c = 1; c < row->nlpcols; ++c )
6033 assert(row->cols[c]->index >= row->cols[c-1]->index);
6034 for( c = row->nlpcols + 1; c < row->len; ++c )
6035 assert(row->cols[c]->index >= row->cols[c-1]->index);
6036 }
6037 }
6038#endif
6039}
6040
6041/** sorts row, and merges equal column entries (resulting from lazy sorting and adding) into a single entry; removes
6042 * zero entries from row
6043 * the row must not be linked to the columns; otherwise, we would need to update the columns as
6044 * well, which is too expensive
6045 */
6046static
6048 SCIP_ROW* row, /**< row to be sorted */
6049 SCIP_SET* set /**< global SCIP settings */
6050 )
6051{
6052 assert(row != NULL);
6053 assert(!row->delaysort);
6054 assert(row->nunlinked == row->len);
6055 assert(row->nlpcols == 0);
6056
6057 SCIPsetDebugMsg(set, "merging row <%s>\n", row->name);
6058
6059 /* do nothing on empty rows; if row is sorted, nothing has to be done */
6060 if( row->len > 0 && (!row->lpcolssorted || !row->nonlpcolssorted) )
6061 {
6062 SCIP_COL** cols;
6063 int* cols_index;
6064 SCIP_Real* vals;
6065 int s;
6066 int t;
6067
6068 /* make sure, the row is sorted */
6069 SCIProwSort(row);
6070 assert(row->lpcolssorted);
6071 assert(row->nonlpcolssorted);
6072
6073 /* merge equal columns, thereby recalculating whether the row's activity is always integral */
6074 cols = row->cols;
6075 cols_index = row->cols_index;
6076 vals = row->vals;
6077 assert(cols != NULL);
6078 assert(cols_index != NULL);
6079 assert(vals != NULL);
6080
6081 t = 0;
6082 row->integral = TRUE;
6083 assert(!SCIPsetIsZero(set, vals[0]));
6084 assert(row->linkpos[0] == -1);
6085
6086 for( s = 1; s < row->len; ++s )
6087 {
6088 assert(!SCIPsetIsZero(set, vals[s]));
6089 assert(row->linkpos[s] == -1);
6090
6091 if( cols[s] == cols[t] )
6092 {
6093 /* merge entries with equal column */
6094 vals[t] += vals[s];
6095 }
6096 else
6097 {
6098 /* go to the next entry, overwriting current entry if coefficient is zero */
6099 if( !SCIPsetIsZero(set, vals[t]) )
6100 {
6101 /* in case the coefficient is integral w.r.t. numerics we explicitly round the coefficient to an integral value */
6102 vals[t] = SCIPsetIsIntegral(set, vals[t]) ? SCIPsetRound(set, vals[t]) : vals[t];
6103
6104 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6105 t++;
6106 }
6107 cols[t] = cols[s];
6108 cols_index[t] = cols_index[s];
6109 vals[t] = vals[s];
6110 }
6111 }
6112 if( !SCIPsetIsZero(set, vals[t]) )
6113 {
6114 row->integral = row->integral && SCIPcolIsIntegral(cols[t]) && SCIPsetIsIntegral(set, vals[t]);
6115 t++;
6116 }
6117 assert(s == row->len);
6118 assert(t <= row->len);
6119
6120 row->len = t;
6121 row->nunlinked = t;
6122
6123 /* if equal entries were merged, we have to recalculate the norms, since the squared Euclidean norm is wrong */
6124 if( t < s )
6125 rowCalcNorms(row, set);
6126 }
6127
6128#ifndef NDEBUG
6129 /* check for double entries */
6130 {
6131 int i;
6132 int j;
6133
6134 for( i = 0; i < row->len; ++i )
6135 {
6136 assert(row->cols[i] != NULL);
6137 assert(row->cols[i]->index == row->cols_index[i]);
6138 for( j = i+1; j < row->len; ++j )
6139 assert(row->cols[i] != row->cols[j]);
6140 }
6141 }
6142#endif
6143}
6144
6145/** enables delaying of row sorting */
6147 SCIP_ROW* row /**< LP row */
6148 )
6149{
6150 assert(row != NULL);
6151 assert(!row->delaysort);
6152
6153 row->delaysort = TRUE;
6154}
6155
6156/** disables delaying of row sorting, sorts row and merges coefficients with equal columns */
6158 SCIP_ROW* row, /**< LP row */
6159 SCIP_SET* set /**< global SCIP settings */
6160 )
6161{
6162 assert(row != NULL);
6163 assert(row->delaysort);
6164
6165 row->delaysort = FALSE;
6166 rowMerge(row, set);
6167}
6168
6169/** recalculates the current activity of a row */
6171 SCIP_ROW* row, /**< LP row */
6172 SCIP_STAT* stat /**< problem statistics */
6173 )
6174{
6175 SCIP_COL* col;
6176 int c;
6177
6178 assert(row != NULL);
6179 assert(stat != NULL);
6180
6181 row->activity = row->constant;
6182 for( c = 0; c < row->nlpcols; ++c )
6183 {
6184 col = row->cols[c];
6185 assert(col != NULL);
6186 assert(col->primsol != SCIP_INVALID); /*lint !e777*/
6187 assert(col->lppos >= 0);
6188 assert(row->linkpos[c] >= 0);
6189 row->activity += row->vals[c] * col->primsol;
6190 }
6191
6192 if( row->nunlinked > 0 )
6193 {
6194 for( c = row->nlpcols; c < row->len; ++c )
6195 {
6196 col = row->cols[c];
6197 assert(col != NULL);
6198 assert(col->lppos >= 0 || col->primsol == 0.0);
6199 assert(col->lppos == -1 || row->linkpos[c] == -1);
6200 if( col->lppos >= 0 )
6201 row->activity += row->vals[c] * col->primsol;
6202 }
6203 }
6204#ifndef NDEBUG
6205 else
6206 {
6207 for( c = row->nlpcols; c < row->len; ++c )
6208 {
6209 col = row->cols[c];
6210 assert(col != NULL);
6211 assert(col->primsol == 0.0);
6212 assert(col->lppos == -1);
6213 assert(row->linkpos[c] >= 0);
6214 }
6215 }
6216#endif
6217
6218 row->validactivitylp = stat->lpcount;
6219}
6220
6221/** returns the activity of a row in the current LP solution */
6223 SCIP_ROW* row, /**< LP row */
6224 SCIP_SET* set, /**< global SCIP settings */
6225 SCIP_STAT* stat, /**< problem statistics */
6226 SCIP_LP* lp /**< current LP data */
6227 )
6228{
6229 SCIP_Real inf;
6230 SCIP_Real activity;
6231
6232 assert(row != NULL);
6233 assert(stat != NULL);
6234 assert(lp != NULL);
6235 assert(row->validactivitylp <= stat->lpcount);
6236 assert(lp->validsollp == stat->lpcount);
6237
6238 if( row->validactivitylp != stat->lpcount )
6239 SCIProwRecalcLPActivity(row, stat);
6240 assert(row->validactivitylp == stat->lpcount);
6241 assert(row->activity != SCIP_INVALID); /*lint !e777*/
6242
6243 activity = row->activity;
6244 inf = SCIPsetInfinity(set);
6245 activity = MAX(activity, -inf);
6246 activity = MIN(activity, +inf);
6247
6248 return activity;
6249}
6250
6251/** returns the feasibility of a row in the current LP solution: negative value means infeasibility */
6253 SCIP_ROW* row, /**< LP row */
6254 SCIP_SET* set, /**< global SCIP settings */
6255 SCIP_STAT* stat, /**< problem statistics */
6256 SCIP_LP* lp /**< current LP data */
6257 )
6258{
6259 SCIP_Real activity;
6260
6261 assert(row != NULL);
6262
6263 activity = SCIProwGetLPActivity(row, set, stat, lp);
6264
6265 return MIN(row->rhs - activity, activity - row->lhs);
6266}
6267
6268/** returns the feasibility of a row in the relaxed solution solution: negative value means infeasibility
6269 *
6270 * @todo Implement calculation of activities similar to LPs.
6271 */
6273 SCIP_ROW* row, /**< LP row */
6274 SCIP_SET* set, /**< global SCIP settings */
6275 SCIP_STAT* stat /**< problem statistics */
6276 )
6277{
6278 SCIP_Real inf;
6279 SCIP_Real activity;
6280 SCIP_COL* col;
6281 int c;
6282
6283 assert( row != NULL );
6284 assert( stat != NULL );
6285
6286 activity = row->constant;
6287 for (c = 0; c < row->nlpcols; ++c)
6288 {
6289 col = row->cols[c];
6290 assert( col != NULL );
6291 assert( col->lppos >= 0 );
6292 assert( col->var != NULL );
6293 assert( row->linkpos[c] >= 0 );
6294 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6295 }
6296
6297 if ( row->nunlinked > 0 )
6298 {
6299 for (c = row->nlpcols; c < row->len; ++c)
6300 {
6301 col = row->cols[c];
6302 assert( col != NULL );
6303 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6304 if ( col->lppos >= 0 )
6305 {
6306 assert( col->var != NULL );
6307 activity += row->vals[c] * SCIPvarGetRelaxSol(col->var, set);
6308 }
6309 }
6310 }
6311#ifndef NDEBUG
6312 else
6313 {
6314 for (c = row->nlpcols; c < row->len; ++c)
6315 {
6316 col = row->cols[c];
6317 assert( col != NULL );
6318 assert( col->lppos == -1 );
6319 assert( row->linkpos[c] >= 0 );
6320 }
6321 }
6322#endif
6323 inf = SCIPsetInfinity(set);
6324 activity = MAX(activity, -inf);
6325 activity = MIN(activity, +inf);
6326
6327 return MIN(row->rhs - activity, activity - row->lhs);
6328}
6329
6330/** returns the feasibility of a row in the current NLP solution: negative value means infeasibility
6331 *
6332 * @todo Implement calculation of activities similar to LPs.
6333 */
6335 SCIP_ROW* row, /**< LP row */
6336 SCIP_SET* set, /**< global SCIP settings */
6337 SCIP_STAT* stat /**< problem statistics */
6338 )
6339{
6340 SCIP_Real inf;
6341 SCIP_Real activity;
6342 SCIP_COL* col;
6343 int c;
6344
6345 assert( row != NULL );
6346 assert( stat != NULL );
6347
6348 activity = row->constant;
6349 for (c = 0; c < row->nlpcols; ++c)
6350 {
6351 col = row->cols[c];
6352 assert( col != NULL );
6353 assert( col->lppos >= 0 );
6354 assert( col->var != NULL );
6355 assert( row->linkpos[c] >= 0 );
6356 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6357 }
6358
6359 if ( row->nunlinked > 0 )
6360 {
6361 for (c = row->nlpcols; c < row->len; ++c)
6362 {
6363 col = row->cols[c];
6364 assert( col != NULL );
6365 assert( col->lppos == -1 || row->linkpos[c] == -1 );
6366 if ( col->lppos >= 0 )
6367 {
6368 assert( col->var != NULL );
6369 activity += row->vals[c] * SCIPvarGetNLPSol(col->var);
6370 }
6371 }
6372 }
6373#ifndef NDEBUG
6374 else
6375 {
6376 for (c = row->nlpcols; c < row->len; ++c)
6377 {
6378 col = row->cols[c];
6379 assert( col != NULL );
6380 assert( col->lppos == -1 );
6381 assert( row->linkpos[c] >= 0 );
6382 }
6383 }
6384#endif
6385 inf = SCIPsetInfinity(set);
6386 activity = MAX(activity, -inf);
6387 activity = MIN(activity, +inf);
6388
6389 return MIN(row->rhs - activity, activity - row->lhs);
6390}
6391
6392/** calculates the current pseudo activity of a row */
6394 SCIP_ROW* row, /**< row data */
6395 SCIP_STAT* stat /**< problem statistics */
6396 )
6397{
6398 SCIP_COL* col;
6399 int i;
6400
6401 assert(row != NULL);
6402 assert(stat != NULL);
6403
6404 row->pseudoactivity = row->constant;
6405 for( i = 0; i < row->len; ++i )
6406 {
6407 col = row->cols[i];
6408 assert(col != NULL);
6409 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6410 assert(col->var != NULL);
6412
6413 row->pseudoactivity += SCIPcolGetBestBound(col) * row->vals[i];
6414 }
6416 assert(!row->integral || EPSISINT(row->pseudoactivity - row->constant, SCIP_DEFAULT_SUMEPSILON));
6417}
6418
6419/** returns the pseudo activity of a row in the current pseudo solution */
6421 SCIP_ROW* row, /**< LP row */
6422 SCIP_SET* set, /**< global SCIP settings */
6423 SCIP_STAT* stat /**< problem statistics */
6424 )
6425{
6426 SCIP_Real inf;
6427 SCIP_Real activity;
6428
6429 assert(row != NULL);
6430 assert(stat != NULL);
6431 assert(row->validpsactivitydomchg <= stat->domchgcount);
6432
6433 /* check, if pseudo activity has to be calculated */
6434 if( row->validpsactivitydomchg != stat->domchgcount )
6435 SCIProwRecalcPseudoActivity(row, stat);
6436 assert(row->validpsactivitydomchg == stat->domchgcount);
6437 assert(row->pseudoactivity != SCIP_INVALID); /*lint !e777*/
6438
6439 activity = row->pseudoactivity;
6440 inf = SCIPsetInfinity(set);
6441 activity = MAX(activity, -inf);
6442 activity = MIN(activity, +inf);
6443
6444 return activity;
6445}
6446
6447/** returns the pseudo feasibility of a row in the current pseudo solution: negative value means infeasibility */
6449 SCIP_ROW* row, /**< LP row */
6450 SCIP_SET* set, /**< global SCIP settings */
6451 SCIP_STAT* stat /**< problem statistics */
6452 )
6453{
6454 SCIP_Real pseudoactivity;
6455
6456 assert(row != NULL);
6457
6458 pseudoactivity = SCIProwGetPseudoActivity(row, set, stat);
6459
6460 return MIN(row->rhs - pseudoactivity, pseudoactivity - row->lhs);
6461}
6462
6463/** returns the activity of a row for a given solution */
6465 SCIP_ROW* row, /**< LP row */
6466 SCIP_SET* set, /**< global SCIP settings */
6467 SCIP_STAT* stat, /**< problem statistics data */
6468 SCIP_SOL* sol /**< primal CIP solution */
6469 )
6470{
6471 SCIP_COL* col;
6472 SCIP_Real inf;
6473 SCIP_Real activity;
6474 SCIP_Real solval;
6475 int i;
6476
6477 assert(row != NULL);
6478
6479 activity = row->constant;
6480 for( i = 0; i < row->len; ++i )
6481 {
6482 col = row->cols[i];
6483 assert(col != NULL);
6484 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6485 solval = SCIPsolGetVal(sol, set, stat, col->var);
6486 if( solval == SCIP_UNKNOWN ) /*lint !e777*/
6487 {
6488 if( SCIPsetIsInfinity(set, -row->lhs) )
6489 solval = (row->vals[i] >= 0.0 ? col->lb : col->ub);
6490 else if( SCIPsetIsInfinity(set, row->rhs) )
6491 solval = (row->vals[i] >= 0.0 ? col->ub : col->lb);
6492 else
6493 solval = (col->lb + col->ub)/2.0;
6494 }
6495 activity += row->vals[i] * solval;
6496 }
6497
6498 inf = SCIPsetInfinity(set);
6499 activity = MAX(activity, -inf);
6500 activity = MIN(activity, +inf);
6501
6502 return activity;
6503}
6504
6505/** returns the feasibility of a row for the given solution */
6507 SCIP_ROW* row, /**< LP row */
6508 SCIP_SET* set, /**< global SCIP settings */
6509 SCIP_STAT* stat, /**< problem statistics data */
6510 SCIP_SOL* sol /**< primal CIP solution */
6511 )
6512{
6513 SCIP_Real activity;
6514
6515 assert(row != NULL);
6516
6517 activity = SCIProwGetSolActivity(row, set, stat, sol);
6518
6519 return MIN(row->rhs - activity, activity - row->lhs);
6520}
6521
6522/** calculates minimal and maximal activity of row w.r.t. the column's bounds */
6523static
6525 SCIP_ROW* row, /**< row data */
6526 SCIP_SET* set, /**< global SCIP settings */
6527 SCIP_STAT* stat /**< problem statistics data */
6528 )
6529{
6530 SCIP_COL* col;
6531 SCIP_Real val;
6532 SCIP_Bool mininfinite;
6533 SCIP_Bool maxinfinite;
6534 int i;
6535
6536 assert(row != NULL);
6537 assert(!SCIPsetIsInfinity(set, REALABS(row->constant)));
6538 assert(stat != NULL);
6539
6540 /* calculate activity bounds */
6541 mininfinite = FALSE;
6542 maxinfinite = FALSE;
6543 row->minactivity = row->constant;
6544 row->maxactivity = row->constant;
6545 for( i = 0; i < row->len && (!mininfinite || !maxinfinite); ++i )
6546 {
6547 col = row->cols[i];
6548 assert(col != NULL);
6549 assert((i < row->nlpcols) == (row->linkpos[i] >= 0 && col->lppos >= 0));
6550 val = row->vals[i];
6551 if( val >= 0.0 )
6552 {
6553 mininfinite = mininfinite || SCIPsetIsInfinity(set, -col->lb);
6554 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, col->ub);
6555 if( !mininfinite )
6556 row->minactivity += val * col->lb;
6557 if( !maxinfinite )
6558 row->maxactivity += val * col->ub;
6559 }
6560 else
6561 {
6562 mininfinite = mininfinite || SCIPsetIsInfinity(set, col->ub);
6563 maxinfinite = maxinfinite || SCIPsetIsInfinity(set, -col->lb);
6564 if( !mininfinite )
6565 row->minactivity += val * col->ub;
6566 if( !maxinfinite )
6567 row->maxactivity += val * col->lb;
6568 }
6569 }
6570
6571 if( mininfinite )
6573 if( maxinfinite )
6576
6577#ifndef NDEBUG
6578 {
6579 SCIP_Real inttol = 1000.0*SCIPsetFeastol(set);
6580
6581 /* even if the row is integral, the bounds on the variables used for computing minimum and maximum activity might
6582 * be integral only within feasibility tolerance; this can happen, e.g., if a continuous variable is promoted to
6583 * an (implicit) integer variable and the bounds cannot be adjusted because they are minimally tighter than the
6584 * rounded bound value; hence, the activity may violate integrality; we allow 1000 times the default feasibility
6585 * tolerance as a proxy to account for the accumulation effect
6586 */
6587 assert(!row->integral || mininfinite || REALABS(row->minactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6588 || EPSISINT(row->minactivity - row->constant, inttol));
6589 assert(!row->integral || maxinfinite || REALABS(row->maxactivity - row->constant) > 1.0/SCIPsetSumepsilon(set)
6590 || EPSISINT(row->maxactivity - row->constant, inttol));
6591 }
6592#endif
6593}
6594
6595/** returns the minimal activity of a row w.r.t. the columns' bounds */
6597 SCIP_ROW* row, /**< LP row */
6598 SCIP_SET* set, /**< global SCIP settings */
6599 SCIP_STAT* stat /**< problem statistics data */
6600 )
6601{
6602 assert(row != NULL);
6603 assert(stat != NULL);
6604 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6605
6606 /* check, if activity bounds has to be calculated */
6607 if( row->validactivitybdsdomchg != stat->domchgcount )
6608 rowCalcActivityBounds(row, set, stat);
6609 assert(row->validactivitybdsdomchg == stat->domchgcount);
6610 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6611 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6612
6613 return row->minactivity;
6614}
6615
6616/** returns the maximal activity of a row w.r.t. the columns' bounds */
6618 SCIP_ROW* row, /**< LP row */
6619 SCIP_SET* set, /**< global SCIP settings */
6620 SCIP_STAT* stat /**< problem statistics data */
6621 )
6622{
6623 assert(row != NULL);
6624 assert(stat != NULL);
6625 assert(row->validactivitybdsdomchg <= stat->domchgcount);
6626
6627 /* check, if activity bounds has to be calculated */
6628 if( row->validactivitybdsdomchg != stat->domchgcount )
6629 rowCalcActivityBounds(row, set, stat);
6630 assert(row->validactivitybdsdomchg == stat->domchgcount);
6631 assert(row->minactivity != SCIP_INVALID); /*lint !e777*/
6632 assert(row->maxactivity != SCIP_INVALID); /*lint !e777*/
6633
6634 return row->maxactivity;
6635}
6636
6637/** returns whether the row is unmodifiable and redundant w.r.t. the columns' bounds */
6639 SCIP_ROW* row, /**< LP row */
6640 SCIP_SET* set, /**< global SCIP settings */
6641 SCIP_STAT* stat /**< problem statistics data */
6642 )
6643{
6644 assert(row != NULL);
6645
6646 if( row->modifiable )
6647 return FALSE;
6648 if( !SCIPsetIsInfinity(set, -row->lhs) )
6649 {
6650 SCIP_Real minactivity;
6651
6652 minactivity = SCIProwGetMinActivity(row, set, stat);
6653 if( SCIPsetIsFeasLT(set, minactivity, row->lhs) )
6654 return FALSE;
6655 }
6656 if( !SCIPsetIsInfinity(set, row->rhs) )
6657 {
6658 SCIP_Real maxactivity;
6659
6660 maxactivity = SCIProwGetMaxActivity(row, set, stat);
6661 if( SCIPsetIsFeasGT(set, maxactivity, row->rhs) )
6662 return FALSE;
6663 }
6664
6665 return TRUE;
6666}
6667
6668/** gets maximal absolute value of row vector coefficients */
6670 SCIP_ROW* row, /**< LP row */
6671 SCIP_SET* set /**< global SCIP settings */
6672 )
6673{
6674 assert(row != NULL);
6675
6676 if( row->nummaxval == 0 )
6677 rowCalcIdxsAndVals(row, set);
6678 assert(row->nummaxval > 0);
6679 assert(row->maxval >= 0.0 || row->len == 0);
6680
6681 return row->maxval;
6682}
6683
6684/** gets minimal absolute value of row vector's non-zero coefficients */
6686 SCIP_ROW* row, /**< LP row */
6687 SCIP_SET* set /**< global SCIP settings */
6688 )
6689{
6690 assert(row != NULL);
6691
6692 if( row->numminval == 0 )
6693 rowCalcIdxsAndVals(row, set);
6694 assert(row->numminval > 0);
6695 assert(row->minval >= 0.0 || row->len == 0);
6696
6697 return row->minval;
6698}
6699
6700/** gets maximal column index of row entries */
6702 SCIP_ROW* row, /**< LP row */
6703 SCIP_SET* set /**< global SCIP settings */
6704 )
6705{
6706 assert(row != NULL);
6707
6708 if( row->validminmaxidx == 0 )
6709 rowCalcIdxsAndVals(row, set);
6710 assert(row->maxidx >= 0 || row->len == 0);
6711 assert(row->validminmaxidx);
6712
6713 return row->maxidx;
6714}
6715
6716/** gets minimal column index of row entries */
6718 SCIP_ROW* row, /**< LP row */
6719 SCIP_SET* set /**< global SCIP settings */
6720 )
6721{
6722 assert(row != NULL);
6723
6724 if( row->validminmaxidx == 0 )
6725 rowCalcIdxsAndVals(row, set);
6726 assert(row->minidx >= 0 || row->len == 0);
6727 assert(row->validminmaxidx);
6728
6729 return row->minidx;
6730}
6731
6732/** gets number of integral columns in row */
6734 SCIP_ROW* row, /**< LP row */
6735 SCIP_SET* set /**< global SCIP settings */
6736 )
6737{
6738 assert(row != NULL);
6739
6740 if( row->numintcols == -1 )
6741 rowCalcIdxsAndVals(row, set);
6742
6743 assert(row->numintcols <= row->len && row->numintcols >= 0);
6744
6745 return row->numintcols;
6746}
6747
6748/** returns row's cutoff distance in the direction of the given primal solution */
6750 SCIP_ROW* row, /**< LP row */
6751 SCIP_SET* set, /**< global SCIP settings */
6752 SCIP_STAT* stat, /**< problem statistics data */
6753 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
6754 SCIP_LP* lp /**< current LP data */
6755 )
6756{
6757 SCIP_Real solcutoffdist;
6758 int k;
6759
6760 assert(sol != NULL);
6761
6762 if( lp->validsoldirlp != stat->lpcount || lp->validsoldirsol != sol )
6763 {
6764 SCIP_Real scale = 0.0;
6765
6766 lp->validsoldirlp = stat->lpcount;
6767 lp->validsoldirsol = sol;
6768
6770
6771 for( k = 0; k < lp->ncols; ++k )
6772 {
6773 assert(lp->cols[k]->lppos == k);
6774 lp->soldirection[k] = SCIPsolGetVal(sol, set, stat, lp->cols[k]->var) - lp->cols[k]->primsol;
6775 scale += SQR(lp->soldirection[k]);
6776 }
6777
6778 if( scale > 0.0 )
6779 {
6780 scale = 1.0 / sqrt(scale);
6781
6782 for( k = 0; k < lp->ncols; ++k )
6783 lp->soldirection[k] *= scale;
6784 }
6785 }
6786
6787 solcutoffdist = 0.0;
6788 for( k = 0; k < row->nlpcols; ++k )
6789 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6790
6791 for( k = row->nlpcols; k < row->len; ++k )
6792 {
6793 if( row->cols[k]->lppos >= 0 )
6794 solcutoffdist += row->vals[k] * lp->soldirection[row->cols[k]->lppos];
6795 }
6796
6797 if( SCIPsetIsSumZero(set, solcutoffdist) )
6798 solcutoffdist = set->num_sumepsilon;
6799
6800 solcutoffdist = -SCIProwGetLPFeasibility(row, set, stat, lp) / ABS(solcutoffdist); /*lint !e795*/
6801
6802 return solcutoffdist;
6803}
6804
6805/** returns row's efficacy with respect to the current LP solution: e = -feasibility/norm */
6807 SCIP_ROW* row, /**< LP row */
6808 SCIP_SET* set, /**< global SCIP settings */
6809 SCIP_STAT* stat, /**< problem statistics data */
6810 SCIP_LP* lp /**< current LP data */
6811 )
6812{
6813 SCIP_Real norm;
6814 SCIP_Real feasibility;
6815 SCIP_Real eps;
6816
6817 assert(set != NULL);
6818
6819 switch( set->sepa_efficacynorm )
6820 {
6821 case 'e':
6822 norm = SCIProwGetNorm(row);
6823 break;
6824 case 'm':
6825 norm = SCIProwGetMaxval(row, set);
6826 break;
6827 case 's':
6828 norm = SCIProwGetSumNorm(row);
6829 break;
6830 case 'd':
6831 norm = (row->len == 0 ? 0.0 : 1.0);
6832 break;
6833 default:
6834 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6835 SCIPABORT();
6836 norm = 0.0; /*lint !e527*/
6837 }
6838
6840 norm = MAX(norm, eps);
6841 feasibility = SCIProwGetLPFeasibility(row, set, stat, lp);
6842
6843 return -feasibility / norm;
6844}
6845
6846/** returns whether the row's efficacy with respect to the current LP solution is greater than the minimal cut efficacy */
6848 SCIP_ROW* row, /**< LP row */
6849 SCIP_SET* set, /**< global SCIP settings */
6850 SCIP_STAT* stat, /**< problem statistics data */
6851 SCIP_LP* lp, /**< current LP data */
6852 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6853 )
6854{
6855 SCIP_Real efficacy;
6856
6857 efficacy = SCIProwGetLPEfficacy(row, set, stat, lp);
6858
6859 return SCIPsetIsEfficacious(set, root, efficacy);
6860}
6861
6862/** returns row's efficacy with respect to the given primal solution: e = -feasibility/norm */
6864 SCIP_ROW* row, /**< LP row */
6865 SCIP_SET* set, /**< global SCIP settings */
6866 SCIP_STAT* stat, /**< problem statistics data */
6867 SCIP_SOL* sol /**< primal CIP solution */
6868 )
6869{
6870 SCIP_Real norm;
6871 SCIP_Real feasibility;
6872 SCIP_Real eps;
6873
6874 assert(set != NULL);
6875
6876 switch( set->sepa_efficacynorm )
6877 {
6878 case 'e':
6879 norm = SCIProwGetNorm(row);
6880 break;
6881 case 'm':
6882 norm = SCIProwGetMaxval(row, set);
6883 break;
6884 case 's':
6885 norm = SCIProwGetSumNorm(row);
6886 break;
6887 case 'd':
6888 norm = (row->len == 0 ? 0.0 : 1.0);
6889 break;
6890 default:
6891 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6892 SCIPABORT();
6893 norm = 0.0; /*lint !e527*/
6894 }
6895
6897 norm = MAX(norm, eps);
6898 feasibility = SCIProwGetSolFeasibility(row, set, stat, sol);
6899
6900 return -feasibility / norm;
6901}
6902
6903/** returns whether the row's efficacy with respect to the given primal solution is greater than the minimal cut
6904 * efficacy
6905 */
6907 SCIP_ROW* row, /**< LP row */
6908 SCIP_SET* set, /**< global SCIP settings */
6909 SCIP_STAT* stat, /**< problem statistics data */
6910 SCIP_SOL* sol, /**< primal CIP solution */
6911 SCIP_Bool root /**< should the root's minimal cut efficacy be used? */
6912 )
6913{
6914 SCIP_Real efficacy;
6915
6916 efficacy = SCIProwGetSolEfficacy(row, set, stat, sol);
6917
6918 return SCIPsetIsEfficacious(set, root, efficacy);
6919}
6920
6921/** returns row's efficacy with respect to the relaxed solution: e = -feasibility/norm */
6923 SCIP_ROW* row, /**< LP row */
6924 SCIP_SET* set, /**< global SCIP settings */
6925 SCIP_STAT* stat /**< problem statistics data */
6926 )
6927{
6928 SCIP_Real norm;
6929 SCIP_Real feasibility;
6930 SCIP_Real eps;
6931
6932 assert(set != NULL);
6933
6934 switch( set->sepa_efficacynorm )
6935 {
6936 case 'e':
6937 norm = SCIProwGetNorm(row);
6938 break;
6939 case 'm':
6940 norm = SCIProwGetMaxval(row, set);
6941 break;
6942 case 's':
6943 norm = SCIProwGetSumNorm(row);
6944 break;
6945 case 'd':
6946 norm = (row->len == 0 ? 0.0 : 1.0);
6947 break;
6948 default:
6949 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6950 SCIPABORT();
6951 norm = 0.0; /*lint !e527*/
6952 }
6953
6955 norm = MAX(norm, eps);
6956 feasibility = SCIProwGetRelaxFeasibility(row, set, stat);
6957
6958 return -feasibility / norm;
6959}
6960
6961/** returns row's efficacy with respect to the NLP solution: e = -feasibility/norm */
6963 SCIP_ROW* row, /**< LP row */
6964 SCIP_SET* set, /**< global SCIP settings */
6965 SCIP_STAT* stat /**< problem statistics data */
6966 )
6967{
6968 SCIP_Real norm;
6969 SCIP_Real feasibility;
6970 SCIP_Real eps;
6971
6972 assert(set != NULL);
6973
6974 switch( set->sepa_efficacynorm )
6975 {
6976 case 'e':
6977 norm = SCIProwGetNorm(row);
6978 break;
6979 case 'm':
6980 norm = SCIProwGetMaxval(row, set);
6981 break;
6982 case 's':
6983 norm = SCIProwGetSumNorm(row);
6984 break;
6985 case 'd':
6986 norm = (row->len == 0 ? 0.0 : 1.0);
6987 break;
6988 default:
6989 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", set->sepa_efficacynorm);
6990 SCIPABORT();
6991 norm = 0.0; /*lint !e527*/
6992 }
6993
6995 norm = MAX(norm, eps);
6996 feasibility = SCIProwGetNLPFeasibility(row, set, stat);
6997
6998 return -feasibility / norm;
6999}
7000
7001/** returns the scalar product of the coefficient vectors of the two given rows
7002 *
7003 * @note the scalar product is computed w.r.t. the current LP columns only
7004 * @todo also consider non-LP columns for the computation?
7005 */
7007 SCIP_ROW* row1, /**< first LP row */
7008 SCIP_ROW* row2 /**< second LP row */
7009 )
7010{
7011 SCIP_Real scalarprod;
7012 int* row1colsidx;
7013 int* row2colsidx;
7014 int i1;
7015 int i2;
7016
7017 assert(row1 != NULL);
7018 assert(row2 != NULL);
7019
7020 /* Sort the column indices of both rows.
7021 *
7022 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7023 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7024 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7025 * for both or one of the non-LP columns for both.
7026 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7027 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7028 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7029 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7030 *
7031 * We distinguish the following cases:
7032 *
7033 * 1) both rows have no unlinked columns
7034 * -> we just check the LP partitions
7035 *
7036 * 2) exactly one row is completely unlinked, the other one is completely linked
7037 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7038 * (thus all common LP columns are regarded)
7039 *
7040 * 3) we have unlinked and LP columns in both rows
7041 * -> we need to compare four partitions at once
7042 *
7043 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7044 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7045 * other row
7046 *
7047 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7048 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7049 *
7050 * 5) both rows are completely unlinked
7051 * -> we need to compare two partitions: both complete rows
7052 */
7053 SCIProwSort(row1);
7054 assert(row1->lpcolssorted);
7055 assert(row1->nonlpcolssorted);
7056 SCIProwSort(row2);
7057 assert(row2->lpcolssorted);
7058 assert(row2->nonlpcolssorted);
7059
7060 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7061 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7062
7063 row1colsidx = row1->cols_index;
7064 row2colsidx = row2->cols_index;
7065
7066#ifndef NDEBUG
7067 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7068 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7069 {
7070 i1 = 0;
7071 i2 = row2->nlpcols;
7072 while( i1 < row1->nlpcols && i2 < row2->len )
7073 {
7074 assert(row1->cols[i1] != row2->cols[i2]);
7075 if( row1->cols[i1]->index < row2->cols[i2]->index )
7076 ++i1;
7077 else
7078 {
7079 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7080 ++i2;
7081 }
7082 }
7083 assert(i1 == row1->nlpcols || i2 == row2->len);
7084
7085 i1 = row1->nlpcols;
7086 i2 = 0;
7087 while( i1 < row1->len && i2 < row2->nlpcols )
7088 {
7089 assert(row1->cols[i1] != row2->cols[i2]);
7090 if( row1->cols[i1]->index < row2->cols[i2]->index )
7091 ++i1;
7092 else
7093 {
7094 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7095 ++i2;
7096 }
7097 }
7098 assert(i1 == row1->len || i2 == row2->nlpcols);
7099 }
7100#endif
7101
7102 /* The "easy" cases 1) and 2) */
7103 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7104 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7105 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7106 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7107 {
7108 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7109 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7110
7111 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7112 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7113 */
7114 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7115 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7116 scalarprod = 0.0;
7117
7118 /* calculate the scalar product */
7119 while( i1 >= 0 && i2 >= 0 )
7120 {
7121 assert(row1->cols[i1]->index == row1colsidx[i1]);
7122 assert(row2->cols[i2]->index == row2colsidx[i2]);
7123 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7124 if( row1colsidx[i1] < row2colsidx[i2] )
7125 --i2;
7126 else if( row1colsidx[i1] > row2colsidx[i2] )
7127 --i1;
7128 else
7129 {
7130 scalarprod += row1->vals[i1] * row2->vals[i2];
7131 --i1;
7132 --i2;
7133 }
7134 }
7135 }
7136 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7137 else
7138 {
7139 SCIP_Bool lpcols;
7140 int ilp1;
7141 int inlp1;
7142 int ilp2;
7143 int inlp2;
7144 int end1;
7145 int end2;
7146
7147 scalarprod = 0;
7148 ilp1 = 0;
7149 ilp2 = 0;
7150
7151 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7152 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7153 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7154
7155 /* handle the case of four partitions (case 3) until one partition is finished;
7156 * cases 4a), 4b), and 5) will fail the while-condition
7157 */
7158 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7159 {
7160 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7161 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7162 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7163 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7164 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7165 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7166 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7167 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7168
7169 /* rows have the same linked LP columns */
7170 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7171 {
7172 scalarprod += row1->vals[ilp1] * row2->vals[ilp2];
7173 ++ilp1;
7174 ++ilp2;
7175 }
7176 /* LP column of row1 is the same as unlinked column of row2 */
7177 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7178 {
7179 scalarprod += row1->vals[ilp1] * row2->vals[inlp2];
7180 ++ilp1;
7181 ++inlp2;
7182 }
7183 /* unlinked column of row1 is the same as LP column of row2 */
7184 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7185 {
7186 scalarprod += row1->vals[inlp1] * row2->vals[ilp2];
7187 ++inlp1;
7188 ++ilp2;
7189 }
7190 /* two unlinked LP columns are the same */
7191 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7192 {
7193 scalarprod += row1->vals[inlp1] * row2->vals[inlp2];
7194 ++inlp1;
7195 ++inlp2;
7196 }
7197 /* increase smallest counter */
7198 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7199 {
7200 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7201 {
7202 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7203 ++ilp1;
7204 else
7205 ++ilp2;
7206 }
7207 else
7208 {
7209 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7210 ++ilp1;
7211 else
7212 ++inlp2;
7213 }
7214 }
7215 else
7216 {
7217 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7218 {
7219 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7220 ++inlp1;
7221 else
7222 ++ilp2;
7223 }
7224 else
7225 {
7226 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7227 ++inlp1;
7228 else
7229 ++inlp2;
7230 }
7231 }
7232 }
7233
7234 /* One partition was completely handled, we just have to handle the three remaining partitions:
7235 * the remaining partition of this row and the two partitions of the other row.
7236 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7237 */
7238 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7239 {
7240 int tmpilp;
7241 int tmpinlp;
7242
7243 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7244
7245 SCIPswapPointers((void**) &row1, (void**) &row2);
7246 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7247 tmpilp = ilp1;
7248 tmpinlp = inlp1;
7249 ilp1 = ilp2;
7250 inlp1 = inlp2;
7251 ilp2 = tmpilp;
7252 inlp2 = tmpinlp;
7253 }
7254
7255 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7256 * -> this merges cases 4a) and 4b)
7257 */
7258 if( ilp1 == row1->nlpcols )
7259 {
7260 i1 = inlp1;
7261 end1 = row1->len;
7262 lpcols = FALSE;
7263 }
7264 else
7265 {
7266 assert(inlp1 == row1->len);
7267
7268 i1 = ilp1;
7269 end1 = row1->nlpcols;
7270 lpcols = TRUE;
7271 }
7272
7273 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7274 * case 5) will fail the while-condition
7275 */
7276 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7277 {
7278 assert(row1->cols[i1]->index == row1colsidx[i1]);
7279 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7280 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7281 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7282 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7283
7284 /* current column in row 1 is the same as the current LP column in row 2 */
7285 if( row1colsidx[i1] == row2colsidx[ilp2] )
7286 {
7287 scalarprod += row1->vals[i1] * row2->vals[ilp2];
7288 ++i1;
7289 ++ilp2;
7290 }
7291 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7292 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7293 {
7294 scalarprod += row1->vals[i1] * row2->vals[inlp2];
7295 ++i1;
7296 ++inlp2;
7297 }
7298 /* increase smallest counter */
7299 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7300 {
7301 if( row1colsidx[i1] < row2colsidx[ilp2] )
7302 ++i1;
7303 else
7304 ++ilp2;
7305 }
7306 else
7307 {
7308 if( row1colsidx[i1] < row2colsidx[inlp2] )
7309 ++i1;
7310 else
7311 ++inlp2;
7312 }
7313 }
7314
7315 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7316 * the two rows
7317 */
7318 if( i1 < end1 )
7319 {
7320 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7321 if( ilp2 == row2->nlpcols )
7322 {
7323 i2 = inlp2;
7324 end2 = row2->len;
7325 lpcols = FALSE;
7326 }
7327 else
7328 {
7329 assert(inlp2 == row2->len);
7330
7331 i2 = ilp2;
7332 end2 = row2->nlpcols;
7333 }
7334
7335 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7336 while( i1 < end1 && i2 < end2 )
7337 {
7338 assert(row1->cols[i1]->index == row1colsidx[i1]);
7339 assert(row2->cols[i2]->index == row2colsidx[i2]);
7340 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7341
7342 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7343 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7344 {
7345 scalarprod += row1->vals[i1] * row2->vals[i2];
7346 ++i1;
7347 ++i2;
7348 }
7349 /* increase smallest counter */
7350 else if( row1colsidx[i1] < row2colsidx[i2] )
7351 ++i1;
7352 else
7353 ++i2;
7354 }
7355 }
7356 }
7357
7358 return scalarprod;
7359}
7360
7361/** returns the discrete scalar product of the coefficient vectors of the two given rows */
7362static
7364 SCIP_ROW* row1, /**< first LP row */
7365 SCIP_ROW* row2 /**< second LP row */
7366 )
7367{
7368 int prod;
7369 int* row1colsidx;
7370 int* row2colsidx;
7371 int i1;
7372 int i2;
7373
7374 assert(row1 != NULL);
7375 assert(row2 != NULL);
7376
7377 /* Sort the column indices of both rows.
7378 *
7379 * The columns in a row are divided into two parts: LP columns, which are currently in the LP and non-LP columns;
7380 * we sort the rows, but that only ensures that within these two parts, columns are sorted w.r.t. their index.
7381 * Normally, this should be suficient, because a column contained in both rows should either be one of the LP columns
7382 * for both or one of the non-LP columns for both.
7383 * However, directly after a row was created, before a row is added to the LP, the row is not linked to all its
7384 * columns and all columns are treated as non-LP columns. Moreover, for example when doing column generation,
7385 * columns can be added later and remain unlinked while all previously added columns might already be linked.
7386 * Therefore, we have to be very careful about whether we can rely on the partitioning of the variables.
7387 *
7388 * We distinguish the following cases:
7389 *
7390 * 1) both rows have no unlinked columns
7391 * -> we just check the LP partitions
7392 *
7393 * 2) exactly one row is completely unlinked, the other one is completely linked
7394 * -> we compare the non-LP (unlinked) partition with the LP partition of the other row
7395 * (thus all common LP columns are regarded)
7396 *
7397 * 3) we have unlinked and LP columns in both rows
7398 * -> we need to compare four partitions at once
7399 *
7400 * 4a) we have one row with unlinked and LP columns and the other without any unlinked columns
7401 * -> we need to compare three partitions: the LP part of the completely linked row and both partitions of the
7402 * other row
7403 *
7404 * 4b) we have one row with unlinked and LP columns and the other is completely unlinked
7405 * -> we need to compare three partitions: the complete unlinked row and both partitions of the other row
7406 *
7407 * 5) both rows are completely unlinked
7408 * -> we need to compare two partitions: both complete rows
7409 */
7410 SCIProwSort(row1);
7411 assert(row1->lpcolssorted);
7412 assert(row1->nonlpcolssorted);
7413 SCIProwSort(row2);
7414 assert(row2->lpcolssorted);
7415 assert(row2->nonlpcolssorted);
7416
7417 assert(row1->nunlinked <= row1->len - row1->nlpcols);
7418 assert(row2->nunlinked <= row2->len - row2->nlpcols);
7419
7420 row1colsidx = row1->cols_index;
7421 row2colsidx = row2->cols_index;
7422
7423#ifndef NDEBUG
7424 /* check that we can rely on the partition into LP columns and non-LP columns if the rows are completely linked */
7425 if( row1->nunlinked == 0 && row2->nunlinked == 0 )
7426 {
7427 i1 = 0;
7428 i2 = row2->nlpcols;
7429 while( i1 < row1->nlpcols && i2 < row2->len )
7430 {
7431 assert(row1->cols[i1] != row2->cols[i2]);
7432 if( row1->cols[i1]->index < row2->cols[i2]->index )
7433 ++i1;
7434 else
7435 {
7436 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7437 ++i2;
7438 }
7439 }
7440 assert(i1 == row1->nlpcols || i2 == row2->len);
7441
7442 i1 = row1->nlpcols;
7443 i2 = 0;
7444 while( i1 < row1->len && i2 < row2->nlpcols )
7445 {
7446 assert(row1->cols[i1] != row2->cols[i2]);
7447 if( row1->cols[i1]->index < row2->cols[i2]->index )
7448 ++i1;
7449 else
7450 {
7451 assert(row1->cols[i1]->index > row2->cols[i2]->index);
7452 ++i2;
7453 }
7454 }
7455 assert(i1 == row1->len || i2 == row2->nlpcols);
7456 }
7457#endif
7458
7459 /* The "easy" cases 1) and 2) */
7460 if( (row1->nunlinked == 0 && row2->nunlinked == 0) ||
7461 ((row1->nlpcols == row1->len || row1->nunlinked == row1->len)
7462 && (row2->nlpcols == row2->len || row2->nunlinked == row2->len)
7463 && (row1->nunlinked == 0 || row2->nunlinked == 0)) )
7464 {
7465 assert(row1->nunlinked == 0 || row1->nunlinked == row1->len);
7466 assert(row2->nunlinked == 0 || row2->nunlinked == row2->len);
7467
7468 /* set the iterators to the last column we want to regard in the row: nunlinked is either 0 or row->len,
7469 * therefore, we get nlpcols if nunlinked is 0 and row->len if the row is completely unlinked
7470 */
7471 i1 = MAX(row1->nlpcols, row1->nunlinked) - 1;
7472 i2 = MAX(row2->nlpcols, row2->nunlinked) - 1;
7473 prod = 0;
7474
7475 /* calculate the scalar product */
7476 while( i1 >= 0 && i2 >= 0 )
7477 {
7478 assert(row1->cols[i1]->index == row1colsidx[i1]);
7479 assert(row2->cols[i2]->index == row2colsidx[i2]);
7480 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7481 if( row1colsidx[i1] < row2colsidx[i2] )
7482 --i2;
7483 else if( row1colsidx[i1] > row2colsidx[i2] )
7484 --i1;
7485 else
7486 {
7487 ++prod;
7488 --i1;
7489 --i2;
7490 }
7491 }
7492 }
7493 /* the "harder" cases 3) - 5): start with four partitions and reduce their number iteratively */
7494 else
7495 {
7496 SCIP_Bool lpcols;
7497 int ilp1;
7498 int inlp1;
7499 int ilp2;
7500 int inlp2;
7501 int end1;
7502 int end2;
7503
7504 prod = 0;
7505 ilp1 = 0;
7506 ilp2 = 0;
7507
7508 /* if a row is completely linked (case 4a), we do not have to consider its non-LP columns */
7509 inlp1 = (row1->nunlinked > 0 ? row1->nlpcols : row1->len);
7510 inlp2 = (row2->nunlinked > 0 ? row2->nlpcols : row2->len);
7511
7512 /* handle the case of four partitions (case 3) until one partition is finished;
7513 * cases 4a), 4b), and 5) will fail the while-condition
7514 */
7515 while( ilp1 < row1->nlpcols && inlp1 < row1->len && ilp2 < row2->nlpcols && inlp2 < row2->len )
7516 {
7517 assert(row1->cols[ilp1]->index == row1colsidx[ilp1]);
7518 assert(row1->cols[inlp1]->index == row1colsidx[inlp1]);
7519 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7520 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7521 assert((row1->cols[ilp1] == row2->cols[ilp2]) == (row1colsidx[ilp1] == row2colsidx[ilp2]));
7522 assert((row1->cols[ilp1] == row2->cols[inlp2]) == (row1colsidx[ilp1] == row2colsidx[inlp2]));
7523 assert((row1->cols[inlp1] == row2->cols[ilp2]) == (row1colsidx[inlp1] == row2colsidx[ilp2]));
7524 assert((row1->cols[inlp1] == row2->cols[inlp2]) == (row1colsidx[inlp1] == row2colsidx[inlp2]));
7525
7526 /* rows have the same linked LP columns */
7527 if( row1colsidx[ilp1] == row2colsidx[ilp2] )
7528 {
7529 ++prod;
7530 ++ilp1;
7531 ++ilp2;
7532 }
7533 /* LP column of row1 is the same as unlinked column of row2 */
7534 else if( row1colsidx[ilp1] == row2colsidx[inlp2] )
7535 {
7536 ++prod;
7537 ++ilp1;
7538 ++inlp2;
7539 }
7540 /* unlinked column of row1 is the same as LP column of row2 */
7541 else if( row1colsidx[inlp1] == row2colsidx[ilp2] )
7542 {
7543 ++prod;
7544 ++inlp1;
7545 ++ilp2;
7546 }
7547 /* two unlinked LP columns are the same */
7548 else if( row1colsidx[inlp1] == row2colsidx[inlp2] && row1->cols[inlp1]->lppos >= 0 )
7549 {
7550 ++prod;
7551 ++inlp1;
7552 ++inlp2;
7553 }
7554 /* increase smallest counter */
7555 else if( row1colsidx[ilp1] < row1colsidx[inlp1] )
7556 {
7557 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7558 {
7559 if( row1colsidx[ilp1] < row2colsidx[ilp2] )
7560 ++ilp1;
7561 else
7562 ++ilp2;
7563 }
7564 else
7565 {
7566 if( row1colsidx[ilp1] < row2colsidx[inlp2] )
7567 ++ilp1;
7568 else
7569 ++inlp2;
7570 }
7571 }
7572 else
7573 {
7574 if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7575 {
7576 if( row1colsidx[inlp1] < row2colsidx[ilp2] )
7577 ++inlp1;
7578 else
7579 ++ilp2;
7580 }
7581 else
7582 {
7583 if( row1colsidx[inlp1] < row2colsidx[inlp2] )
7584 ++inlp1;
7585 else
7586 ++inlp2;
7587 }
7588 }
7589 }
7590
7591 /* One partition was completely handled, we just have to handle the three remaining partitions:
7592 * the remaining partition of this row and the two partitions of the other row.
7593 * If necessary, we swap the partitions to ensure that row1 is the row with only one remaining partition.
7594 */
7595 if( ilp1 != row1->nlpcols && inlp1 != row1->len )
7596 {
7597 int tmpilp;
7598 int tmpinlp;
7599
7600 assert(ilp2 == row2->nlpcols || inlp2 == row2->len);
7601
7602 SCIPswapPointers((void**) &row1, (void**) &row2);
7603 SCIPswapPointers((void**) &row1colsidx, (void**) &row2colsidx);
7604 tmpilp = ilp1;
7605 tmpinlp = inlp1;
7606 ilp1 = ilp2;
7607 inlp1 = inlp2;
7608 ilp2 = tmpilp;
7609 inlp2 = tmpinlp;
7610 }
7611
7612 /* determine section of row 1 that we want to look at (current iterator = begin, end, LP-columns?)
7613 * -> this merges cases 4a) and 4b)
7614 */
7615 if( ilp1 == row1->nlpcols )
7616 {
7617 i1 = inlp1;
7618 end1 = row1->len;
7619 lpcols = FALSE;
7620 }
7621 else
7622 {
7623 assert(inlp1 == row1->len);
7624
7625 i1 = ilp1;
7626 end1 = row1->nlpcols;
7627 lpcols = TRUE;
7628 }
7629
7630 /* handle the case of three partitions (case 4) until one partition is finished, this reduces our problem to case 1), 2), or 5);
7631 * case 5) will fail the while-condition
7632 */
7633 while( i1 < end1 && ilp2 < row2->nlpcols && inlp2 < row2->len )
7634 {
7635 assert(row1->cols[i1]->index == row1colsidx[i1]);
7636 assert(row2->cols[ilp2]->index == row2colsidx[ilp2]);
7637 assert(row2->cols[inlp2]->index == row2colsidx[inlp2]);
7638 assert((row1->cols[i1] == row2->cols[ilp2]) == (row1colsidx[i1] == row2colsidx[ilp2]));
7639 assert((row1->cols[i1] == row2->cols[inlp2]) == (row1colsidx[i1] == row2colsidx[inlp2]));
7640
7641 /* current column in row 1 is the same as the current LP column in row 2 */
7642 if( row1colsidx[i1] == row2colsidx[ilp2] )
7643 {
7644 ++prod;
7645 ++i1;
7646 ++ilp2;
7647 }
7648 /* linked or unlinked LP column of row1 is the same as unlinked column of row2 */
7649 else if( row1colsidx[i1] == row2colsidx[inlp2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7650 {
7651 ++prod;
7652 ++i1;
7653 ++inlp2;
7654 }
7655 /* increase smallest counter */
7656 else if( row2colsidx[ilp2] < row2colsidx[inlp2] )
7657 {
7658 if( row1colsidx[i1] < row2colsidx[ilp2] )
7659 ++i1;
7660 else
7661 ++ilp2;
7662 }
7663 else
7664 {
7665 if( row1colsidx[i1] < row2colsidx[inlp2] )
7666 ++i1;
7667 else
7668 ++inlp2;
7669 }
7670 }
7671
7672 /* if the second section of row 1 was finished, we can stop; otherwise, we have to consider the remaining parts of
7673 * the two rows
7674 */
7675 if( i1 < end1 )
7676 {
7677 /* determine section of row 2 that we want to look at (current iterator = begin, end, LP-columns?) */
7678 if( ilp2 == row2->nlpcols )
7679 {
7680 i2 = inlp2;
7681 end2 = row2->len;
7682 lpcols = FALSE;
7683 }
7684 else
7685 {
7686 assert(inlp2 == row2->len);
7687
7688 i2 = ilp2;
7689 end2 = row2->nlpcols;
7690 }
7691
7692 /* handle the case of two partitions (standard case 5, or case 1 or 2 due to partition reduction) */
7693 while( i1 < end1 && i2 < end2 )
7694 {
7695 assert(row1->cols[i1]->index == row1colsidx[i1]);
7696 assert(row2->cols[i2]->index == row2colsidx[i2]);
7697 assert((row1->cols[i1] == row2->cols[i2]) == (row1colsidx[i1] == row2colsidx[i2]));
7698
7699 /* linked or unlinked LP column of row1 is the same as linked or unlinked LP column of row2 */
7700 if( row1colsidx[i1] == row2colsidx[i2] && (lpcols || row1->cols[i1]->lppos >= 0) )
7701 {
7702 ++prod;
7703 ++i1;
7704 ++i2;
7705 }
7706 /* increase smallest counter */
7707 else if( row1colsidx[i1] < row2colsidx[i2] )
7708 ++i1;
7709 else
7710 ++i2;
7711 }
7712 }
7713 }
7714
7715 return prod;
7716}
7717
7718/** returns the degree of parallelism between the hyperplanes defined by the two row vectors v, w:
7719 * p = |v*w|/(|v|*|w|);
7720 * the hyperplanes are parallel, iff p = 1, they are orthogonal, iff p = 0
7721 */
7723 SCIP_ROW* row1, /**< first LP row */
7724 SCIP_ROW* row2, /**< second LP row */
7725 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7726 )
7727{
7728 SCIP_Real parallelism;
7729 SCIP_Real scalarprod;
7730
7731 switch( orthofunc )
7732 {
7733 case 'e':
7734 scalarprod = SCIProwGetScalarProduct(row1, row2);
7735 if( scalarprod == 0.0 )
7736 {
7737 parallelism = 0.0;
7738 break;
7739 }
7740
7741 if( SCIProwGetNorm(row1) == 0.0 )
7742 {
7743 /* In theory, this should not happen if the scalarproduct is not zero
7744 * But due to bug 520 (also issue 44), it is possible that norms are not correct.
7745 * Thus, if the norm is so bad that it is even 0, then reevaluate it here.
7746 * But as we don't have set available here, we cannot call rowCalcNorms, so do it by hand.
7747 */
7748 int i;
7749 for( i = 0; i < row1->len; ++i )
7750 if( row1->cols[i]->lppos >= 0 )
7751 row1->sqrnorm += SQR(row1->vals[i]);
7752 assert(SCIProwGetNorm(row1) != 0.0);
7753 }
7754
7755 if( SCIProwGetNorm(row2) == 0.0 )
7756 {
7757 /* same as for row1 above: reeval norms if it is 0, which is wrong */
7758 int i;
7759 for( i = 0; i < row2->len; ++i )
7760 if( row2->cols[i]->lppos >= 0 )
7761 row2->sqrnorm += SQR(row2->vals[i]);
7762 assert(SCIProwGetNorm(row2) != 0.0);
7763 }
7764
7765 parallelism = REALABS(scalarprod) / (SCIProwGetNorm(row1) * SCIProwGetNorm(row2));
7766 break;
7767
7768 case 'd':
7769 scalarprod = (SCIP_Real) SCIProwGetDiscreteScalarProduct(row1, row2);
7770 parallelism = scalarprod / (sqrt((SCIP_Real) SCIProwGetNNonz(row1)) * sqrt((SCIP_Real) SCIProwGetNNonz(row2)));
7771 break;
7772
7773 default:
7774 SCIPerrorMessage("invalid orthogonality function parameter '%c'\n", orthofunc);
7775 SCIPABORT();
7776 parallelism = 0.0; /*lint !e527*/
7777 }
7778
7779 return parallelism;
7780}
7781
7782/** returns the degree of orthogonality between the hyperplanes defined by the two row vectors v, w:
7783 * o = 1 - |v*w|/(|v|*|w|);
7784 * the hyperplanes are orthogonal, iff p = 1, they are parallel, iff p = 0
7785 */
7787 SCIP_ROW* row1, /**< first LP row */
7788 SCIP_ROW* row2, /**< second LP row */
7789 char orthofunc /**< function used for calc. scalar prod. ('e'uclidean, 'd'iscrete) */
7790 )
7791{
7792 return 1.0 - SCIProwGetParallelism(row1, row2, orthofunc);
7793}
7794
7795/** gets parallelism of row with objective function: if the returned value is 1, the row is parallel to the objective
7796 * function, if the value is 0, it is orthogonal to the objective function
7797 */
7799 SCIP_ROW* row, /**< LP row */
7800 SCIP_SET* set, /**< global SCIP settings */
7801 SCIP_LP* lp /**< current LP data */
7802 )
7803{
7804 SCIP_Real prod;
7805 SCIP_Real parallelism;
7806
7807 assert(row != NULL);
7808 assert(lp != NULL);
7809
7810 if( lp->objsqrnormunreliable )
7812
7813 assert(!lp->objsqrnormunreliable);
7814 assert(lp->objsqrnorm >= 0.0);
7815
7816 checkRowSqrnorm(row);
7817 checkRowObjprod(row);
7818
7819 prod = row->sqrnorm * lp->objsqrnorm;
7820
7821 parallelism = SCIPsetIsPositive(set, prod) ? REALABS(row->objprod) / sqrt(prod) : 0.0;
7822 assert(SCIPsetIsSumGE(set, parallelism, 0.0));
7823 assert(SCIPsetIsSumLE(set, parallelism, 1.0));
7824 parallelism = MIN(parallelism, 1.0);
7825 parallelism = MAX(parallelism, 0.0);
7826
7827 return parallelism;
7828}
7829
7830/** includes event handler with given data in row's event filter */
7832 SCIP_ROW* row, /**< row */
7833 BMS_BLKMEM* blkmem, /**< block memory */
7834 SCIP_SET* set, /**< global SCIP settings */
7835 SCIP_EVENTTYPE eventtype, /**< event type to catch */
7836 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7837 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7838 int* filterpos /**< pointer to store position of event filter entry, or NULL */
7839 )
7840{
7841 assert(row != NULL);
7842 assert(row->eventfilter != NULL);
7843 assert((eventtype & ~SCIP_EVENTTYPE_ROWCHANGED) == 0);
7844 assert((eventtype & SCIP_EVENTTYPE_ROWCHANGED) != 0);
7845
7846 SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of row <%s> with handler %p and data %p\n",
7847 eventtype, row->name, (void*)eventhdlr, (void*)eventdata);
7848
7849 SCIP_CALL( SCIPeventfilterAdd(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7850
7851 return SCIP_OKAY;
7852}
7853
7854/** deletes event handler with given data from row's event filter */
7856 SCIP_ROW* row, /**< row */
7857 BMS_BLKMEM* blkmem, /**< block memory */
7858 SCIP_SET* set, /**< global SCIP settings */
7859 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
7860 SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
7861 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
7862 int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
7863 )
7864{
7865 assert(row != NULL);
7866 assert(row->eventfilter != NULL);
7867
7868 SCIPsetDebugMsg(set, "drop event of row <%s> with handler %p and data %p\n", row->name, (void*)eventhdlr, (void*)eventdata);
7869
7870 SCIP_CALL( SCIPeventfilterDel(row->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
7871
7872 return SCIP_OKAY;
7873}
7874
7875/** marks a row to be not removable from the LP in the current node because it became obsolete */
7877 SCIP_ROW* row, /**< LP row */
7878 SCIP_STAT* stat /**< problem statistics */
7879 )
7880{
7881 assert(row != NULL);
7882 assert(stat != NULL);
7883 assert(stat->nnodes > 0);
7884
7885 /* lpRemoveObsoleteRows() does not remove a row if the node number stored in obsoletenode equals the current node number */
7886 row->obsoletenode = stat->nnodes;
7887}
7888
7889/*
7890 * LP solver data update
7891 */
7892
7893/** resets column data to represent a column not in the LP solver */
7894static
7896 SCIP_COL* col /**< column to be marked deleted */
7897 )
7898{
7899 assert(col != NULL);
7900
7901 col->lpipos = -1;
7902 col->primsol = 0.0;
7903 col->redcost = SCIP_INVALID;
7904 col->farkascoef = SCIP_INVALID;
7905 col->sbdown = SCIP_INVALID;
7906 col->sbup = SCIP_INVALID;
7907 col->sbdownvalid = FALSE;
7908 col->sbupvalid = FALSE;
7909 col->validredcostlp = -1;
7910 col->validfarkaslp = -1;
7911 col->sbitlim = -1;
7912 col->basisstatus = SCIP_BASESTAT_ZERO; /*lint !e641*/
7913}
7914
7915/** applies all cached column removals to the LP solver */
7916static
7918 SCIP_LP* lp /**< current LP data */
7919 )
7920{
7921 assert(lp != NULL);
7922 assert(lp->lpifirstchgcol <= lp->nlpicols);
7923 assert(lp->lpifirstchgcol <= lp->ncols);
7924
7925 /* find the first column to change */
7926 while( lp->lpifirstchgcol < lp->nlpicols
7927 && lp->lpifirstchgcol < lp->ncols
7928 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
7929 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
7930 {
7931 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
7932 lp->lpifirstchgcol++;
7933 }
7934
7935 /* shrink LP to the part which didn't change */
7936 if( lp->lpifirstchgcol < lp->nlpicols )
7937 {
7938 int i;
7939
7940 assert(!lp->diving);
7941 SCIPdebugMessage("flushing col deletions: shrink LP from %d to %d columns\n", lp->nlpicols, lp->lpifirstchgcol);
7943 for( i = lp->lpifirstchgcol; i < lp->nlpicols; ++i )
7944 {
7945 markColDeleted(lp->lpicols[i]);
7946 }
7947 lp->nlpicols = lp->lpifirstchgcol;
7948 lp->flushdeletedcols = TRUE;
7949 lp->updateintegrality = TRUE;
7950
7951 /* mark the LP unsolved */
7952 lp->solved = FALSE;
7953 lp->primalfeasible = FALSE;
7954 lp->primalchecked = FALSE;
7955 lp->lpobjval = SCIP_INVALID;
7957 }
7958 assert(lp->nlpicols == lp->lpifirstchgcol);
7959
7960 return SCIP_OKAY;
7961}
7962
7963/** computes for the given column the lower and upper bound that should be flushed into the LP
7964 * depending on lazy bounds and diving mode; in diving mode, lazy bounds are ignored, i.e.,
7965 * the bounds are explicitly added to the LP in any case
7966 */
7967static
7969 SCIP_LP* lp, /**< current LP data */
7970 SCIP_SET* set, /**< global SCIP settings */
7971 SCIP_COL* col, /**< column to compute bounds for */
7972 SCIP_Real lpiinf, /**< infinity value if the LP solver */
7973 SCIP_Real* lb, /**< pointer to store the new lower bound */
7974 SCIP_Real* ub /**< pointer to store the new upper bound */
7975 )
7976{
7977 assert(lp != NULL);
7978 assert(set != NULL);
7979 assert(col != NULL);
7980 assert(lb != NULL);
7981 assert(ub != NULL);
7982
7983 /* get the correct new lower bound:
7984 * if lazy lower bound exists and is larger than lower bound, set lower bound to infinity;
7985 * if we are in diving mode, ignore lazy bounds and always take the lower bound
7986 */
7987 if( SCIPsetIsInfinity(set, -col->lb) || (SCIPsetIsLE(set, col->lb, col->lazylb) && !SCIPlpDiving(lp)) )
7988 (*lb) = -lpiinf;
7989 else
7990 (*lb) = col->lb;
7991 /* get the correct new upper bound:
7992 * if lazy upper bound exists and is larger than upper bound, set upper bound to infinity;
7993 * if we are in diving mode, ignore lazy bounds and always take the upper bound
7994 */
7995 if( SCIPsetIsInfinity(set, col->ub) || (SCIPsetIsGE(set, col->ub, col->lazyub) && !SCIPlpDiving(lp)) )
7996 (*ub) = lpiinf;
7997 else
7998 (*ub) = col->ub;
7999}
8000
8001/** applies all cached column additions to the LP solver */
8002static
8004 SCIP_LP* lp, /**< current LP data */
8005 BMS_BLKMEM* blkmem, /**< block memory */
8006 SCIP_SET* set, /**< global SCIP settings */
8007 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8008 )
8009{
8010 SCIP_Real* obj;
8011 SCIP_Real* lb;
8012 SCIP_Real* ub;
8013 int* beg;
8014 int* ind;
8015 SCIP_Real* val;
8016 char** name;
8017 SCIP_COL* col;
8018 SCIP_Real lpiinf;
8019 int c;
8020 int pos;
8021 int nnonz;
8022 int naddcols;
8023 int naddcoefs;
8024 int i;
8025 int lpipos;
8026
8027 assert(lp != NULL);
8028 assert(lp->lpifirstchgcol == lp->nlpicols);
8029 assert(blkmem != NULL);
8030 assert(set != NULL);
8031
8032 /* if there are no columns to add, we are ready */
8033 if( lp->ncols == lp->nlpicols )
8034 return SCIP_OKAY;
8035
8036 /* add the additional columns */
8037 assert(!lp->diving);
8038 assert(lp->ncols > lp->nlpicols);
8039 SCIP_CALL( ensureLpicolsSize(lp, set, lp->ncols) );
8040
8041 /* get the solver's infinity value */
8042 lpiinf = SCIPlpiInfinity(lp->lpi);
8043
8044 /* count the (maximal) number of added coefficients, calculate the number of added columns */
8045 naddcols = lp->ncols - lp->nlpicols;
8046 naddcoefs = 0;
8047 for( c = lp->nlpicols; c < lp->ncols; ++c )
8048 naddcoefs += lp->cols[c]->len;
8049 assert(naddcols > 0);
8050
8051 /* get temporary memory for changes */
8052 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, naddcols) );
8053 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, naddcols) );
8054 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, naddcols) );
8055 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddcols) );
8056 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8057 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8058 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddcols) );
8059
8060 /* fill temporary memory with column data */
8061 nnonz = 0;
8062 for( pos = 0, c = lp->nlpicols; c < lp->ncols; ++pos, ++c )
8063 {
8064 col = lp->cols[c];
8065 assert(col != NULL);
8066 assert(col->var != NULL);
8068 assert(SCIPvarGetCol(col->var) == col);
8069 assert(col->lppos == c);
8070 assert(nnonz + col->nlprows <= naddcoefs);
8071
8072 SCIPsetDebugMsg(set, "flushing added column <%s>: ", SCIPvarGetName(col->var));
8073 debugColPrint(set, col);
8074
8075 /* Because the column becomes a member of the LP solver, it now can take values
8076 * different from zero. That means, we have to include the column in the corresponding
8077 * row vectors.
8078 */
8079 SCIP_CALL( colLink(col, blkmem, set, eventqueue, lp) );
8080
8081 lp->lpicols[c] = col;
8082 col->lpipos = c;
8083 col->primsol = SCIP_INVALID;
8084 col->redcost = SCIP_INVALID;
8085 col->farkascoef = SCIP_INVALID;
8086 col->sbdown = SCIP_INVALID;
8087 col->sbup = SCIP_INVALID;
8088 col->sbdownvalid = FALSE;
8089 col->sbupvalid = FALSE;
8090 col->validredcostlp = -1;
8091 col->validfarkaslp = -1;
8092 col->sbitlim = -1;
8093 col->objchanged = FALSE;
8094 col->lbchanged = FALSE;
8095 col->ubchanged = FALSE;
8096 col->coefchanged = FALSE;
8097 obj[pos] = col->obj;
8098
8099 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8100 computeLPBounds(lp, set, col, lpiinf, &(lb[pos]), &(ub[pos]));
8101
8102 beg[pos] = nnonz;
8103 name[pos] = (char*)SCIPvarGetName(col->var);
8104
8105 col->flushedobj = obj[pos];
8106 col->flushedlb = lb[pos];
8107 col->flushedub = ub[pos];
8108
8109 for( i = 0; i < col->nlprows; ++i )
8110 {
8111 assert(col->rows[i] != NULL);
8112 lpipos = col->rows[i]->lpipos;
8113 if( lpipos >= 0 )
8114 {
8115 assert(lpipos < lp->nrows);
8116 assert(nnonz < naddcoefs);
8117 ind[nnonz] = lpipos;
8118 val[nnonz] = col->vals[i];
8119 nnonz++;
8120 }
8121 }
8122#ifndef NDEBUG
8123 for( i = col->nlprows; i < col->len; ++i )
8124 {
8125 assert(col->rows[i] != NULL);
8126 assert(col->rows[i]->lpipos == -1); /* because the row deletions are already performed */
8127 }
8128#endif
8129 }
8130
8131 /* call LP interface */
8132 SCIPsetDebugMsg(set, "flushing col additions: enlarge LP from %d to %d columns\n", lp->nlpicols, lp->ncols);
8133 SCIP_CALL( SCIPlpiAddCols(lp->lpi, naddcols, obj, lb, ub, name, nnonz, beg, ind, val) );
8134 lp->nlpicols = lp->ncols;
8135 lp->lpifirstchgcol = lp->nlpicols;
8136
8137 /* free temporary memory */
8145
8146 lp->flushaddedcols = TRUE;
8147 lp->updateintegrality = TRUE;
8148
8149 /* mark the LP unsolved */
8150 lp->solved = FALSE;
8151 lp->dualfeasible = FALSE;
8152 lp->dualchecked = FALSE;
8153 lp->lpobjval = SCIP_INVALID;
8155
8156 return SCIP_OKAY;
8157}
8158
8159/** resets row data to represent a row not in the LP solver */
8160static
8162 SCIP_ROW* row /**< row to be marked deleted */
8163 )
8164{
8165 assert(row != NULL);
8166
8167 row->lpipos = -1;
8168 row->dualsol = 0.0;
8169 row->activity = SCIP_INVALID;
8170 row->dualfarkas = 0.0;
8171 row->basisstatus = SCIP_BASESTAT_BASIC; /*lint !e641*/
8172 row->validactivitylp = -1;
8173}
8174
8175/** applies all cached row removals to the LP solver */
8176static
8178 SCIP_LP* lp, /**< current LP data */
8179 BMS_BLKMEM* blkmem, /**< block memory */
8180 SCIP_SET* set /**< global SCIP settings */
8181 )
8182{
8183 assert(lp != NULL);
8184 assert(lp->lpifirstchgrow <= lp->nlpirows);
8185 assert(lp->lpifirstchgrow <= lp->nrows);
8186
8187 /* find the first row to change */
8188 while( lp->lpifirstchgrow < lp->nlpirows
8189 && lp->lpifirstchgrow < lp->nrows
8190 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8191 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8192 {
8193 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8194 lp->lpifirstchgrow++;
8195 }
8196
8197 /* shrink LP to the part which didn't change */
8198 if( lp->lpifirstchgrow < lp->nlpirows )
8199 {
8200 int i;
8201
8202 SCIPsetDebugMsg(set, "flushing row deletions: shrink LP from %d to %d rows\n", lp->nlpirows, lp->lpifirstchgrow);
8204 for( i = lp->lpifirstchgrow; i < lp->nlpirows; ++i )
8205 {
8206 markRowDeleted(lp->lpirows[i]);
8207 SCIP_CALL( SCIProwRelease(&lp->lpirows[i], blkmem, set, lp) );
8208 }
8209 lp->nlpirows = lp->lpifirstchgrow;
8210 lp->flushdeletedrows = TRUE;
8211
8212 /* mark the LP unsolved */
8213 lp->solved = FALSE;
8214 lp->dualfeasible = FALSE;
8215 lp->dualchecked = FALSE;
8216 lp->lpobjval = SCIP_INVALID;
8218 }
8219 assert(lp->nlpirows == lp->lpifirstchgrow);
8220
8221 return SCIP_OKAY;
8222}
8223
8224/** applies all cached row additions and removals to the LP solver */
8225static
8227 SCIP_LP* lp, /**< current LP data */
8228 BMS_BLKMEM* blkmem, /**< block memory */
8229 SCIP_SET* set, /**< global SCIP settings */
8230 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8231 )
8232{
8233 SCIP_Real* lhs;
8234 SCIP_Real* rhs;
8235 int* beg;
8236 int* ind;
8237 SCIP_Real* val;
8238 char** name;
8239 SCIP_ROW* row;
8240 SCIP_Real lpiinf;
8241 int r;
8242 int pos;
8243 int nnonz;
8244 int naddrows;
8245 int naddcoefs;
8246 int i;
8247 int lpipos;
8248
8249 assert(lp != NULL);
8250 assert(lp->lpifirstchgrow == lp->nlpirows);
8251 assert(blkmem != NULL);
8252
8253 /* if there are no rows to add, we are ready */
8254 if( lp->nrows == lp->nlpirows )
8255 return SCIP_OKAY;
8256
8257 /* add the additional rows */
8258 assert(lp->nrows > lp->nlpirows);
8259 SCIP_CALL( ensureLpirowsSize(lp, set, lp->nrows) );
8260
8261 /* get the solver's infinity value */
8262 lpiinf = SCIPlpiInfinity(lp->lpi);
8263
8264 /* count the (maximal) number of added coefficients, calculate the number of added rows */
8265 naddrows = lp->nrows - lp->nlpirows;
8266 naddcoefs = 0;
8267 for( r = lp->nlpirows; r < lp->nrows; ++r )
8268 naddcoefs += lp->rows[r]->len;
8269 assert(naddrows > 0);
8270
8271 /* get temporary memory for changes */
8272 SCIP_CALL( SCIPsetAllocBufferArray(set, &lhs, naddrows) );
8273 SCIP_CALL( SCIPsetAllocBufferArray(set, &rhs, naddrows) );
8274 SCIP_CALL( SCIPsetAllocBufferArray(set, &beg, naddrows) );
8275 SCIP_CALL( SCIPsetAllocBufferArray(set, &ind, naddcoefs) );
8276 SCIP_CALL( SCIPsetAllocBufferArray(set, &val, naddcoefs) );
8277 SCIP_CALL( SCIPsetAllocBufferArray(set, &name, naddrows) );
8278
8279 /* fill temporary memory with row data */
8280 nnonz = 0;
8281 for( pos = 0, r = lp->nlpirows; r < lp->nrows; ++pos, ++r )
8282 {
8283 row = lp->rows[r];
8284 assert(row != NULL);
8285 assert(row->lppos == r);
8286 assert(nnonz + row->nlpcols <= naddcoefs);
8287
8288 SCIPsetDebugMsg(set, "flushing added row <%s>: ", row->name);
8289 debugRowPrint(set, row);
8290
8291 /* Because the row becomes a member of the LP solver, its dual variable now can take values
8292 * different from zero. That means, we have to include the row in the corresponding
8293 * column vectors.
8294 */
8295 SCIP_CALL( rowLink(row, blkmem, set, eventqueue, lp) );
8296
8297 SCIProwCapture(row);
8298 lp->lpirows[r] = row;
8299 row->lpipos = r;
8300 row->dualsol = SCIP_INVALID;
8301 row->activity = SCIP_INVALID;
8302 row->dualfarkas = SCIP_INVALID;
8303 row->validactivitylp = -1;
8304 row->lhschanged = FALSE;
8305 row->rhschanged = FALSE;
8306 row->coefchanged = FALSE;
8307 if( SCIPsetIsInfinity(set, -row->lhs) )
8308 lhs[pos] = -lpiinf;
8309 else
8310 lhs[pos] = row->lhs - row->constant;
8311 if( SCIPsetIsInfinity(set, row->rhs) )
8312 rhs[pos] = lpiinf;
8313 else
8314 rhs[pos] = row->rhs - row->constant;
8315 beg[pos] = nnonz;
8316 name[pos] = row->name;
8317
8318 row->flushedlhs = lhs[pos];
8319 row->flushedrhs = rhs[pos];
8320
8321 SCIPsetDebugMsg(set, "flushing added row (SCIP_LPI): %+g <=", lhs[pos]);
8322 for( i = 0; i < row->nlpcols; ++i )
8323 {
8324 assert(row->cols[i] != NULL);
8325 lpipos = row->cols[i]->lpipos;
8326 if( lpipos >= 0 )
8327 {
8328 assert(lpipos < lp->ncols);
8329 assert(nnonz < naddcoefs);
8330 SCIPsetDebugMsgPrint(set, " %+gx%d(<%s>)", row->vals[i], lpipos+1, SCIPvarGetName(row->cols[i]->var));
8331 ind[nnonz] = lpipos;
8332 val[nnonz] = row->vals[i];
8333 nnonz++;
8334 }
8335 }
8336 SCIPsetDebugMsgPrint(set, " <= %+g\n", rhs[pos]);
8337#ifndef NDEBUG
8338 for( i = row->nlpcols; i < row->len; ++i )
8339 {
8340 assert(row->cols[i] != NULL);
8341 assert(row->cols[i]->lpipos == -1); /* because the column deletions are already performed */
8342 }
8343#endif
8344 }
8345
8346 /* call LP interface */
8347 SCIPsetDebugMsg(set, "flushing row additions: enlarge LP from %d to %d rows\n", lp->nlpirows, lp->nrows);
8348 SCIP_CALL( SCIPlpiAddRows(lp->lpi, naddrows, lhs, rhs, name, nnonz, beg, ind, val) );
8349 lp->nlpirows = lp->nrows;
8350 lp->lpifirstchgrow = lp->nlpirows;
8351
8352 /* free temporary memory */
8359
8360 lp->flushaddedrows = TRUE;
8361
8362 /* mark the LP unsolved */
8363 lp->solved = FALSE;
8364 lp->primalfeasible = FALSE;
8365 lp->primalchecked = FALSE;
8366 lp->lpobjval = SCIP_INVALID;
8368
8369 return SCIP_OKAY;
8370}
8371
8372/** applies all cached column bound and objective changes to the LP */
8373static
8375 SCIP_LP* lp, /**< current LP data */
8376 SCIP_SET* set /**< global SCIP settings */
8377 )
8378{
8379#ifndef NDEBUG
8380 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8381#endif
8382 SCIP_COL* col;
8383 int* objind;
8384 int* bdind;
8385 SCIP_Real* obj;
8386 SCIP_Real* lb;
8387 SCIP_Real* ub;
8388 SCIP_Real lpiinf;
8389 int nobjchg;
8390 int nbdchg;
8391 int i;
8392
8393 assert(lp != NULL);
8394
8395 if( lp->nchgcols == 0 )
8396 return SCIP_OKAY;
8397
8398 /* get the solver's infinity value */
8399 lpiinf = SCIPlpiInfinity(lp->lpi);
8400
8401 /* get temporary memory for changes */
8402 SCIP_CALL( SCIPsetAllocBufferArray(set, &objind, lp->ncols) );
8404 SCIP_CALL( SCIPsetAllocBufferArray(set, &bdind, lp->ncols) );
8407
8408 /* collect all cached bound and objective changes */
8409 nobjchg = 0;
8410 nbdchg = 0;
8411 for( i = 0; i < lp->nchgcols; ++i )
8412 {
8413 col = lp->chgcols[i];
8414 assert(col != NULL);
8415 assert(col->var != NULL);
8417 assert(SCIPvarGetCol(col->var) == col);
8418
8419 if( col->lpipos >= 0 )
8420 {
8421#ifndef NDEBUG
8422 /* do not check consistency of data with LPI in case of LPI=none */
8423 if( !lpinone )
8424 {
8425 SCIP_Real lpiobj;
8426 SCIP_Real lpilb;
8427 SCIP_Real lpiub;
8428
8429 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8430 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8431 assert(SCIPsetIsFeasEQ(set, lpiobj, col->flushedobj));
8432 assert((SCIPsetIsInfinity(set, -lpilb) && SCIPsetIsInfinity(set, -col->flushedlb))
8433 || (!SCIPsetIsInfinity(set, -lpilb) && !SCIPsetIsInfinity(set, -col->flushedlb) && SCIPsetIsFeasEQ(set, lpilb, col->flushedlb)));
8434 assert((SCIPsetIsInfinity(set, lpiub) && SCIPsetIsInfinity(set, col->flushedub))
8435 || (!SCIPsetIsInfinity(set, lpiub) && !SCIPsetIsInfinity(set, col->flushedub) && SCIPsetIsFeasEQ(set, lpiub, col->flushedub)));
8436 }
8437#endif
8438
8439 if( col->objchanged )
8440 {
8441 SCIP_Real newobj;
8442
8443 newobj = col->obj;
8444 if( col->flushedobj != newobj ) /*lint !e777*/
8445 {
8446 assert(nobjchg < lp->ncols);
8447 objind[nobjchg] = col->lpipos;
8448 obj[nobjchg] = newobj;
8449 nobjchg++;
8450 col->flushedobj = newobj;
8451 }
8452 col->objchanged = FALSE;
8453 }
8454
8455 if( col->lbchanged || col->ubchanged )
8456 {
8457 SCIP_Real newlb;
8458 SCIP_Real newub;
8459
8460 /* compute bounds that should be flushed into the LP (taking into account lazy bounds) */
8461 computeLPBounds(lp, set, col, lpiinf, &newlb, &newub);
8462
8463 if( col->flushedlb != newlb || col->flushedub != newub ) /*lint !e777*/
8464 {
8465 assert(nbdchg < lp->ncols);
8466 bdind[nbdchg] = col->lpipos;
8467 lb[nbdchg] = newlb;
8468 ub[nbdchg] = newub;
8469 nbdchg++;
8470 col->flushedlb = newlb;
8471 col->flushedub = newub;
8472 }
8473 col->lbchanged = FALSE;
8474 col->ubchanged = FALSE;
8475 }
8476 }
8477 /* maybe lb/ub/objchanged should all be set to false when lpipos is -1 */
8478 }
8479
8480 /* change objective values in LP */
8481 if( nobjchg > 0 )
8482 {
8483 SCIPsetDebugMsg(set, "flushing objective changes: change %d objective values of %d changed columns\n", nobjchg, lp->nchgcols);
8484 SCIP_CALL( SCIPlpiChgObj(lp->lpi, nobjchg, objind, obj) );
8485
8486 /* mark the LP unsolved */
8487 lp->solved = FALSE;
8488 lp->dualfeasible = FALSE;
8489 lp->dualchecked = FALSE;
8490 lp->lpobjval = SCIP_INVALID;
8492 }
8493
8494 /* change bounds in LP */
8495 if( nbdchg > 0 )
8496 {
8497 SCIPsetDebugMsg(set, "flushing bound changes: change %d bounds of %d changed columns\n", nbdchg, lp->nchgcols);
8498 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, nbdchg, bdind, lb, ub) );
8499
8500 /* mark the LP unsolved */
8501 lp->solved = FALSE;
8502 lp->primalfeasible = FALSE;
8503 lp->primalchecked = FALSE;
8504 lp->lpobjval = SCIP_INVALID;
8506 }
8507
8508 lp->nchgcols = 0;
8509
8510 /* free temporary memory */
8513 SCIPsetFreeBufferArray(set, &bdind);
8515 SCIPsetFreeBufferArray(set, &objind);
8516
8517 return SCIP_OKAY;
8518}
8519
8520/** applies all cached row side changes to the LP */
8521static
8523 SCIP_LP* lp, /**< current LP data */
8524 SCIP_SET* set /**< global SCIP settings */
8525 )
8526{
8527#ifndef NDEBUG
8528 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8529#endif
8530 SCIP_ROW* row;
8531 int* ind;
8532 SCIP_Real* lhs;
8533 SCIP_Real* rhs;
8534 SCIP_Real lpiinf;
8535 int i;
8536 int nchg;
8537
8538 assert(lp != NULL);
8539
8540 if( lp->nchgrows == 0 )
8541 return SCIP_OKAY;
8542
8543 /* get the solver's infinity value */
8544 lpiinf = SCIPlpiInfinity(lp->lpi);
8545
8546 /* get temporary memory for changes */
8550
8551 /* collect all cached left and right hand side changes */
8552 nchg = 0;
8553 for( i = 0; i < lp->nchgrows; ++i )
8554 {
8555 row = lp->chgrows[i];
8556 assert(row != NULL);
8557
8558 if( row->lpipos >= 0 )
8559 {
8560#ifndef NDEBUG
8561 /* do not check consistency of data with LPI in case of LPI=none */
8562 if( !lpinone )
8563 {
8564 SCIP_Real lpilhs;
8565 SCIP_Real lpirhs;
8566
8567 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8568 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8569 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8570 }
8571#endif
8572 if( row->lhschanged || row->rhschanged )
8573 {
8574 SCIP_Real newlhs;
8575 SCIP_Real newrhs;
8576
8577 newlhs = (SCIPsetIsInfinity(set, -row->lhs) ? -lpiinf : row->lhs - row->constant);
8578 newrhs = (SCIPsetIsInfinity(set, row->rhs) ? lpiinf : row->rhs - row->constant);
8579 if( row->flushedlhs != newlhs || row->flushedrhs != newrhs ) /*lint !e777*/
8580 {
8581 assert(nchg < lp->nrows);
8582 ind[nchg] = row->lpipos;
8583 lhs[nchg] = newlhs;
8584 rhs[nchg] = newrhs;
8585 nchg++;
8586 row->flushedlhs = newlhs;
8587 row->flushedrhs = newrhs;
8588 }
8589 row->lhschanged = FALSE;
8590 row->rhschanged = FALSE;
8591 }
8592 }
8593 }
8594
8595 /* change left and right hand sides in LP */
8596 if( nchg > 0 )
8597 {
8598 SCIPsetDebugMsg(set, "flushing side changes: change %d sides of %d rows\n", nchg, lp->nchgrows);
8599 SCIP_CALL( SCIPlpiChgSides(lp->lpi, nchg, ind, lhs, rhs) );
8600
8601 /* mark the LP unsolved */
8602 lp->solved = FALSE;
8603 lp->primalfeasible = FALSE;
8604 lp->primalchecked = FALSE;
8605 lp->lpobjval = SCIP_INVALID;
8607 }
8608
8609 lp->nchgrows = 0;
8610
8611 /* free temporary memory */
8615
8616 return SCIP_OKAY;
8617}
8618
8619/** copy integrality information to the LP */
8620static
8622 SCIP_LP* lp, /**< current LP data */
8623 SCIP_SET* set /**< global SCIP settings */
8624 )
8625{
8626 int i;
8627 int nintegers;
8628 int* integerInfo;
8629 SCIP_VAR* var;
8630
8631 assert(lp != NULL);
8632
8633 SCIP_CALL( SCIPsetAllocBufferArray(set, &integerInfo, lp->ncols) );
8634
8635 /* count total number of integralities */
8636 nintegers = 0;
8637
8638 for( i = 0; i < lp->ncols; ++i )
8639 {
8640 var = SCIPcolGetVar(lp->cols[i]);
8641 if( SCIPvarIsIntegral(var) || SCIPvarIsBinary(var) )
8642 {
8643 integerInfo[i] = 1;
8644 ++nintegers;
8645 }
8646 else
8647 integerInfo[i] = 0;
8648 }
8649
8650 /* only pass integrality information if integer variables are present */
8651 if( nintegers > 0 )
8652 {
8653 SCIP_CALL( SCIPlpiSetIntegralityInformation(lp->lpi, lp->ncols, integerInfo) );
8654 }
8655 else
8656 {
8658 }
8659
8660 SCIPsetFreeBufferArray(set, &integerInfo);
8661
8662 /* mark integralities to be updated */
8664
8665 return SCIP_OKAY;
8666}
8667
8668/** applies all cached changes to the LP solver */
8670 SCIP_LP* lp, /**< current LP data */
8671 BMS_BLKMEM* blkmem, /**< block memory */
8672 SCIP_SET* set, /**< global SCIP settings */
8673 SCIP_PROB* prob, /**< problem data */
8674 SCIP_EVENTQUEUE* eventqueue /**< event queue */
8675 )
8676{
8677 assert(lp != NULL);
8678 assert(blkmem != NULL);
8679
8680 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",
8681 lp->nlpicols, lp->nlpirows, lp->nchgcols, lp->nchgrows, lp->lpifirstchgcol, lp->lpifirstchgrow, lp->ncols, lp->nrows, lp->flushed);
8682
8683 if( !lp->flushed )
8684 {
8685 lp->flushdeletedcols = FALSE;
8686 lp->flushaddedcols = FALSE;
8687 lp->flushdeletedrows = FALSE;
8688 lp->flushaddedrows = FALSE;
8689
8691 SCIP_CALL( lpFlushDelRows(lp, blkmem, set) );
8694 SCIP_CALL( lpFlushAddCols(lp, blkmem, set, eventqueue) );
8695 SCIP_CALL( lpFlushAddRows(lp, blkmem, set, eventqueue) );
8696
8697 lp->flushed = TRUE;
8698
8699 checkLinks(lp);
8700 }
8701
8702 /* if the cutoff bound was changed in between and it is not disabled (e.g. for column generation),
8703 * we want to re-optimize the LP even if nothing else has changed
8704 */
8705 if( !lpCutoffDisabled(set, prob, lp) && lp->cutoffbound != lp->lpiobjlim && lp->ncols > 0 ) /*lint !e777*/
8706 {
8707 lp->solved = FALSE;
8709 }
8710
8711 assert(lp->nlpicols == lp->ncols);
8712 assert(lp->lpifirstchgcol == lp->nlpicols);
8713 assert(lp->nlpirows == lp->nrows);
8714 assert(lp->lpifirstchgrow == lp->nlpirows);
8715 assert(lp->nchgcols == 0);
8716 assert(lp->nchgrows == 0);
8717#ifndef NDEBUG
8718 {
8719 int ncols;
8720 int nrows;
8721
8722 SCIP_CALL( SCIPlpiGetNCols(lp->lpi, &ncols) );
8723 SCIP_CALL( SCIPlpiGetNRows(lp->lpi, &nrows) );
8724 assert(ncols == lp->ncols);
8725 assert(nrows == lp->nrows);
8726 }
8727#endif
8728
8729 return SCIP_OKAY;
8730}
8731
8732/** marks the LP to be flushed, even if the LP thinks it is not flushed */
8734 SCIP_LP* lp, /**< current LP data */
8735 SCIP_SET* set /**< global SCIP settings */
8736 )
8737{
8738#ifndef NDEBUG
8739 SCIP_Bool lpinone = (strcmp( SCIPlpiGetSolverName(), "NONE") == 0);
8740#endif
8741 int i;
8742
8743 assert(lp != NULL);
8744
8745#ifndef NDEBUG
8746 /* check, if there are really no column or row deletions or coefficient changes left */
8747 while( lp->lpifirstchgcol < lp->nlpicols
8748 && lp->lpifirstchgcol < lp->ncols
8749 && lp->cols[lp->lpifirstchgcol]->lpipos == lp->lpifirstchgcol
8750 && !lp->cols[lp->lpifirstchgcol]->coefchanged )
8751 {
8752 assert(lp->cols[lp->lpifirstchgcol] == lp->lpicols[lp->lpifirstchgcol]);
8753 lp->lpifirstchgcol++;
8754 }
8755 assert(lp->nlpicols == lp->lpifirstchgcol);
8756
8757 while( lp->lpifirstchgrow < lp->nlpirows
8758 && lp->lpifirstchgrow < lp->nrows
8759 && lp->rows[lp->lpifirstchgrow]->lpipos == lp->lpifirstchgrow
8760 && !lp->rows[lp->lpifirstchgrow]->coefchanged )
8761 {
8762 assert(lp->rows[lp->lpifirstchgrow] == lp->lpirows[lp->lpifirstchgrow]);
8763 lp->lpifirstchgrow++;
8764 }
8765 assert(lp->nlpirows == lp->lpifirstchgrow);
8766#endif
8767
8768 lp->lpifirstchgcol = lp->nlpicols;
8769 lp->lpifirstchgrow = lp->nlpirows;
8770
8771 /* check, if there are really no column or row additions left */
8772 assert(lp->ncols == lp->nlpicols);
8773 assert(lp->nrows == lp->nlpirows);
8774
8775 /* mark the changed columns to be unchanged, and check, if this is really correct */
8776 for( i = 0; i < lp->nchgcols; ++i )
8777 {
8778 SCIP_COL* col;
8779
8780 col = lp->chgcols[i];
8781 assert(col != NULL);
8782 assert(col->var != NULL);
8784 assert(SCIPvarGetCol(col->var) == col);
8785
8786 if( col->lpipos >= 0 )
8787 {
8788#ifndef NDEBUG
8789 /* do not check consistency of data with LPI in case of LPI=none */
8790 if( !lpinone )
8791 {
8792 SCIP_Real lpiobj;
8793 SCIP_Real lpilb;
8794 SCIP_Real lpiub;
8795
8796 SCIP_CALL( SCIPlpiGetObj(lp->lpi, col->lpipos, col->lpipos, &lpiobj) );
8797 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, col->lpipos, col->lpipos, &lpilb, &lpiub) );
8798 assert(SCIPsetIsSumEQ(set, lpiobj, col->flushedobj));
8799 assert(SCIPsetIsSumEQ(set, lpilb, col->flushedlb));
8800 assert(SCIPsetIsSumEQ(set, lpiub, col->flushedub));
8801 assert(col->flushedobj == col->obj); /*lint !e777*/
8802 assert(col->flushedlb == (SCIPsetIsInfinity(set, -col->lb) ? -SCIPlpiInfinity(lp->lpi) : col->lb)); /*lint !e777*/
8803 assert(col->flushedub == (SCIPsetIsInfinity(set, col->ub) ? SCIPlpiInfinity(lp->lpi) : col->ub)); /*lint !e777*/
8804 }
8805#endif
8806 col->objchanged = FALSE;
8807 col->lbchanged = FALSE;
8808 col->ubchanged = FALSE;
8809 }
8810 /* maybe lb/ub/objchanged should be set to false also when lpipos is -1 */
8811 }
8812 lp->nchgcols = 0;
8813
8814 /* mark the changed rows to be unchanged, and check, if this is really correct */
8815 for( i = 0; i < lp->nchgrows; ++i )
8816 {
8817 SCIP_ROW* row;
8818
8819 row = lp->chgrows[i];
8820 assert(row != NULL);
8821
8822 if( row->lpipos >= 0 )
8823 {
8824#ifndef NDEBUG
8825 /* do not check consistency of data with LPI in case of LPI=none */
8826 if( !lpinone )
8827 {
8828 SCIP_Real lpilhs;
8829 SCIP_Real lpirhs;
8830
8831 SCIP_CALL( SCIPlpiGetSides(lp->lpi, row->lpipos, row->lpipos, &lpilhs, &lpirhs) );
8832 assert(SCIPsetIsSumEQ(set, lpilhs, row->flushedlhs));
8833 assert(SCIPsetIsSumEQ(set, lpirhs, row->flushedrhs));
8834 assert(row->flushedlhs == (SCIPsetIsInfinity(set, -row->lhs) ? -SCIPlpiInfinity(lp->lpi) : row->lhs - row->constant)); /*lint !e777*/
8835 assert(row->flushedrhs == (SCIPsetIsInfinity(set, row->rhs) ? SCIPlpiInfinity(lp->lpi) : row->rhs - row->constant)); /*lint !e777*/
8836 }
8837#endif
8838 row->lhschanged = FALSE;
8839 row->rhschanged = FALSE;
8840 }
8841 }
8842 lp->nchgrows = 0;
8843
8844 /* mark the LP to be flushed */
8845 lp->flushed = TRUE;
8846
8847 checkLinks(lp);
8848
8849 return SCIP_OKAY;
8850}
8851
8852
8853
8854
8855/*
8856 * LP methods
8857 */
8858
8859/** updates link data after addition of column */
8860static
8862 SCIP_COL* col, /**< LP column */
8863 SCIP_SET* set /**< global SCIP settings */
8864 )
8865{
8866 SCIP_ROW* row;
8867 int i;
8868 int pos;
8869
8870 assert(col != NULL);
8871 assert(col->lppos >= 0);
8872
8873 /* update column arrays of all linked rows */
8874 for( i = 0; i < col->len; ++i )
8875 {
8876 pos = col->linkpos[i];
8877 if( pos >= 0 )
8878 {
8879 row = col->rows[i];
8880 assert(row != NULL);
8881 assert(row->linkpos[pos] == i);
8882 assert(row->cols[pos] == col);
8883 assert(row->nlpcols <= pos && pos < row->len);
8884
8885 row->nlpcols++;
8886 rowSwapCoefs(row, pos, row->nlpcols-1);
8887 assert(row->cols[row->nlpcols-1] == col);
8888
8889 /* if no swap was necessary, mark lpcols to be unsorted */
8890 if( pos == row->nlpcols-1 )
8891 row->lpcolssorted = FALSE;
8892
8893 /* update norms */
8894 rowAddNorms(row, set, col, row->vals[row->nlpcols-1], FALSE);
8895 }
8896 }
8897}
8898
8899/** updates link data after addition of row */
8900static
8902 SCIP_ROW* row /**< LP row */
8903 )
8904{
8905 SCIP_COL* col;
8906 int i;
8907 int pos;
8908
8909 assert(row != NULL);
8910 assert(row->lppos >= 0);
8911
8912 /* update row arrays of all linked columns */
8913 for( i = 0; i < row->len; ++i )
8914 {
8915 pos = row->linkpos[i];
8916 if( pos >= 0 )
8917 {
8918 col = row->cols[i];
8919 assert(col != NULL);
8920 assert(col->linkpos[pos] == i);
8921 assert(col->rows[pos] == row);
8922 assert(col->nlprows <= pos && pos < col->len);
8923
8924 col->nlprows++;
8925 colSwapCoefs(col, pos, col->nlprows-1);
8926
8927 /* if no swap was necessary, mark lprows to be unsorted */
8928 if( pos == col->nlprows-1 )
8929 col->lprowssorted = FALSE;
8930 }
8931 }
8932}
8933
8934/** updates link data after removal of column */
8935static
8937 SCIP_COL* col, /**< LP column */
8938 SCIP_SET* set /**< global SCIP settings */
8939 )
8940{
8941 SCIP_ROW* row;
8942 int i;
8943 int pos;
8944
8945 assert(col != NULL);
8946 assert(col->lppos == -1);
8947
8948 /* update column arrays of all linked rows */
8949 for( i = 0; i < col->len; ++i )
8950 {
8951 pos = col->linkpos[i];
8952 if( pos >= 0 )
8953 {
8954 row = col->rows[i];
8955 assert(row != NULL);
8956 assert(row->linkpos[pos] == i);
8957 assert(row->cols[pos] == col);
8958 assert(0 <= pos && pos < row->nlpcols);
8959
8960 /* update norms */
8961 rowDelNorms(row, set, col, row->vals[pos], TRUE, FALSE, FALSE);
8962
8963 row->nlpcols--;
8964 rowSwapCoefs(row, pos, row->nlpcols);
8965
8966 /* if no swap was necessary, mark nonlpcols to be unsorted */
8967 if( pos == row->nlpcols )
8968 row->nonlpcolssorted = FALSE;
8969 }
8970 }
8971}
8972
8973/** updates link data after removal of row */
8974static
8976 SCIP_ROW* row /**< LP row */
8977 )
8978{
8979 SCIP_COL* col;
8980 int i;
8981 int pos;
8982
8983 assert(row != NULL);
8984 assert(row->lppos == -1);
8985
8986 /* update row arrays of all linked columns */
8987 for( i = 0; i < row->len; ++i )
8988 {
8989 pos = row->linkpos[i];
8990 if( pos >= 0 )
8991 {
8992 col = row->cols[i];
8993 assert(col != NULL);
8994 assert(0 <= pos && pos < col->nlprows);
8995 assert(col->linkpos[pos] == i);
8996 assert(col->rows[pos] == row);
8997
8998 col->nlprows--;
8999 colSwapCoefs(col, pos, col->nlprows);
9000
9001 /* if no swap was necessary, mark lprows to be unsorted */
9002 if( pos == col->nlprows )
9003 col->nonlprowssorted = FALSE;
9004 }
9005 }
9006}
9007
9008static
9010 SCIP_LP* lp, /**< LP data object */
9011 int initsize /**< initial size of the arrays */
9012 )
9013{
9014 assert(lp != NULL);
9015 assert(lp->divechgsides == NULL);
9016 assert(lp->divechgsidetypes == NULL);
9017 assert(lp->divechgrows == NULL);
9018 assert(lp->ndivechgsides == 0);
9019 assert(lp->divechgsidessize == 0);
9020 assert(initsize > 0);
9021
9022 lp->divechgsidessize = initsize;
9026
9027 return SCIP_OKAY;
9028}
9029
9030static
9032 SCIP_LP* lp, /**< LP data object */
9033 int minsize, /**< minimal number of elements */
9034 SCIP_Real growfact /**< growing factor */
9035 )
9036{
9037 assert(lp != NULL);
9038 assert(lp->divechgsides != NULL);
9039 assert(lp->divechgsidetypes != NULL);
9040 assert(lp->divechgrows != NULL);
9041 assert(lp->ndivechgsides > 0);
9042 assert(lp->divechgsidessize > 0);
9043 assert(minsize > 0);
9044
9045 if( minsize <= lp->divechgsidessize )
9046 return SCIP_OKAY;
9047
9048 lp->divechgsidessize = MAX(minsize, (int)(lp->divechgsidessize * growfact));
9052
9053 return SCIP_OKAY;
9054}
9055
9056static
9058 SCIP_LP* lp /**< LP data object */
9059 )
9060{
9061 assert(lp != NULL);
9062 assert(lp->divechgsides != NULL);
9063 assert(lp->divechgsidetypes != NULL);
9064 assert(lp->divechgrows != NULL);
9065 assert(lp->ndivechgsides == 0);
9066 assert(lp->divechgsidessize > 0);
9067
9071 lp->divechgsidessize = 0;
9072}
9073
9074#define DIVESTACKINITSIZE 100
9075
9076/** creates empty LP data object */
9078 SCIP_LP** lp, /**< pointer to LP data object */
9079 SCIP_SET* set, /**< global SCIP settings */
9080 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
9081 SCIP_STAT* stat, /**< problem statistics */
9082 const char* name /**< problem name */
9083 )
9084{
9085 SCIP_Bool success;
9086
9087 assert(lp != NULL);
9088 assert(set != NULL);
9089 assert(stat != NULL);
9090 assert(name != NULL);
9091
9093
9094 /* open LP Solver interface */
9095 SCIP_CALL( SCIPlpiCreate(&(*lp)->lpi, messagehdlr, name, SCIP_OBJSEN_MINIMIZE) );
9096
9097 (*lp)->lpicols = NULL;
9098 (*lp)->lpirows = NULL;
9099 (*lp)->chgcols = NULL;
9100 (*lp)->chgrows = NULL;
9101 (*lp)->cols = NULL;
9102 (*lp)->soldirection = NULL;
9103 (*lp)->lazycols = NULL;
9104 (*lp)->rows = NULL;
9105 (*lp)->lpobjval = 0.0;
9106 (*lp)->glbpseudoobjval = 0.0;
9107 (*lp)->relglbpseudoobjval = 0.0;
9108 (*lp)->glbpseudoobjvalid = TRUE;
9109 (*lp)->glbpseudoobjvalinf = 0;
9110 (*lp)->pseudoobjval = 0.0;
9111 (*lp)->relpseudoobjval = 0.0;
9112 (*lp)->pseudoobjvalid = TRUE;
9113 (*lp)->pseudoobjvalinf = 0;
9114 (*lp)->looseobjval = 0.0;
9115 (*lp)->rellooseobjval = 0.0;
9116 (*lp)->looseobjvalid = TRUE;
9117 (*lp)->looseobjvalinf = 0;
9118 (*lp)->nloosevars = 0;
9119 (*lp)->rootlpobjval = SCIP_INVALID;
9120 (*lp)->rootlooseobjval = SCIP_INVALID;
9121 (*lp)->cutoffbound = SCIPsetInfinity(set);
9122 (*lp)->feastol = SCIP_INVALID; /* to have it initialized */
9123 SCIPlpResetFeastol(*lp, set);
9124 (*lp)->validdegeneracylp = -1;
9125 (*lp)->objsqrnorm = 0.0;
9126 (*lp)->objsumnorm = 0.0;
9127 (*lp)->lpicolssize = 0;
9128 (*lp)->nlpicols = 0;
9129 (*lp)->lpirowssize = 0;
9130 (*lp)->nlpirows = 0;
9131 (*lp)->lpifirstchgcol = 0;
9132 (*lp)->lpifirstchgrow = 0;
9133 (*lp)->colssize = 0;
9134 (*lp)->soldirectionsize = 0;
9135 (*lp)->ncols = 0;
9136 (*lp)->lazycolssize = 0;
9137 (*lp)->nlazycols = 0;
9138 (*lp)->rowssize = 0;
9139 (*lp)->nrows = 0;
9140 (*lp)->chgcolssize = 0;
9141 (*lp)->nchgcols = 0;
9142 (*lp)->chgrowssize = 0;
9143 (*lp)->nchgrows = 0;
9144 (*lp)->firstnewcol = 0;
9145 (*lp)->firstnewrow = 0;
9146 (*lp)->nremovablecols = 0;
9147 (*lp)->nremovablerows = 0;
9148 (*lp)->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9149 (*lp)->validfarkaslp = -1;
9150 (*lp)->validsoldirlp = -1;
9151 (*lp)->validsoldirsol = NULL;
9152 (*lp)->objsqrnormunreliable = FALSE;
9153 (*lp)->flushdeletedcols = FALSE;
9154 (*lp)->flushaddedcols = FALSE;
9155 (*lp)->flushdeletedrows = FALSE;
9156 (*lp)->flushaddedrows = FALSE;
9157 (*lp)->updateintegrality = TRUE;
9158 (*lp)->flushed = TRUE;
9159 (*lp)->lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
9160 (*lp)->solved = TRUE;
9161 (*lp)->primalfeasible = TRUE;
9162 (*lp)->primalchecked = TRUE;
9163 (*lp)->dualfeasible = TRUE;
9164 (*lp)->dualchecked = TRUE;
9165 (*lp)->solisbasic = FALSE;
9166 (*lp)->rootlpisrelax = TRUE;
9167 (*lp)->isrelax = TRUE;
9168 (*lp)->installing = FALSE;
9169 (*lp)->strongbranching = FALSE;
9170 (*lp)->strongbranchprobing = FALSE;
9171 (*lp)->probing = FALSE;
9172 (*lp)->diving = FALSE;
9173 (*lp)->divingobjchg = FALSE;
9174 (*lp)->divinglazyapplied = FALSE;
9175 (*lp)->divelpistate = NULL;
9176 (*lp)->divelpwasprimfeas = TRUE;
9177 (*lp)->divelpwasprimchecked = TRUE;
9178 (*lp)->divelpwasdualfeas = TRUE;
9179 (*lp)->divelpwasdualchecked = TRUE;
9180 (*lp)->divechgsides = NULL;
9181 (*lp)->divechgsidetypes = NULL;
9182 (*lp)->divechgrows = NULL;
9183 (*lp)->ndivechgsides = 0;
9184 (*lp)->divechgsidessize = 0;
9185 (*lp)->ndivingrows = 0;
9186 (*lp)->divinglpiitlim = INT_MAX;
9187 (*lp)->resolvelperror = FALSE;
9188 (*lp)->divenolddomchgs = 0;
9189 (*lp)->adjustlpval = FALSE;
9190 (*lp)->lpiobjlim = SCIPlpiInfinity((*lp)->lpi);
9191 (*lp)->lpifeastol = (*lp)->feastol;
9192 (*lp)->lpidualfeastol = SCIPsetDualfeastol(set);
9193 (*lp)->lpibarrierconvtol = SCIPsetBarrierconvtol(set);
9194 (*lp)->lpifromscratch = FALSE;
9195 (*lp)->lpifastmip = set->lp_fastmip;
9196 (*lp)->lpiscaling = set->lp_scaling;
9197 (*lp)->lpipresolving = set->lp_presolving;
9198 (*lp)->lpilpinfo = set->disp_lpinfo;
9199 (*lp)->lpirowrepswitch = set->lp_rowrepswitch;
9200 (*lp)->lpisolutionpolishing = (set->lp_solutionpolishing > 0);
9201 (*lp)->lpirefactorinterval = set->lp_refactorinterval;
9202 (*lp)->lpiconditionlimit = set->lp_conditionlimit;
9203 (*lp)->lpimarkowitz = set->lp_markowitz;
9204 (*lp)->lpiitlim = INT_MAX;
9205 (*lp)->lpipricing = SCIP_PRICING_AUTO;
9206 (*lp)->lastlpalgo = SCIP_LPALGO_DUALSIMPLEX;
9207 (*lp)->lpithreads = set->lp_threads;
9208 (*lp)->lpitiming = (int) set->time_clocktype;
9209 (*lp)->lpirandomseed = set->random_randomseed;
9210 (*lp)->storedsolvals = NULL;
9211
9212 /* allocate arrays for diving */
9214
9215 /* set default parameters in LP solver */
9216 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_OBJLIM, (*lp)->lpiobjlim, &success) );
9217 if( !success )
9218 {
9219 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9220 "LP Solver <%s>: objective limit cannot be set -- can lead to unnecessary simplex iterations\n",
9222 }
9223 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_FEASTOL, (*lp)->lpifeastol, &success) );
9224 (*lp)->lpihasfeastol = success;
9225 if( !success )
9226 {
9227 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9228 "LP Solver <%s>: primal feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9230 }
9231 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_DUALFEASTOL, (*lp)->lpidualfeastol, &success) );
9232 (*lp)->lpihasdualfeastol = success;
9233 if( !success )
9234 {
9235 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9236 "LP Solver <%s>: dual feasibility tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9238 }
9239 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_BARRIERCONVTOL, (*lp)->lpibarrierconvtol, &success) );
9240 (*lp)->lpihasbarrierconvtol = success;
9241 if( !success )
9242 {
9243 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9244 "LP Solver <%s>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ\n",
9246 }
9247 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_FROMSCRATCH, (*lp)->lpifromscratch, &success) );
9248 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_FASTMIP, (*lp)->lpifastmip, &success) );
9249 (*lp)->lpihasfastmip = success;
9250 if( !success )
9251 {
9252 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9253 "LP Solver <%s>: fastmip setting not available -- SCIP parameter has no effect\n",
9255 }
9256 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_SCALING, (*lp)->lpiscaling, &success) );
9257 (*lp)->lpihasscaling = success;
9258 if( !success )
9259 {
9260 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9261 "LP Solver <%s>: scaling not available -- SCIP parameter has no effect\n",
9263 }
9264 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_PRESOLVING, (*lp)->lpipresolving, &success) );
9265 (*lp)->lpihaspresolving = success;
9266 if( !success )
9267 {
9268 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9269 "LP Solver <%s>: presolving not available -- SCIP parameter has no effect\n",
9271 }
9272 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_TIMING, (*lp)->lpitiming, &success) );
9273 if( !success )
9274 {
9275 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9276 "LP Solver <%s>: clock type cannot be set\n",
9278 }
9279 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_LPITLIM, (*lp)->lpiitlim, &success) );
9280 if( !success )
9281 {
9282 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9283 "LP Solver <%s>: iteration limit cannot be set -- can lead to unnecessary simplex iterations\n",
9285 }
9286 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_PRICING, (int)(*lp)->lpipricing, &success) );
9287 if( !success )
9288 {
9289 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9290 "LP Solver <%s>: pricing strategy cannot be set -- SCIP parameter has no effect\n",
9292 }
9293 SCIP_CALL( lpSetBoolpar(*lp, SCIP_LPPAR_LPINFO, (*lp)->lpilpinfo, &success) );
9294 if( !success )
9295 {
9296 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9297 "LP Solver <%s>: lpinfo setting not available -- SCIP parameter has no effect\n",
9299 }
9300 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_ROWREPSWITCH, (*lp)->lpirowrepswitch, &success) );
9301 (*lp)->lpihasrowrep = success;
9302 if( !success )
9303 {
9304 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9305 "LP Solver <%s>: row representation of the basis not available -- SCIP parameter lp/rowrepswitch has no effect\n",
9307 }
9308 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_POLISHING, ((*lp)->lpisolutionpolishing ? 1 : 0), &success) );
9309 (*lp)->lpihaspolishing = success;
9310 if( !success )
9311 {
9312 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9313 "LP Solver <%s>: solution polishing not available -- SCIP parameter lp/solutionpolishing has no effect\n",
9315 }
9316 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_REFACTOR, (*lp)->lpirefactorinterval, &success) );
9317 (*lp)->lpihasrefactor = success;
9318 if( !success )
9319 {
9320 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9321 "LP Solver <%s>: refactorization interval not available -- SCIP parameter lp/refactorinterval has no effect\n",
9323 }
9324 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_CONDITIONLIMIT, (*lp)->lpiconditionlimit, &success) );
9325 if( !success )
9326 {
9327 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9328 "LP Solver <%s>: condition number limit for the basis not available -- SCIP parameter lp/conditionlimit has no effect\n",
9330 }
9331 SCIP_CALL( lpSetRealpar(*lp, SCIP_LPPAR_MARKOWITZ, (*lp)->lpimarkowitz, &success) );
9332 if( !success )
9333 {
9334 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9335 "LP Solver <%s>: markowitz threshhold not available -- SCIP parameter lp/minmarkowitz has no effect\n",
9337 }
9338 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_THREADS, (*lp)->lpithreads, &success) );
9339 if( !success )
9340 {
9341 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9342 "LP Solver <%s>: number of threads settings not available -- SCIP parameter has no effect\n",
9344 }
9345 /* keep the default LP random seed if this parameter is set to 0 (current default) */
9346 if( (*lp)->lpirandomseed != 0 )
9347 {
9348 SCIP_CALL( lpSetIntpar(*lp, SCIP_LPPAR_RANDOMSEED, (*lp)->lpirandomseed, &success) );
9349 if( !success )
9350 {
9351 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
9352 "LP Solver <%s>: random seed parameter not available -- SCIP parameter has no effect\n",
9354 }
9355 }
9356
9357 /* Check that infinity value of LP-solver is at least as large as the one used in SCIP. This is necessary, because we
9358 * transfer SCIP infinity values to the ones by the LPI, but not the converse. */
9359 if ( set->num_infinity > SCIPlpiInfinity((*lp)->lpi) )
9360 {
9361 SCIPerrorMessage("The infinity value of the LP solver has to be at least as large as the one of SCIP.\n");
9363 }
9364
9365 return SCIP_OKAY;
9366}
9367
9368/** frees LP data object */
9370 SCIP_LP** lp, /**< pointer to LP data object */
9371 BMS_BLKMEM* blkmem, /**< block memory */
9372 SCIP_SET* set, /**< global SCIP settings */
9373 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9374 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9375 )
9376{
9377 int i;
9378
9379 assert(lp != NULL);
9380 assert(*lp != NULL);
9381
9382 SCIP_CALL( SCIPlpClear(*lp, blkmem, set, eventqueue, eventfilter) );
9383
9385
9386 /* release LPI rows */
9387 for( i = 0; i < (*lp)->nlpirows; ++i )
9388 {
9389 SCIP_CALL( SCIProwRelease(&(*lp)->lpirows[i], blkmem, set, *lp) );
9390 }
9391
9392 if( (*lp)->lpi != NULL )
9393 {
9394 SCIP_CALL( SCIPlpiFree(&(*lp)->lpi) );
9395 }
9396
9397 BMSfreeMemoryNull(&(*lp)->storedsolvals);
9398 BMSfreeMemoryArrayNull(&(*lp)->lpicols);
9399 BMSfreeMemoryArrayNull(&(*lp)->lpirows);
9400 BMSfreeMemoryArrayNull(&(*lp)->chgcols);
9401 BMSfreeMemoryArrayNull(&(*lp)->chgrows);
9402 BMSfreeMemoryArrayNull(&(*lp)->lazycols);
9403 BMSfreeMemoryArrayNull(&(*lp)->cols);
9404 BMSfreeMemoryArrayNull(&(*lp)->rows);
9405 BMSfreeMemoryArrayNull(&(*lp)->soldirection);
9406 BMSfreeMemory(lp);
9407
9408 return SCIP_OKAY;
9409}
9410
9411/** resets the LP to the empty LP by removing all columns and rows from LP, releasing all rows, and flushing the
9412 * changes to the LP solver
9413 */
9415 SCIP_LP* lp, /**< LP data */
9416 BMS_BLKMEM* blkmem, /**< block memory */
9417 SCIP_SET* set, /**< global SCIP settings */
9418 SCIP_PROB* prob, /**< problem data */
9419 SCIP_STAT* stat, /**< problem statistics */
9420 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9421 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9422 )
9423{
9424 assert(stat != NULL);
9425
9426 SCIP_CALL( SCIPlpClear(lp, blkmem, set, eventqueue, eventfilter) );
9427 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
9428
9429 /* mark the empty LP to be solved */
9431 lp->lpobjval = 0.0;
9432 lp->validsollp = stat->lpcount; /* the initial (empty) SCIP_LP is solved with primal and dual solution of zero */
9433 lp->validfarkaslp = -1;
9434 lp->validdegeneracylp = -1;
9435 lp->validsoldirlp = -1;
9436 lp->validsoldirsol = NULL;
9437 lp->solved = TRUE;
9438 lp->primalfeasible = TRUE;
9439 lp->primalchecked = TRUE;
9440 lp->dualfeasible = TRUE;
9441 lp->dualchecked = TRUE;
9442 lp->solisbasic = FALSE;
9444
9445 return SCIP_OKAY;
9446}
9447
9448/** adds a column to the LP */
9450 SCIP_LP* lp, /**< LP data */
9451 SCIP_SET* set, /**< global SCIP settings */
9452 SCIP_COL* col, /**< LP column */
9453 int depth /**< depth in the tree where the column addition is performed */
9454 )
9455{
9456 assert(lp != NULL);
9457 assert(!lp->diving);
9458 assert(col != NULL);
9459 assert(col->len == 0 || col->rows != NULL);
9460 assert(col->lppos == -1);
9461 assert(col->var != NULL);
9463 assert(SCIPvarGetCol(col->var) == col);
9464 assert(SCIPvarIsIntegral(col->var) == col->integral);
9465
9466 SCIPsetDebugMsg(set, "adding column <%s> to LP (%d rows, %d cols)\n", SCIPvarGetName(col->var), lp->nrows, lp->ncols);
9467#ifdef SCIP_DEBUG
9468 {
9469 int i;
9470 SCIPsetDebugMsgPrint(set, " (obj: %g) [%g,%g]", col->obj, col->lb, col->ub);
9471 for( i = 0; i < col->len; ++i )
9472 SCIPsetDebugMsgPrint(set, " %+g<%s>", col->vals[i], col->rows[i]->name);
9474 }
9475#endif
9476
9477 SCIP_CALL( ensureColsSize(lp, set, lp->ncols+1) );
9478 lp->cols[lp->ncols] = col;
9479 col->lppos = lp->ncols;
9480 col->lpdepth = depth;
9481 col->age = 0;
9482 lp->ncols++;
9483 if( col->removable )
9484 lp->nremovablecols++;
9485
9486 if( !SCIPsetIsInfinity(set, -col->lazylb) || !SCIPsetIsInfinity(set, col->lazyub) )
9487 {
9489 lp->lazycols[lp->nlazycols] = col;
9490 lp->nlazycols++;
9491 }
9492
9493 /* mark the current LP unflushed */
9494 lp->flushed = FALSE;
9495
9496 /* update column arrays of all linked rows */
9497 colUpdateAddLP(col, set);
9498
9499 /* update the objective function vector norms */
9500 lpUpdateObjNorms(lp, set, 0.0, col->unchangedobj);
9501
9502 checkLinks(lp);
9503
9504 return SCIP_OKAY;
9505}
9506
9507/** adds a row to the LP and captures it */
9509 SCIP_LP* lp, /**< LP data */
9510 BMS_BLKMEM* blkmem, /**< block memory buffers */
9511 SCIP_SET* set, /**< global SCIP settings */
9512 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9513 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9514 SCIP_ROW* row, /**< LP row */
9515 int depth /**< depth in the tree where the row addition is performed */
9516 )
9517{
9518 assert(lp != NULL);
9519 assert(row != NULL);
9520 assert(row->len == 0 || row->cols != NULL);
9521 assert(row->lppos == -1);
9522
9523 SCIProwCapture(row);
9524 SCIProwLock(row);
9525
9526 SCIPsetDebugMsg(set, "adding row <%s> to LP (%d rows, %d cols)\n", row->name, lp->nrows, lp->ncols);
9527#ifdef SCIP_DEBUG
9528 {
9529 int i;
9530 SCIPsetDebugMsgPrint(set, " %g <=", row->lhs);
9531 for( i = 0; i < row->len; ++i )
9532 SCIPsetDebugMsgPrint(set, " %+g<%s>", row->vals[i], SCIPvarGetName(row->cols[i]->var));
9533 if( !SCIPsetIsZero(set, row->constant) )
9534 SCIPsetDebugMsgPrint(set, " %+g", row->constant);
9535 SCIPsetDebugMsgPrint(set, " <= %g\n", row->rhs);
9536 }
9537#endif
9538
9539 SCIP_CALL( ensureRowsSize(lp, set, lp->nrows+1) );
9540 lp->rows[lp->nrows] = row;
9541 row->lppos = lp->nrows;
9542 row->lpdepth = depth;
9543 row->age = 0;
9544 lp->nrows++;
9545 if( row->removable )
9546 lp->nremovablerows++;
9547
9548 /* mark the current LP unflushed */
9549 lp->flushed = FALSE;
9550
9551 /* update row arrays of all linked columns */
9552 rowUpdateAddLP(row);
9553
9554 checkLinks(lp);
9555
9556 rowCalcNorms(row, set);
9557
9558 /* check, if row addition to LP events are tracked
9559 * if so, issue ROWADDEDLP event
9560 */
9561 if( (eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDLP) != 0) )
9562 {
9563 SCIP_EVENT* event;
9564
9565 SCIP_CALL( SCIPeventCreateRowAddedLP(&event, blkmem, row) );
9566 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9567 }
9568
9569 return SCIP_OKAY;
9570}
9571
9572
9573#ifndef NDEBUG
9574/** method checks if all columns in the lazycols array have at least one lazy bound and also have a counter part in the
9575 * cols array; furthermore, it is checked if columns in the cols array which have a lazy bound have a counter part in
9576 * the lazycols array
9577 */
9578static
9580 SCIP_LP* lp, /**< LP data */
9581 SCIP_SET* set /**< global SCIP settings */
9582 )
9583{
9584 SCIP_Bool contained;
9585 int c;
9586 int i;
9587
9588 assert(lp != NULL);
9589
9590 /* check if each column in the lazy column array has a counter part in the column array */
9591 for( i = 0; i < lp->nlazycols; ++i )
9592 {
9593 /* check if each lazy column has at least on lazy bound */
9594 assert(lp->lazycols[i] != NULL);
9595 assert(!SCIPsetIsInfinity(set, lp->lazycols[i]->lazyub) || !SCIPsetIsInfinity(set, -lp->lazycols[i]->lazylb));
9596
9597 contained = FALSE;
9598 for( c = 0; c < lp->ncols; ++c )
9599 {
9600 if( lp->lazycols[i] == lp->cols[c] )
9601 {
9602 assert(!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb));
9603 contained = TRUE;
9604 }
9605 }
9606 assert(contained);
9607 }
9608
9609 /* check if each column in the column array which has at least one lazy bound has a counter part in the lazy column *
9610 * array */
9611 for( c = 0; c < lp->ncols; ++c )
9612 {
9613 contained = FALSE;
9614 assert(lp->cols[c] != NULL);
9615
9616 for( i = 0; i < lp->nlazycols; ++i )
9617 {
9618 if( lp->lazycols[i] == lp->cols[c] )
9619 {
9620 contained = TRUE;
9621 }
9622 }
9623
9624 assert(contained == (!SCIPsetIsInfinity(set, lp->cols[c]->lazyub) || !SCIPsetIsInfinity(set, -lp->cols[c]->lazylb)));
9625 }
9626}
9627#else
9628#define checkLazyColArray(lp, set) /**/
9629#endif
9630
9631/** removes all columns after the given number of cols from the LP */
9633 SCIP_LP* lp, /**< LP data */
9634 SCIP_SET* set, /**< global SCIP settings */
9635 int newncols /**< new number of columns in the LP */
9636 )
9637{
9638 SCIP_COL* col;
9639 int c;
9640
9641 assert(lp != NULL);
9642
9643 SCIPsetDebugMsg(set, "shrinking LP from %d to %d columns\n", lp->ncols, newncols);
9644 assert(0 <= newncols);
9645 assert(newncols <= lp->ncols);
9646
9647 if( newncols < lp->ncols )
9648 {
9649 assert(!lp->diving);
9650
9651 for( c = lp->ncols-1; c >= newncols; --c )
9652 {
9653 col = lp->cols[c];
9654 assert(col != NULL);
9655 assert(col->len == 0 || col->rows != NULL);
9656 assert(col->var != NULL);
9658 assert(SCIPvarGetCol(col->var) == lp->cols[c]);
9659 assert(col->lppos == c);
9660
9661 /* mark column to be removed from the LP */
9662 col->lppos = -1;
9663 col->lpdepth = -1;
9664 lp->ncols--;
9665
9666 /* count removable columns */
9667 if( col->removable )
9668 lp->nremovablecols--;
9669
9670 /* update column arrays of all linked rows */
9671 colUpdateDelLP(col, set);
9672
9673 /* update the objective function vector norms */
9674 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
9675 }
9676 assert(lp->ncols == newncols);
9677 lp->lpifirstchgcol = MIN(lp->lpifirstchgcol, newncols);
9678
9679 /* remove columns which are deleted from the lazy column array */
9680 c = 0;
9681 while( c < lp->nlazycols )
9682 {
9683 if( lp->lazycols[c]->lppos < 0 )
9684 {
9685 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
9686 lp->nlazycols--;
9687 }
9688 else
9689 c++;
9690 }
9691
9692 /* mark the current LP unflushed */
9693 lp->flushed = FALSE;
9694
9696 checkLinks(lp);
9697 }
9698 assert(lp->nremovablecols <= lp->ncols);
9699
9700 return SCIP_OKAY;
9701}
9702
9703/** removes and releases all rows after the given number of rows from the LP */
9705 SCIP_LP* lp, /**< LP data */
9706 BMS_BLKMEM* blkmem, /**< block memory */
9707 SCIP_SET* set, /**< global SCIP settings */
9708 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9709 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
9710 int newnrows /**< new number of rows in the LP */
9711 )
9712{
9713 SCIP_ROW* row;
9714 int r;
9715
9716 assert(lp != NULL);
9717 assert(0 <= newnrows && newnrows <= lp->nrows);
9718
9719 SCIPsetDebugMsg(set, "shrinking LP from %d to %d rows\n", lp->nrows, newnrows);
9720 if( newnrows < lp->nrows )
9721 {
9722 for( r = lp->nrows-1; r >= newnrows; --r )
9723 {
9724 row = lp->rows[r];
9725 assert(row != NULL);
9726 assert(row->len == 0 || row->cols != NULL);
9727 assert(row->lppos == r);
9728
9729 /* mark row to be removed from the LP */
9730 row->lppos = -1;
9731 row->lpdepth = -1;
9732 lp->nrows--;
9733
9734 /* count removable rows */
9735 if( row->removable )
9736 lp->nremovablerows--;
9737
9738 /* update row arrays of all linked columns */
9739 rowUpdateDelLP(row);
9740
9741 SCIProwUnlock(lp->rows[r]);
9742
9743 /* check, if row deletion events are tracked
9744 * if so, issue ROWDELETEDLP event
9745 */
9746 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
9747 {
9748 SCIP_EVENT* event;
9749
9750 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, lp->rows[r]) );
9751 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
9752 }
9753
9754 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
9755 }
9756 assert(lp->nrows == newnrows);
9757 lp->lpifirstchgrow = MIN(lp->lpifirstchgrow, newnrows);
9758
9759 /* mark the current LP unflushed */
9760 lp->flushed = FALSE;
9761
9762 checkLinks(lp);
9763 }
9764 assert(lp->nremovablerows <= lp->nrows);
9765
9766 return SCIP_OKAY;
9767}
9768
9769/** removes all columns and rows from LP, releases all rows */
9771 SCIP_LP* lp, /**< LP data */
9772 BMS_BLKMEM* blkmem, /**< block memory */
9773 SCIP_SET* set, /**< global SCIP settings */
9774 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9775 SCIP_EVENTFILTER* eventfilter /**< global event filter */
9776 )
9777{
9778 assert(lp != NULL);
9779 assert(!lp->diving);
9780
9781 SCIPsetDebugMsg(set, "clearing LP\n");
9782 SCIP_CALL( SCIPlpShrinkCols(lp, set, 0) );
9783 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, 0) );
9784
9785 return SCIP_OKAY;
9786}
9787
9788/** remembers number of columns and rows to track the newly added ones */
9790 SCIP_LP* lp /**< current LP data */
9791 )
9792{
9793 assert(lp != NULL);
9794 assert(!lp->diving);
9795
9796 lp->firstnewrow = lp->nrows;
9797 lp->firstnewcol = lp->ncols;
9798}
9799
9800/** sets the remembered number of columns and rows to the given values */
9802 SCIP_LP* lp, /**< current LP data */
9803 int nrows, /**< number of rows to set the size marker to */
9804 int ncols /**< number of columns to set the size marker to */
9805 )
9806{
9807 assert(lp != NULL);
9808 assert(!lp->diving);
9809
9810 lp->firstnewrow = nrows;
9811 lp->firstnewcol = ncols;
9812}
9813
9814/** gets all indices of basic columns and rows: index i >= 0 corresponds to column i, index i < 0 to row -i-1 */
9816 SCIP_LP* lp, /**< LP data */
9817 int* basisind /**< pointer to store basis indices ready to keep number of rows entries */
9818 )
9819{
9820 assert(lp != NULL);
9821 assert(lp->flushed);
9822 assert(lp->solved);
9823 assert(lp->solisbasic);
9824 assert(basisind != NULL);
9825
9826 SCIP_CALL( SCIPlpiGetBasisInd(lp->lpi, basisind) );
9827
9828 return SCIP_OKAY;
9829}
9830
9831/** gets current basis status for columns and rows; arrays must be large enough to store the basis status */
9833 SCIP_LP* lp, /**< LP data */
9834 int* cstat, /**< array to store column basis status, or NULL */
9835 int* rstat /**< array to store row basis status, or NULL */
9836 )
9837{
9838 assert(lp != NULL);
9839 assert(lp->flushed);
9840 assert(lp->solved);
9841 assert(lp->solisbasic);
9842
9843 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
9844
9845 return SCIP_OKAY;
9846}
9847
9848/** gets a row from the inverse basis matrix B^-1 */
9850 SCIP_LP* lp, /**< LP data */
9851 int r, /**< row number */
9852 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9853 int* inds, /**< array to store the non-zero indices, or NULL */
9854 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9855 * (-1: if we do not store sparsity informations) */
9856 )
9857{
9858 assert(lp != NULL);
9859 assert(lp->flushed);
9860 assert(lp->solved);
9861 assert(lp->solisbasic);
9862 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9863 assert(coef != NULL);
9864
9865 SCIP_CALL( SCIPlpiGetBInvRow(lp->lpi, r, coef, inds, ninds) );
9866
9867 return SCIP_OKAY;
9868}
9869
9870/** gets a column from the inverse basis matrix B^-1 */
9872 SCIP_LP* lp, /**< LP data */
9873 int c, /**< column number of B^-1; this is NOT the number of the column in the LP
9874 * returned by SCIPcolGetLPPos(); you have to call SCIPgetBasisInd()
9875 * to get the array which links the B^-1 column numbers to the row and
9876 * column numbers of the LP! c must be between 0 and nrows-1, since the
9877 * basis has the size nrows * nrows */
9878 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9879 int* inds, /**< array to store the non-zero indices, or NULL */
9880 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9881 * (-1: if we do not store sparsity informations) */
9882 )
9883{
9884 assert(lp != NULL);
9885 assert(lp->flushed);
9886 assert(lp->solved);
9887 assert(lp->solisbasic);
9888 assert(0 <= c && c < lp->nrows); /* the basis matrix is nrows x nrows */
9889 assert(coef != NULL);
9890
9891 SCIP_CALL( SCIPlpiGetBInvCol(lp->lpi, c, coef, inds, ninds) );
9892
9893 return SCIP_OKAY;
9894}
9895
9896/** gets a row from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A) */
9898 SCIP_LP* lp, /**< LP data */
9899 int r, /**< row number */
9900 SCIP_Real* binvrow, /**< row in B^-1 from prior call to SCIPlpGetBInvRow(), or NULL */
9901 SCIP_Real* coef, /**< pointer to store the coefficients of the row */
9902 int* inds, /**< array to store the non-zero indices, or NULL */
9903 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9904 * (-1: if we do not store sparsity informations) */
9905 )
9906{
9907 assert(lp != NULL);
9908 assert(lp->flushed);
9909 assert(lp->solved);
9910 assert(lp->solisbasic);
9911 assert(0 <= r && r < lp->nrows); /* the basis matrix is nrows x nrows */
9912 assert(coef != NULL);
9913
9914 SCIP_CALL( SCIPlpiGetBInvARow(lp->lpi, r, binvrow, coef, inds, ninds) );
9915
9916 return SCIP_OKAY;
9917}
9918
9919/** gets a column from the product of inverse basis matrix B^-1 and coefficient matrix A (i.e. from B^-1 * A),
9920 * i.e., it computes B^-1 * A_c with A_c being the c'th column of A
9921 */
9923 SCIP_LP* lp, /**< LP data */
9924 int c, /**< column number which can be accessed by SCIPcolGetLPPos() */
9925 SCIP_Real* coef, /**< pointer to store the coefficients of the column */
9926 int* inds, /**< array to store the non-zero indices, or NULL */
9927 int* ninds /**< pointer to store the number of non-zero indices, or NULL
9928 * (-1: if we do not store sparsity informations) */
9929 )
9930{
9931 assert(lp != NULL);
9932 assert(lp->flushed);
9933 assert(lp->solved);
9934 assert(lp->solisbasic);
9935 assert(0 <= c && c < lp->ncols);
9936 assert(coef != NULL);
9937
9938 SCIP_CALL( SCIPlpiGetBInvACol(lp->lpi, c, coef, inds, ninds) );
9939
9940 return SCIP_OKAY;
9941}
9942
9943/** calculates a weighted sum of all LP rows; for negative weights, the left and right hand side of the corresponding
9944 * LP row are swapped in the summation
9945 */
9947 SCIP_LP* lp, /**< LP data */
9948 SCIP_SET* set, /**< global SCIP settings */
9949 SCIP_PROB* prob, /**< problem data */
9950 SCIP_Real* weights, /**< row weights in row summation */
9951 SCIP_REALARRAY* sumcoef, /**< array to store sum coefficients indexed by variables' probindex */
9952 SCIP_Real* sumlhs, /**< pointer to store the left hand side of the row summation */
9953 SCIP_Real* sumrhs /**< pointer to store the right hand side of the row summation */
9954 )
9955{
9956 SCIP_ROW* row;
9957 int r;
9958 int i;
9959 int idx;
9960 SCIP_Bool lhsinfinite;
9961 SCIP_Bool rhsinfinite;
9962
9963 assert(lp != NULL);
9964 assert(prob != NULL);
9965 assert(weights != NULL);
9966 assert(sumcoef != NULL);
9967 assert(sumlhs != NULL);
9968 assert(sumrhs != NULL);
9969
9970 /**@todo test, if a column based summation is faster */
9971
9972 SCIP_CALL( SCIPrealarrayClear(sumcoef) );
9973 SCIP_CALL( SCIPrealarrayExtend(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, 0, prob->nvars-1) );
9974 *sumlhs = 0.0;
9975 *sumrhs = 0.0;
9976 lhsinfinite = FALSE;
9977 rhsinfinite = FALSE;
9978 for( r = 0; r < lp->nrows; ++r )
9979 {
9980 if( !SCIPsetIsZero(set, weights[r]) )
9981 {
9982 row = lp->rows[r];
9983 assert(row != NULL);
9984 assert(row->len == 0 || row->cols != NULL);
9985 assert(row->len == 0 || row->cols_index != NULL);
9986 assert(row->len == 0 || row->vals != NULL);
9987
9988 /* add the row coefficients to the sum */
9989 for( i = 0; i < row->len; ++i )
9990 {
9991 assert(row->cols[i] != NULL);
9992 assert(row->cols[i]->var != NULL);
9993 assert(SCIPvarGetStatus(row->cols[i]->var) == SCIP_VARSTATUS_COLUMN);
9994 assert(SCIPvarGetCol(row->cols[i]->var) == row->cols[i]);
9995 assert(SCIPvarGetProbindex(row->cols[i]->var) == row->cols[i]->var_probindex);
9996 idx = row->cols[i]->var_probindex;
9997 assert(0 <= idx && idx < prob->nvars);
9998 SCIP_CALL( SCIPrealarrayIncVal(sumcoef, set->mem_arraygrowinit, set->mem_arraygrowfac, idx, weights[r] * row->vals[i]) );
9999 }
10000
10001 /* add the row sides to the sum, depending on the sign of the weight */
10002 if( weights[r] > 0.0 )
10003 {
10004 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10005 if( !lhsinfinite )
10006 (*sumlhs) += weights[r] * (row->lhs - row->constant);
10007 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10008 if( !rhsinfinite )
10009 (*sumrhs) += weights[r] * (row->rhs - row->constant);
10010 }
10011 else
10012 {
10013 lhsinfinite = lhsinfinite || SCIPsetIsInfinity(set, row->rhs);
10014 if( !lhsinfinite )
10015 (*sumlhs) += weights[r] * (row->rhs - row->constant);
10016 rhsinfinite = rhsinfinite || SCIPsetIsInfinity(set, -row->lhs);
10017 if( !rhsinfinite )
10018 (*sumrhs) += weights[r] * (row->lhs - row->constant);
10019 }
10020 }
10021 }
10022
10023 if( lhsinfinite )
10024 *sumlhs = -SCIPsetInfinity(set);
10025 if( rhsinfinite )
10026 *sumrhs = SCIPsetInfinity(set);
10027
10028 return SCIP_OKAY;
10029}
10030
10031/** stores LP state (like basis information) into LP state object */
10033 SCIP_LP* lp, /**< LP data */
10034 BMS_BLKMEM* blkmem, /**< block memory */
10035 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10036 )
10037{
10038 assert(lp != NULL);
10039 assert(lp->flushed);
10040 assert(lp->solved);
10041 assert(blkmem != NULL);
10042 assert(lpistate != NULL);
10043
10044 /* check whether there is no lp */
10045 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10046 *lpistate = NULL;
10047 else
10048 {
10049 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, lpistate) );
10050 }
10051
10052 return SCIP_OKAY;
10053}
10054
10055/** loads LP state (like basis information) into solver */
10057 SCIP_LP* lp, /**< LP data */
10058 BMS_BLKMEM* blkmem, /**< block memory */
10059 SCIP_SET* set, /**< global SCIP settings */
10060 SCIP_PROB* prob, /**< problem data */
10061 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10062 SCIP_LPISTATE* lpistate, /**< LP state information (like basis information) */
10063 SCIP_Bool wasprimfeas, /**< primal feasibility when LP state information was stored */
10064 SCIP_Bool wasprimchecked, /**< true if the LP solution has passed the primal feasibility check */
10065 SCIP_Bool wasdualfeas, /**< dual feasibility when LP state information was stored */
10066 SCIP_Bool wasdualchecked /**< true if the LP solution has passed the dual feasibility check */
10067 )
10068{
10069 assert(lp != NULL);
10070 assert(blkmem != NULL);
10071
10072 /* flush changes to the LP solver */
10073 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
10074 assert(lp->flushed);
10075
10076 if( lp->solved && lp->solisbasic )
10077 return SCIP_OKAY;
10078
10079 /* set LPI state in the LP solver */
10080 if( lpistate == NULL )
10081 lp->solisbasic = FALSE;
10082 else
10083 {
10084 SCIP_CALL( SCIPlpiSetState(lp->lpi, blkmem, lpistate) );
10085 lp->solisbasic = SCIPlpiHasStateBasis(lp->lpi, lpistate);
10086 }
10087 /* @todo: setting feasibility to TRUE might be wrong because in probing mode, the state is even saved when the LP was
10088 * flushed and solved, also, e.g., when we hit the iteration limit
10089 */
10090 lp->primalfeasible = wasprimfeas;
10091 lp->primalchecked = wasprimchecked;
10092 lp->dualfeasible = wasdualfeas;
10093 lp->dualchecked = wasdualchecked;
10094
10095 return SCIP_OKAY;
10096}
10097
10098/** frees LP state information */
10100 SCIP_LP* lp, /**< LP data */
10101 BMS_BLKMEM* blkmem, /**< block memory */
10102 SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
10103 )
10104{
10105 assert(lp != NULL);
10106
10107 if( *lpistate != NULL )
10108 {
10109 SCIP_CALL( SCIPlpiFreeState(lp->lpi, blkmem, lpistate) );
10110 }
10111
10112 return SCIP_OKAY;
10113}
10114
10115/** interrupts the currently ongoing lp solve, or disables the interrupt */
10117 SCIP_LP* lp, /**< LP data */
10118 SCIP_Bool interrupt /**< TRUE if interrupt should be set, FALSE if it should be disabled */
10119 )
10120{
10121 assert(lp != NULL);
10122
10123 if( lp->lpi == NULL )
10124 return SCIP_OKAY;
10125
10126 SCIP_CALL( SCIPlpiInterrupt(lp->lpi, interrupt) );
10127
10128 return SCIP_OKAY;
10129}
10130
10131/** stores pricing norms into LP norms object */
10133 SCIP_LP* lp, /**< LP data */
10134 BMS_BLKMEM* blkmem, /**< block memory */
10135 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10136 )
10137{
10138 assert(lp != NULL);
10139 assert(lp->flushed);
10140 assert(lp->solved);
10141 assert(blkmem != NULL);
10142 assert(lpinorms != NULL);
10143
10144 /* check whether there is no lp */
10145 if( lp->nlpicols == 0 && lp->nlpirows == 0 )
10146 *lpinorms = NULL;
10147 else
10148 {
10149 SCIP_CALL( SCIPlpiGetNorms(lp->lpi, blkmem, lpinorms) );
10150 }
10151
10152 return SCIP_OKAY;
10153}
10154
10155/** loads pricing norms from LP norms object into solver */
10157 SCIP_LP* lp, /**< LP data */
10158 BMS_BLKMEM* blkmem, /**< block memory */
10159 SCIP_LPINORMS* lpinorms /**< LP pricing norms information */
10160 )
10161{
10162 assert(lp != NULL);
10163 assert(blkmem != NULL);
10164 assert(lp->flushed);
10165
10166 /* set LPI norms in the LP solver */
10167 if( lpinorms != NULL )
10168 {
10169 SCIP_CALL( SCIPlpiSetNorms(lp->lpi, blkmem, lpinorms) );
10170 }
10171
10172 return SCIP_OKAY;
10173}
10174
10175/** frees pricing norms information */
10177 SCIP_LP* lp, /**< LP data */
10178 BMS_BLKMEM* blkmem, /**< block memory */
10179 SCIP_LPINORMS** lpinorms /**< pointer to LP pricing norms information */
10180 )
10181{
10182 assert(lp != NULL);
10183
10184 SCIP_CALL( SCIPlpiFreeNorms(lp->lpi, blkmem, lpinorms) );
10185
10186 return SCIP_OKAY;
10187}
10188
10189/** return the current cutoff bound of the lp */
10191 SCIP_LP* lp /**< current LP data */
10192 )
10193{
10194 assert(lp != NULL);
10195
10196 return lp->cutoffbound;
10197}
10198
10199/** sets the upper objective limit of the LP solver */
10201 SCIP_LP* lp, /**< current LP data */
10202 SCIP_SET* set, /**< global SCIP settings */
10203 SCIP_PROB* prob, /**< problem data */
10204 SCIP_Real cutoffbound /**< new upper objective limit */
10205 )
10206{
10207 assert(lp != NULL);
10208
10209 SCIPsetDebugMsg(set, "setting LP upper objective limit from %g to %g\n", lp->cutoffbound, cutoffbound);
10210
10211 /* if the objective function was changed in diving, the cutoff bound has no meaning (it will be set correctly
10212 * in SCIPendDive())
10213 */
10214 if( SCIPlpDivingObjChanged(lp) )
10215 {
10216 assert(SCIPsetIsInfinity(set, lp->cutoffbound));
10217 return SCIP_OKAY;
10218 }
10219
10220 /* if the cutoff bound is increased, and the LP was proved to exceed the old cutoff, it is no longer solved */
10221 if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OBJLIMIT && cutoffbound > lp->cutoffbound )
10222 {
10223 /* mark the current solution invalid */
10224 lp->solved = FALSE;
10225 lp->lpobjval = SCIP_INVALID;
10227 }
10228 /* if the cutoff bound is decreased below the current optimal value, the LP now exceeds the objective limit;
10229 * if the objective limit in the LP solver was disabled, the solution status of the LP is not changed
10230 */
10231 else if( !lpCutoffDisabled(set, prob, lp) && SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_OPTIMAL
10232 && SCIPlpGetObjval(lp, set, prob) >= cutoffbound )
10233 {
10234 assert(lp->flushed);
10235 assert(lp->solved);
10237 }
10238
10239 lp->cutoffbound = cutoffbound;
10240
10241 return SCIP_OKAY;
10242}
10243
10244/** gets current primal feasibility tolerance of LP solver */
10246 SCIP_LP* lp /**< current LP data */
10247 )
10248{
10249 assert(lp != NULL);
10250
10251 return lp->feastol;
10252}
10253
10254/** sets primal feasibility tolerance of LP solver */
10256 SCIP_LP* lp, /**< current LP data */
10257 SCIP_SET* set, /**< global SCIP settings */
10258 SCIP_Real newfeastol /**< new primal feasibility tolerance for LP */
10259 )
10260{
10261 assert(lp != NULL);
10262 assert(newfeastol > 0.0);
10263
10264 SCIPsetDebugMsg(set, "setting LP primal feasibility tolerance from %g to %g\n", lp->feastol, newfeastol);
10265
10266 /* mark the LP unsolved, if the primal feasibility tolerance is tightened */
10267 if( newfeastol < lp->feastol )
10268 {
10269 lp->solved = FALSE;
10271 }
10272
10273 lp->feastol = newfeastol;
10274}
10275
10276/** resets primal feasibility tolerance of LP solver
10277 *
10278 * Sets primal feasibility tolerance to min of numerics/lpfeastolfactor * numerics/feastol and relaxfeastol.
10279 */
10281 SCIP_LP* lp, /**< current LP data */
10282 SCIP_SET* set /**< global SCIP settings */
10283 )
10284{
10285 assert(lp != NULL);
10286
10287 SCIPsetDebugMsg(set, "reset LP primal feasibility tolerance\n");
10288
10289 if( SCIPsetRelaxfeastol(set) != SCIP_INVALID ) /*lint !e777*/
10291 else
10293}
10294
10295/** returns the name of the given LP algorithm */
10296static
10297const char* lpalgoName(
10298 SCIP_LPALGO lpalgo /**< LP algorithm */
10299 )
10300{
10301 switch( lpalgo )
10302 {
10304 return "primal simplex";
10306 return "dual simplex";
10308 return "barrier";
10310 return "barrier/crossover";
10311 default:
10312 SCIPerrorMessage("invalid LP algorithm\n");
10313 SCIPABORT();
10314 return "invalid"; /*lint !e527*/
10315 }
10316}
10317
10318/** calls LPI to perform primal simplex, measures time and counts iterations, gets basis feasibility status */
10319static
10321 SCIP_LP* lp, /**< current LP data */
10322 SCIP_SET* set, /**< global SCIP settings */
10323 SCIP_STAT* stat, /**< problem statistics */
10324 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10325 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10326 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10327 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10328 )
10329{
10330 SCIP_Real timedelta;
10331 SCIP_RETCODE retcode;
10332 int iterations;
10333
10334 assert(lp != NULL);
10335 assert(lp->flushed);
10336 assert(set != NULL);
10337 assert(stat != NULL);
10338 assert(lperror != NULL);
10339
10340 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",
10341 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10342
10343 *lperror = FALSE;
10344
10345#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10346 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10347 {
10348 char fname[SCIP_MAXSTRLEN];
10349 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10350 SCIP_CALL( SCIPlpWrite(lp, fname) );
10351 SCIPsetDebugMsg(set, "wrote LP to file <%s> (primal simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10352 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10354 }
10355#endif
10356
10357 /* start timing */
10358 if( lp->diving || lp->probing )
10359 {
10360 if( lp->strongbranchprobing )
10362 else
10364
10365 timedelta = 0.0; /* unused for diving or probing */
10366 }
10367 else
10368 {
10370 timedelta = -SCIPclockGetTime(stat->primallptime);
10371 }
10372
10373 /* if this is a call to resolve an instable LP, collect time */
10374 if( instable )
10375 {
10377 }
10378
10379 /* call primal simplex */
10380 retcode = SCIPlpiSolvePrimal(lp->lpi);
10381 if( retcode == SCIP_LPERROR )
10382 {
10383 *lperror = TRUE;
10384 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10385 }
10386 else
10387 {
10388 SCIP_CALL( retcode );
10389 }
10391 lp->solisbasic = TRUE;
10392
10393 /* stop timing */
10394 if( lp->diving || lp->probing )
10395 {
10396 if( lp->strongbranchprobing )
10398 else
10400 }
10401 else
10402 {
10403 timedelta += SCIPclockGetTime(stat->primallptime);
10405 }
10406
10407 if ( instable )
10408 {
10410 }
10411
10412 /* count number of iterations */
10413 SCIPstatIncrement(stat, set, lpcount);
10414 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10415 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10416 {
10417 if( !lp->strongbranchprobing )
10418 {
10419 SCIPstatIncrement(stat, set, nlps);
10420 SCIPstatAdd( stat, set, nlpiterations, iterations );
10421 }
10422 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10423 {
10424 SCIPstatIncrement(stat, set, nprimalresolvelps );
10425 SCIPstatAdd(stat, set, nprimalresolvelpiterations, iterations);
10426 }
10427 if ( instable )
10428 {
10429 SCIPstatIncrement(stat, set, nresolveinstablelps);
10430 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10431 }
10432 if( lp->diving || lp->probing )
10433 {
10434 if( lp->strongbranchprobing )
10435 {
10436 SCIPstatIncrement(stat, set, nsbdivinglps);
10437 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10438 }
10439 else
10440 {
10441 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10442 SCIPstatIncrement(stat, set, ndivinglps);
10443 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10444 }
10445 }
10446 else
10447 {
10448 SCIPstatIncrement(stat, set, nprimallps);
10449 SCIPstatAdd(stat, set, nprimallpiterations, iterations);
10450 }
10451 }
10452 else
10453 {
10454 if ( ! lp->diving && ! lp->probing )
10455 {
10456 SCIPstatIncrement(stat, set, nprimalzeroitlps);
10457 SCIPstatAdd(stat, set, primalzeroittime, timedelta);
10458 }
10459
10460 if ( keepsol && !(*lperror) )
10461 {
10462 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10463 if( lp->validsollp == stat->lpcount-1 )
10464 lp->validsollp = stat->lpcount;
10465 if( lp->validfarkaslp == stat->lpcount-1 )
10466 lp->validfarkaslp = stat->lpcount;
10467 }
10468 }
10469
10470 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with primal simplex (diving=%d, nprimallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10471 stat->lpcount, lp->diving || lp->probing, stat->nprimallps, stat->ndivinglps);
10472
10473 return SCIP_OKAY;
10474}
10475
10476/** calls LPI to perform dual simplex, measures time and counts iterations */
10477static
10479 SCIP_LP* lp, /**< current LP data */
10480 SCIP_SET* set, /**< global SCIP settings */
10481 SCIP_STAT* stat, /**< problem statistics */
10482 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10483 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10484 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
10485 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10486 )
10487{
10488 SCIP_Real timedelta;
10489 SCIP_RETCODE retcode;
10490 int iterations;
10491
10492 assert(lp != NULL);
10493 assert(lp->flushed);
10494 assert(set != NULL);
10495 assert(stat != NULL);
10496 assert(lperror != NULL);
10497
10498 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",
10499 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10500
10501 *lperror = FALSE;
10502
10503#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
10504 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
10505 {
10506 char fname[SCIP_MAXSTRLEN];
10507 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
10508 SCIP_CALL( SCIPlpWrite(lp, fname) );
10509 SCIPsetDebugMsg(set, "wrote LP to file <%s> (dual simplex, objlim=%.15g, feastol=%.15g/%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
10510 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol,
10512 }
10513#endif
10514
10515 /* start timing */
10516 if( lp->diving || lp->probing )
10517 {
10518 if( lp->strongbranchprobing )
10520 else
10522
10523 timedelta = 0.0; /* unused for diving or probing */
10524 }
10525 else
10526 {
10528 timedelta = -SCIPclockGetTime(stat->duallptime);
10529 }
10530
10531 /* if this is a call to resolve an instable LP, collect time */
10532 if ( instable )
10533 {
10535 }
10536
10537 /* call dual simplex */
10538 retcode = SCIPlpiSolveDual(lp->lpi);
10539 if( retcode == SCIP_LPERROR )
10540 {
10541 *lperror = TRUE;
10542 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10543 }
10544 else
10545 {
10546 SCIP_CALL( retcode );
10547 }
10549 lp->solisbasic = TRUE;
10550
10551 /* stop timing */
10552 if( lp->diving || lp->probing )
10553 {
10554 if( lp->strongbranchprobing )
10556 else
10558 }
10559 else
10560 {
10561 timedelta += SCIPclockGetTime(stat->duallptime);
10563 }
10564
10565 if ( instable )
10566 {
10568 }
10569
10570 /* count number of iterations */
10571 SCIPstatIncrement(stat, set, lpcount);
10572 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10573 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10574 {
10575 if( !lp->strongbranchprobing )
10576 {
10577 SCIPstatIncrement(stat, set, nlps);
10578 SCIPstatAdd(stat, set, nlpiterations, iterations);
10579 }
10580 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10581 {
10582 SCIPstatIncrement(stat, set, ndualresolvelps);
10583 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10584 }
10585 if ( instable )
10586 {
10587 SCIPstatIncrement(stat, set, nresolveinstablelps);
10588 SCIPstatAdd(stat, set, nresolveinstablelpiters, iterations);
10589 }
10590 if( lp->diving || lp->probing )
10591 {
10592 if( lp->strongbranchprobing )
10593 {
10594 SCIPstatIncrement(stat, set, nsbdivinglps);
10595 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10596 }
10597 else
10598 {
10599 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10600 SCIPstatIncrement(stat, set, ndivinglps);
10601 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10602 }
10603 }
10604 else
10605 {
10606 SCIPstatIncrement(stat, set, nduallps);
10607 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10608 }
10609 }
10610 else
10611 {
10612 if ( ! lp->diving && ! lp->probing )
10613 {
10614 SCIPstatIncrement(stat, set, ndualzeroitlps);
10615 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10616 }
10617
10618 if( keepsol && !(*lperror) )
10619 {
10620 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
10621 if( lp->validsollp == stat->lpcount-1 )
10622 lp->validsollp = stat->lpcount;
10623 if( lp->validfarkaslp == stat->lpcount-1 )
10624 lp->validfarkaslp = stat->lpcount;
10625 }
10626 }
10627
10628 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
10629 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10630
10631 return SCIP_OKAY;
10632}
10633
10634/** calls LPI to perform lexicographic dual simplex to find a lexicographically minimal optimal solution, measures time and counts iterations
10635 *
10636 * We follow the approach of the following paper to find a lexicographically minimal optimal
10637 * solution:
10638 *
10639 * Zanette, Fischetti, Balas@n
10640 * Can pure cutting plane algorithms work?@n
10641 * IPCO 2008, Bertinoro, Italy.
10642 *
10643 * We do, however, not aim for the exact lexicographically minimal optimal solutions, but perform a
10644 * heuristic, i.e., we limit the number of components which are minimized.
10645 *
10646 * More precisely, we first solve the problem with the dual simplex algorithm. Then we fix those
10647 * nonbasic variables to their current value (i.e., one of the bounds except maybe for free
10648 * variables) that have nonzero reduced cost. This fixes the objective function value, because only
10649 * pivots that will not change the objective are allowed afterwards.
10650 *
10651 * Then the not yet fixed variables are considered in turn. If they are at their lower bounds and
10652 * nonbasic, they are fixed to this bound, since their value cannot be decreased further. Once a
10653 * candidate is found, we set the objective to minimize this variable. We run the primal simplex
10654 * algorithm (since the objective is changed the solution is not dual feasible anymore; if
10655 * variables out of the basis have been fixed to their lower bound, the basis is also not primal
10656 * feasible anymore). After the optimization, we again fix nonbasic variables that have nonzero
10657 * reduced cost. We then choose the next variable and iterate.
10658 *
10659 * We stop the process once we do not find candidates or have performed a maximum number of
10660 * iterations.
10661 *
10662 * @todo Does this really produce a lexicographically minimal solution?
10663 * @todo Can we skip the consideration of basic variables that are at their lower bound? How can we
10664 * guarantee that these variables will not be changed in later stages? We can fix these variables
10665 * to their lower bound, but this destroys the basis.
10666 * @todo Should we use lexicographical minimization in diving/probing or not?
10667 */
10668static
10670 SCIP_LP* lp, /**< current LP data */
10671 SCIP_SET* set, /**< global SCIP settings */
10672 SCIP_STAT* stat, /**< problem statistics */
10673 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
10674 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
10675 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
10676 )
10677{
10678 SCIP_Real timedelta;
10679 SCIP_RETCODE retcode;
10680 int totalIterations;
10681 int lexIterations;
10682 int iterations;
10683 int rounds;
10684
10685 assert(lp != NULL);
10686 assert(lp->flushed);
10687 assert(set != NULL);
10688 assert(stat != NULL);
10689 assert(lperror != NULL);
10690
10691 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",
10692 stat->lpcount+1, lp->ncols, lp->nrows, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
10693
10694 *lperror = FALSE;
10695
10696 /* start timing */
10697 if( lp->diving || lp->probing )
10698 {
10699 if( lp->strongbranchprobing )
10701 else
10703
10704 timedelta = 0.0; /* unused for diving or probing */
10705 }
10706 else
10707 {
10709 timedelta = -SCIPclockGetTime(stat->duallptime);
10710 }
10711
10712 /* call dual simplex for first lp */
10713 retcode = SCIPlpiSolveDual(lp->lpi);
10714 if( retcode == SCIP_LPERROR )
10715 {
10716 *lperror = TRUE;
10717 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
10718 }
10719 else
10720 {
10721 SCIP_CALL( retcode );
10722 }
10723 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
10724 totalIterations = iterations;
10725
10726 /* stop timing */
10727 if( lp->diving || lp->probing )
10728 {
10729 if( lp->strongbranchprobing )
10731 else
10733 }
10734 else
10735 {
10736 timedelta += SCIPclockGetTime(stat->duallptime);
10738 }
10739
10740 /* count number of iterations */
10741 SCIPstatIncrement(stat, set, lpcount);
10742 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
10743 {
10744 if( lp->strongbranchprobing )
10745 {
10746 SCIPstatAdd(stat, set, nlpiterations, iterations);
10747 }
10748 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
10749 {
10750 SCIPstatIncrement(stat, set, ndualresolvelps);
10751 SCIPstatAdd(stat, set, ndualresolvelpiterations, iterations);
10752 }
10753 if( lp->diving || lp->probing )
10754 {
10755 if( lp->strongbranchprobing )
10756 {
10757 SCIPstatIncrement(stat, set, nsbdivinglps);
10758 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
10759 }
10760 else
10761 {
10762 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
10763 SCIPstatIncrement(stat, set, ndivinglps);
10764 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
10765 }
10766 }
10767 else
10768 {
10769 SCIPstatIncrement(stat, set, nduallps);
10770 SCIPstatAdd(stat, set, nduallpiterations, iterations);
10771 }
10772 }
10773 else
10774 {
10775 if ( ! lp->diving && ! lp->probing )
10776 {
10777 SCIPstatIncrement(stat, set, ndualzeroitlps);
10778 SCIPstatAdd(stat, set, dualzeroittime, timedelta);
10779 }
10780 }
10781 lexIterations = 0;
10782
10783 /* search for lexicographically minimal optimal solution */
10784 if( !lp->diving && !lp->probing && SCIPlpiIsOptimal(lp->lpi) )
10785 {
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 SCIP_Bool chooseBasic;
10808 SCIP_Bool success;
10809 int nDualDeg;
10810 int r, c;
10811 int cntcol;
10812 int cntrow;
10813 int nruns;
10814 int pos;
10815
10816 chooseBasic = set->lp_lexdualbasic;
10817
10818 /* start timing */
10820
10821 /* get all solution information */
10822 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10823 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10824 if( chooseBasic )
10825 {
10826 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10827 }
10828 else
10829 primsol = NULL;
10830
10831 /* get basic and nonbasic information */
10834
10835 /* save bounds, lhs/rhs, and objective */
10841 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10842 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10843 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10844
10845 /* get storage for several arrays */
10849
10853
10854 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10855 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10856
10859
10860 /* initialize: set objective to 0, get fixed variables */
10862 for( c = 0; c < lp->nlpicols; ++c )
10863 {
10864 newobj[c] = 0.0;
10865 indallcol[c] = c;
10866 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10867 fixedc[c] = TRUE;
10868 else
10869 fixedc[c] = FALSE;
10870 }
10871
10872 /* initialize: get fixed slack variables */
10873 for( r = 0; r < lp->nlpirows; ++r )
10874 {
10875 indallrow[r] = r;
10876 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10877 fixedr[r] = TRUE;
10878 else
10879 fixedr[r] = FALSE;
10880 }
10881
10882#ifdef DEBUG_LEXDUAL
10883 {
10884 int j;
10885
10886 if( !chooseBasic )
10887 {
10888 assert(primsol == NULL);
10889 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10890 }
10891 assert(primsol != NULL);
10892 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10893 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10894
10895 for( j = 0; j < lp->nlpicols; ++j )
10896 {
10897 if( fixedc[j] )
10898 {
10899 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10900 }
10901 else
10902 {
10903 char type;
10904 switch( (SCIP_BASESTAT) cstat[j] )
10905 {
10907 type = 'l';
10908 break;
10910 type = 'u';
10911 break;
10912 case SCIP_BASESTAT_ZERO:
10913 type = 'z';
10914 break;
10916 type = 'b';
10917 break;
10918 default:
10919 type = '?';
10920 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10921 SCIPABORT();
10922 }
10923 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10924 }
10925 }
10926 SCIPsetDebugMsg(set, "\n\n");
10927
10928 if( !chooseBasic )
10929 {
10930 SCIPsetFreeBufferArray(set, &primsol);
10931 assert(primsol == NULL);
10932 }
10933 }
10934#endif
10935
10936 /* disable objective limit */
10938 assert(success);
10939
10940 /* perform lexicographic rounds */
10941 pos = -1;
10942 nruns = 0;
10943 rounds = 0;
10944 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10945 do
10946 {
10947 int oldpos;
10948
10949 /* get current solution */
10950 if( chooseBasic )
10951 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10952 else
10953 {
10954 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10955 assert(primsol == NULL);
10956 }
10957
10958 /* get current basis */
10959 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10960
10961 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10962 nDualDeg = 0;
10963 cntcol = 0;
10964 oldpos = pos;
10965 pos = -1;
10966 for( c = 0; c < lp->nlpicols; ++c )
10967 {
10968 if( !fixedc[c] )
10969 {
10970 /* check whether variable is in basis */
10971 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10972 {
10973 /* store first candidate */
10974 if( pos == -1 && c > oldpos )
10975 {
10976 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10977 pos = c;
10978 }
10979 }
10980 else
10981 {
10982 /* reduced cost == 0 -> possible candidate */
10983 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10984 {
10985 ++nDualDeg;
10986 /* only if we have not yet found a candidate */
10987 if( pos == -1 && c > oldpos )
10988 {
10989 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10990 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10991 {
10992 newlb[cntcol] = oldlb[c];
10993 newub[cntcol] = oldlb[c];
10994 indcol[cntcol++] = c;
10995 fixedc[c] = TRUE;
10996 }
10997 else /* found a non-fixed candidate */
10998 {
10999 if( !chooseBasic )
11000 pos = c;
11001 }
11002 }
11003 }
11004 else
11005 {
11006 /* nonzero reduced cost -> variable can be fixed */
11007 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11008 {
11009 newlb[cntcol] = oldlb[c];
11010 newub[cntcol] = oldlb[c];
11011 }
11012 else
11013 {
11014 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11015 {
11016 newlb[cntcol] = oldub[c];
11017 newub[cntcol] = oldub[c];
11018 }
11019 else
11020 {
11021 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11022 newlb[cntcol] = 0.0;
11023 newub[cntcol] = 0.0;
11024 }
11025 }
11026 indcol[cntcol++] = c;
11027 fixedc[c] = TRUE;
11028 }
11029 }
11030 }
11031 }
11032
11033 /* check rows */
11034 cntrow = 0;
11035 for( r = 0; r < lp->nlpirows; ++r )
11036 {
11037 if( !fixedr[r] )
11038 {
11039 /* consider only nonbasic rows */
11040 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11041 {
11042 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11043 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11044 ++nDualDeg;
11045 else
11046 {
11047 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11048 {
11049 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11050 newlhs[cntrow] = oldlhs[r];
11051 newrhs[cntrow] = oldlhs[r];
11052 }
11053 else
11054 {
11055 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11056 newlhs[cntrow] = oldrhs[r];
11057 newrhs[cntrow] = oldrhs[r];
11058 }
11059 indrow[cntrow++] = r;
11060 fixedr[r] = TRUE;
11061 }
11062 }
11063 }
11064 }
11065
11066 if( nDualDeg > 0 && pos >= 0 )
11067 {
11068 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11069
11070 /* change objective */
11071 if( nruns == 0 )
11072 {
11073 /* set objective to appropriate unit vector for first run */
11074 newobj[pos] = 1.0;
11075 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11076 }
11077 else
11078 {
11079 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11080 SCIP_Real obj = 1.0;
11081 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11082 }
11083
11084 /* fix variables */
11085 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11086 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11087
11088 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11089 retcode = SCIPlpiSolvePrimal(lp->lpi);
11090 if( retcode == SCIP_LPERROR )
11091 {
11092 *lperror = TRUE;
11093 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11094 }
11095 else
11096 {
11097 SCIP_CALL( retcode );
11098 }
11099 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11100 lexIterations += iterations;
11101
11102#ifdef DEBUG_LEXDUAL
11103 if( iterations > 0 )
11104 {
11105 int j;
11106
11107 if( !chooseBasic )
11108 {
11109 assert(primsol == NULL);
11110 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11111 }
11112 assert(primsol != NULL);
11113 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11114
11115 for( j = 0; j < lp->nlpicols; ++j )
11116 {
11117 if( fixedc[j] )
11118 {
11119 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11120 }
11121 else
11122 {
11123 char cstart = '[';
11124 char cend = ']';
11125 char type;
11126
11127 if(j == pos)
11128 {
11129 cstart = '*';
11130 cend = '*';
11131 }
11132
11133 switch( (SCIP_BASESTAT) cstat[j] )
11134 {
11136 type = 'l';
11137 break;
11139 type = 'u';
11140 break;
11141 case SCIP_BASESTAT_ZERO:
11142 type = 'z';
11143 break;
11145 type = 'b';
11146 break;
11147 default:
11148 type = '?';
11149 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11150 SCIPABORT();
11151 }
11152 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11153 }
11154 }
11155 SCIPsetDebugMsg(set, "\n\n");
11156
11157 if( !chooseBasic )
11158 {
11159 SCIPsetFreeBufferArray(set, &primsol);
11160 assert(primsol == NULL);
11161 }
11162 }
11163#endif
11164
11165 /* count only as round if iterations have been performed */
11166 if( iterations > 0 )
11167 ++rounds;
11168 ++nruns;
11169 }
11170 }
11171 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11172
11173 /* reset bounds, lhs/rhs, and obj */
11174 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11175 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11176 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11177
11178 /* resolve to update solvers internal data structures - should only produce few pivots */
11179 retcode = SCIPlpiSolveDual(lp->lpi);
11180 if( retcode == SCIP_LPERROR )
11181 {
11182 *lperror = TRUE;
11183 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11184 }
11185 else
11186 {
11187 SCIP_CALL( retcode );
11188 }
11189 assert(SCIPlpiIsOptimal(lp->lpi));
11190
11191 /* reset objective limit */
11192 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_OBJLIM, lp->lpiobjlim, &success) );
11193 assert(success);
11194
11195 /* add LP iterations */
11196 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11197 lexIterations += iterations;
11198
11199 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11200
11201 /* count number of iterations */
11202 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11203 SCIPstatIncrement(stat, set, nlps);
11204
11205 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11206 {
11207 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11208 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11209 {
11210 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11211 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11212 }
11213 SCIPstatIncrement(stat, set, nlexduallps);
11214 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11215
11216 totalIterations += lexIterations;
11217 }
11218
11219 /* free space */
11220 SCIPsetFreeBufferArray(set, &newobj);
11221
11222 SCIPsetFreeBufferArray(set, &fixedr);
11223 SCIPsetFreeBufferArray(set, &fixedc);
11224
11225 SCIPsetFreeBufferArray(set, &indallrow);
11226 SCIPsetFreeBufferArray(set, &indallcol);
11227
11228 SCIPsetFreeBufferArray(set, &indrow);
11229 SCIPsetFreeBufferArray(set, &newrhs);
11230 SCIPsetFreeBufferArray(set, &newlhs);
11231
11232 SCIPsetFreeBufferArray(set, &indcol);
11233 SCIPsetFreeBufferArray(set, &newub);
11234 SCIPsetFreeBufferArray(set, &newlb);
11235
11236 SCIPsetFreeBufferArray(set, &oldobj);
11237 SCIPsetFreeBufferArray(set, &oldrhs);
11238 SCIPsetFreeBufferArray(set, &oldlhs);
11239 SCIPsetFreeBufferArray(set, &oldub);
11240 SCIPsetFreeBufferArray(set, &oldlb);
11241
11242 SCIPsetFreeBufferArray(set, &rstat);
11243 SCIPsetFreeBufferArray(set, &cstat);
11244
11245 SCIPsetFreeBufferArray(set, &redcost);
11246 SCIPsetFreeBufferArray(set, &dualsol);
11247 if( chooseBasic )
11248 SCIPsetFreeBufferArray(set, &primsol);
11249
11250 /* stop timing */
11252
11253 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11254 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11255 }
11257 lp->solisbasic = TRUE;
11258
11259 if( totalIterations > 0 && !lp->strongbranchprobing )
11260 SCIPstatIncrement(stat, set, nlps);
11261 else
11262 {
11263 if( keepsol && !(*lperror) )
11264 {
11265 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11266 if( lp->validsollp == stat->lpcount-1 )
11267 lp->validsollp = stat->lpcount;
11268 if( lp->validfarkaslp == stat->lpcount-1 )
11269 lp->validfarkaslp = stat->lpcount;
11270 }
11271 }
11272
11273 return SCIP_OKAY;
11274}
11275
11276/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11277static
11279 SCIP_LP* lp, /**< current LP data */
11280 SCIP_SET* set, /**< global SCIP settings */
11281 SCIP_STAT* stat, /**< problem statistics */
11282 SCIP_Bool crossover, /**< should crossover be performed? */
11283 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11284 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11285 )
11286{
11287 SCIP_Real timedelta;
11288 SCIP_RETCODE retcode;
11289 int iterations;
11290
11291 assert(lp != NULL);
11292 assert(lp->flushed);
11293 assert(set != NULL);
11294 assert(stat != NULL);
11295 assert(lperror != NULL);
11296
11297 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",
11298 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11299 stat->nbarrierlps, stat->ndivinglps);
11300
11301 *lperror = FALSE;
11302
11303#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11304 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11305 {
11306 char fname[SCIP_MAXSTRLEN];
11307 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11308 SCIP_CALL( SCIPlpWrite(lp, fname) );
11309 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11310 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11312 }
11313#endif
11314
11315 /* start timing */
11316 if( lp->diving || lp->probing )
11317 {
11318 if( lp->strongbranchprobing )
11320 else
11322
11323 timedelta = 0.0; /* unused for diving or probing */
11324 }
11325 else
11326 {
11328 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11329 }
11330
11331 /* call barrier algorithm */
11332 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11333 if( retcode == SCIP_LPERROR )
11334 {
11335 *lperror = TRUE;
11336 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11337 }
11338 else
11339 {
11340 SCIP_CALL( retcode );
11341 }
11343 lp->solisbasic = crossover;
11344
11345 /* stop timing */
11346 if( lp->diving || lp->probing )
11347 {
11348 if( lp->strongbranchprobing )
11350 else
11352 }
11353 else
11354 {
11356 timedelta += SCIPclockGetTime(stat->barrierlptime);
11357 }
11358
11359 /* count number of iterations */
11360 SCIPstatIncrement(stat, set, lpcount);
11361 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11362 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11363 {
11364 if( !lp->strongbranchprobing )
11365 {
11366 SCIPstatIncrement(stat, set, nlps);
11367 SCIPstatAdd(stat, set, nlpiterations, iterations);
11368 }
11369 if( lp->diving || lp->probing )
11370 {
11371 if( lp->strongbranchprobing )
11372 {
11373 SCIPstatIncrement(stat, set, nsbdivinglps);
11374 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11375 }
11376 else
11377 {
11378 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11379 SCIPstatIncrement(stat, set, ndivinglps);
11380 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11381 }
11382 }
11383 else
11384 {
11385 SCIPstatIncrement(stat, set, nbarrierlps);
11386 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11387 }
11388 }
11389 else
11390 {
11391 if ( ! lp->diving && ! lp->probing )
11392 {
11393 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11394 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11395 }
11396
11397 if( keepsol && !(*lperror) )
11398 {
11399 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11400 if( lp->validsollp == stat->lpcount-1 )
11401 lp->validsollp = stat->lpcount;
11402 if( lp->validfarkaslp == stat->lpcount-1 )
11403 lp->validfarkaslp = stat->lpcount;
11404 }
11405 }
11406
11407 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11408 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11409
11410 return SCIP_OKAY;
11411}
11412
11413/** solves the LP with the given algorithm */
11414static
11416 SCIP_LP* lp, /**< current LP data */
11417 SCIP_SET* set, /**< global SCIP settings */
11418 SCIP_STAT* stat, /**< problem statistics */
11419 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11420 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11421 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11422 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11423 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11424 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11425 )
11426{
11427 SCIP_Real lptimelimit;
11428 SCIP_Bool success;
11429
11430 assert(lp != NULL);
11431 assert(lp->flushed);
11432 assert(lperror != NULL);
11433
11434 /* check if a time limit is set, and set time limit for LP solver accordingly */
11435 lptimelimit = SCIPlpiInfinity(lp->lpi);
11436 if( set->istimelimitfinite )
11437 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11438
11439 success = FALSE;
11440 if( lptimelimit > 0.0 )
11441 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11442
11443 if( lptimelimit <= 0.0 || !success )
11444 {
11445 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11446 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11447 *timelimit = TRUE;
11448 return SCIP_OKAY;
11449 }
11450 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11451
11452 /* call appropriate LP algorithm */
11453 switch( lpalgo )
11454 {
11456 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11457 break;
11458
11460 /* run dual lexicographic simplex if required */
11461 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11462 {
11463 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11464 }
11465 else
11466 {
11467 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11468 }
11469 break;
11470
11472 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11473 break;
11474
11476 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11477 break;
11478
11479 default:
11480 SCIPerrorMessage("invalid LP algorithm\n");
11481 return SCIP_INVALIDDATA;
11482 }
11483
11484 if( !(*lperror) )
11485 {
11486 /* check for primal and dual feasibility */
11488
11489 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11490 }
11491
11492 return SCIP_OKAY;
11493}
11494
11495/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11496 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11497 */
11498#define MAXNUMTROUBLELPMSGS 10
11499
11500/** prints message about numerical trouble
11501 *
11502 * If message has verblevel at most high and display/verblevel is not full,
11503 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11504 * were printed before in the current run.
11505 */
11506static
11508 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11509 SCIP_SET* set, /**< global SCIP settings */
11510 SCIP_STAT* stat, /**< problem statistics */
11511 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11512 const char* formatstr, /**< message format string */
11513 ... /**< arguments to format string */
11514 )
11515{
11516 va_list ap;
11517
11518 assert(verblevel > SCIP_VERBLEVEL_NONE);
11519 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11520 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11521
11522 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11523 {
11524 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11525 {
11526 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11528 return;
11529
11530 /* increase count on messages with verblevel high */
11531 ++stat->nnumtroublelpmsgs ;
11532 }
11533
11534 /* if messages wouldn't be printed, then return already */
11535 if( verblevel > set->disp_verblevel )
11536 return;
11537 }
11538
11539 /* print common begin of message */
11540 SCIPmessagePrintInfo(messagehdlr,
11541 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11542 stat->nnodes, stat->nlps);
11543
11544 /* print individual part of message */
11545 va_start(ap, formatstr); /*lint !e838*/
11546 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11547 va_end(ap);
11548
11549 /* warn that further messages will be suppressed */
11550 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11551 {
11552 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11553 }
11554
11555 /* print closing new-line */
11556 SCIPmessagePrintInfo(messagehdlr, "\n");
11557}
11558
11559static
11561 SCIP_LP* lp, /**< current LP data */
11562 SCIP_SET* set, /**< global SCIP settings */
11563 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11564 SCIP_STAT* stat, /**< problem statistics */
11565 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11566 SCIP_Bool* success /**< was instability successfully ignored */
11567 )
11568{
11569 assert(lp != NULL);
11570 assert(set != NULL);
11571
11572 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11573
11574 if( *success )
11575 {
11576 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11577 if( !set->lp_checkdualfeas )
11578 lp->dualfeasible = TRUE;
11579 if( !set->lp_checkprimfeas )
11580 lp->primalchecked = TRUE;
11581 }
11582
11583 return SCIP_OKAY;
11584}
11585
11586#define FEASTOLTIGHTFAC 0.001
11587/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11588static
11590 SCIP_LP* lp, /**< current LP data */
11591 SCIP_SET* set, /**< global SCIP settings */
11592 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11593 SCIP_STAT* stat, /**< problem statistics */
11594 SCIP_PROB* prob, /**< problem data */
11595 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11596 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11597 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11598 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11599 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11600 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11601 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11602 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11603 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11604 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11605 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11606 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11607 )
11608{
11609 SCIP_Bool success;
11610 SCIP_Bool success2;
11611 SCIP_Bool success3;
11612 SCIP_Bool simplex;
11613 SCIP_Bool itlimishard;
11614 SCIP_Bool usepolishing;
11615
11616 assert(lp != NULL);
11617 assert(lp->flushed);
11618 assert(set != NULL);
11619 assert(stat != NULL);
11620 assert(lperror != NULL);
11621 assert(timelimit != NULL);
11622
11623 *lperror = FALSE;
11624
11625 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11626 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11627 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11628 * SCIP_LP such that we can return a primal ray
11629 */
11630 if( lp->looseobjvalinf > 0 )
11631 {
11632 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11633 return SCIP_ERROR;
11634 }
11635
11636 /* check, whether we solve with a simplex algorithm */
11637 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11638
11639 /* check whether the iteration limit is a hard one */
11640 itlimishard = (itlim == harditlim);
11641
11642 /* check whether solution polishing should be used */
11643 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11644 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11645 {
11646 usepolishing = TRUE;
11647 if( lp->updateintegrality )
11648 {
11650 }
11651 }
11652 else
11653 usepolishing = FALSE;
11654
11655 /* solve with given settings (usually fast but imprecise) */
11657 {
11658 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11659 }
11660 else
11661 {
11662 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11663 }
11664 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11665 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11667 &success) );
11668 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11669 : SCIPsetBarrierconvtol(set), &success) );
11670 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11671 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11672 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11673 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11674 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11675 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11676 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11677 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11678 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11679 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11680 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11681 SCIP_CALL( lpSetRandomseed(lp, (int) (SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed) % INT_MAX), &success) );
11682 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11683 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11684
11685 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11686
11687 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11688 * optimal without preforming scaling/change tolerances/presolving */
11689 resolve = FALSE;
11690
11691 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11692 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11693 return SCIP_OKAY;
11694
11695 if( !set->lp_checkstability )
11696 {
11697 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11698
11699 if( success )
11700 return SCIP_OKAY;
11701 }
11702
11703 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11704 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11705 */
11706
11707 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11708 * do this only if the iteration limit was not exceeded in the last LP solving call
11709 */
11710 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11711 {
11712 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11713 if( success )
11714 {
11715 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11716 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11717
11718 /* check for stability */
11719 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11720 return SCIP_OKAY;
11721
11722 if( !set->lp_checkstability )
11723 {
11724 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11725
11726 if( success )
11727 return SCIP_OKAY;
11728 }
11729 }
11730 }
11731
11732 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11733 * and go directly to solving the LP from scratch
11734 */
11735 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11736 {
11737 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11738 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11739 if( success )
11740 {
11741 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11742 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11743 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11744
11745 /* check for stability */
11746 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11747 return SCIP_OKAY;
11748
11749 if( !set->lp_checkstability )
11750 {
11751 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11752
11753 if( success )
11754 return SCIP_OKAY;
11755 }
11756
11757 /* reset scaling */
11758 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11759 assert(success);
11760 }
11761 }
11762
11763 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11764 * and go directly to solving the LP from scratch */
11765 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11766 {
11767 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11768 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11769 if( success )
11770 {
11771 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11772 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11773 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11774
11775 /* check for stability */
11776 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11777 return SCIP_OKAY;
11778
11779 if( !set->lp_checkstability )
11780 {
11781 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11782
11783 if( success )
11784 return SCIP_OKAY;
11785 }
11786
11787 /* reset presolving */
11788 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11789 assert(success);
11790 }
11791 }
11792
11793 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11794 * do this only if the iteration limit was not exceeded in the last LP solving call
11795 */
11796 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11797 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11798 {
11799 success = FALSE;
11800 if( !tightprimfeastol )
11801 {
11802 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11803 }
11804
11805 success2 = FALSE;
11806 if( !tightdualfeastol )
11807 {
11809 }
11810
11811 success3 = FALSE;
11812 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11813 {
11815 }
11816
11817 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11818 if( success || success2 || success3 )
11819 {
11820 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11821 lpalgoName(lpalgo));
11822 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11823
11824 /* check for stability */
11825 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11826 return SCIP_OKAY;
11827
11828 if( !set->lp_checkstability )
11829 {
11830 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11831
11832 if( success )
11833 return SCIP_OKAY;
11834 }
11835
11836 /* reset feasibility tolerance */
11837 if( !tightprimfeastol )
11838 {
11839 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11840 }
11841 if( !tightdualfeastol )
11842 {
11844 }
11845 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11846 {
11848 }
11849 }
11850 }
11851
11852 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11853 * the given iteration limit might be a soft one to restrict resolving calls only */
11854 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11855
11856 /* if not already done, solve again from scratch */
11857 if( !fromscratch && simplex )
11858 {
11859 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11860 if( success )
11861 {
11862 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11863 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11864
11865 /* check for stability */
11866 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11867 return SCIP_OKAY;
11868
11869 if( !set->lp_checkstability )
11870 {
11871 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11872
11873 if( success )
11874 return SCIP_OKAY;
11875 }
11876 }
11877 }
11878
11879 /* solve again, use other simplex this time */
11880 if( simplex )
11881 {
11883 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11884 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11885
11886 /* check for stability */
11887 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11888 return SCIP_OKAY;
11889
11890 if( !set->lp_checkstability )
11891 {
11892 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11893
11894 if( success )
11895 return SCIP_OKAY;
11896 }
11897
11898 /* solve again with opposite scaling and other simplex */
11899 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11900 if( success )
11901 {
11902 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11903 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11904 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11905
11906 /* check for stability */
11907 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11908 return SCIP_OKAY;
11909
11910 if( !set->lp_checkstability )
11911 {
11912 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11913
11914 if( success )
11915 return SCIP_OKAY;
11916 }
11917
11918 /* reset scaling */
11919 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11920 assert(success);
11921 }
11922
11923 /* solve again with opposite presolving and other simplex */
11924 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11925 if( success )
11926 {
11927 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11928 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11929 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11930
11931 /* check for stability */
11932 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11933 return SCIP_OKAY;
11934
11935 if( !set->lp_checkstability )
11936 {
11937 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11938
11939 if( success )
11940 return SCIP_OKAY;
11941 }
11942
11943 /* reset presolving */
11944 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11945 assert(success);
11946 }
11947
11948 /* solve again with tighter feasibility tolerance, use other simplex this time */
11949 if( !tightprimfeastol || !tightdualfeastol )
11950 {
11951 success = FALSE;
11952 if( !tightprimfeastol )
11953 {
11954 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11955 }
11956
11957 success2 = FALSE;
11958 if( !tightdualfeastol )
11959 {
11961 }
11962
11963 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11964 if( success || success2 )
11965 {
11966 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11967 lpalgoName(lpalgo));
11968 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11969
11970 /* check for stability */
11971 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11972 return SCIP_OKAY;
11973
11974 if( !set->lp_checkstability )
11975 {
11976 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11977
11978 if( success )
11979 return SCIP_OKAY;
11980 }
11981
11982 /* reset feasibility tolerance */
11983 if( !tightprimfeastol )
11984 {
11985 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11986 }
11987 if( !tightdualfeastol )
11988 {
11990 }
11991 SCIP_UNUSED(success);
11992 }
11993 }
11994 }
11995
11996 /* nothing worked -- exit with an LPERROR */
11997 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11998 *lperror = TRUE;
11999
12000 return SCIP_OKAY;
12001}
12002
12003/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
12004static
12006 SCIP_LP* lp, /**< current LP data */
12007 SCIP_SET* set, /**< global SCIP settings */
12008 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
12009 )
12010{
12011 assert(lp != NULL);
12012 assert(set != NULL);
12013
12014 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12015 {
12016 if( !lp->adjustlpval && messagehdlr != NULL )
12017 {
12018 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12019 lp->adjustlpval = TRUE;
12020 }
12022 }
12023 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12024 {
12025 if( !lp->adjustlpval && messagehdlr != NULL )
12026 {
12027 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12028 lp->adjustlpval = TRUE;
12029 }
12031 }
12032}
12033
12034/** solves the LP with the given algorithm and evaluates return status */
12035static
12037 SCIP_LP* lp, /**< current LP data */
12038 SCIP_SET* set, /**< global SCIP settings */
12039 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12040 SCIP_STAT* stat, /**< problem statistics */
12041 SCIP_PROB* prob, /**< problem data */
12042 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12043 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12044 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12045 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12046 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12047 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12048 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12049 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12050 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12051 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12052 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12053 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12054 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12055 )
12056{
12057 SCIP_Bool solvedprimal;
12058 SCIP_Bool solveddual;
12059 SCIP_Bool timelimit;
12060 int itlim;
12061
12062 assert(lp != NULL);
12063 assert(lp->flushed);
12064 assert(set != NULL);
12065 assert(stat != NULL);
12066 assert(lperror != NULL);
12067
12068 checkLinks(lp);
12069
12070 solvedprimal = FALSE;
12071 solveddual = FALSE;
12072 timelimit = FALSE;
12073
12074 /* select the basic iteration limit depending on whether this is a resolving call or not */
12075 itlim = ( resolve ? resolveitlim : harditlim );
12076
12077 SOLVEAGAIN:
12078 /* call simplex */
12079 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12080 scaling, keepsol, &timelimit, lperror) );
12081 resolve = FALSE; /* only the first solve should be counted as resolving call */
12082 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12083 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12084
12085 /* check, if an error occurred */
12086 if( *lperror )
12087 {
12088 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12089 lp->solved = FALSE;
12091 return SCIP_OKAY;
12092 }
12093
12094 /* check, if a time limit was exceeded */
12095 if( timelimit )
12096 {
12097 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12098 lp->solved = TRUE;
12101 return SCIP_OKAY;
12102 }
12103
12104 /* only one should return true */
12107
12108 /* evaluate solution status */
12109 if( SCIPlpiIsOptimal(lp->lpi) )
12110 {
12111 assert(lp->primalfeasible);
12112 assert(lp->dualfeasible);
12114 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12115 adjustLPobjval(lp, set, messagehdlr);
12116
12118 {
12119 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12120 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12123 }
12124 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12125 * reached if the LP objective value is greater than the cutoff bound
12126 */
12127 assert(lpCutoffDisabled(set, prob, lp) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
12129 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12130 }
12131 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12132 {
12133 assert(!lpCutoffDisabled(set, prob, lp));
12134
12135#ifndef NDEBUG
12136 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12137 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12138 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12139 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12140#endif
12141
12144 }
12145 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12146 {
12147 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12148 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12149 {
12150 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12151 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12152 goto SOLVEAGAIN;
12153 }
12156 }
12157 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12158 {
12159 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12160 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12161 {
12162 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12165 goto SOLVEAGAIN;
12166 }
12169 }
12170 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12171 {
12172 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12173
12174 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12175 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12176 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12177 adjustLPobjval(lp, set, NULL);
12178 else
12179 adjustLPobjval(lp, set, messagehdlr);
12180
12182 }
12183 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12184 {
12187 }
12188 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12189 {
12190 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12191 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12192 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12193 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12194 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12195 goto SOLVEAGAIN;
12196 }
12197 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12198 {
12201 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12202 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12203 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12204 goto SOLVEAGAIN;
12205 }
12206 else
12207 {
12208 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12209 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12211 return SCIP_LPERROR;
12212 }
12213
12214 lp->solved = TRUE;
12215
12216 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12219
12220 return SCIP_OKAY;
12221}
12222
12223/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12224static
12226 SCIP_LP* lp, /**< current LP data */
12227 BMS_BLKMEM* blkmem, /**< block memory */
12228 SCIP_SET* set, /**< global SCIP settings */
12229 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12230 SCIP_STAT* stat, /**< problem statistics */
12231 SCIP_PROB* prob, /**< problem data */
12232 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12233 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12234 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12235 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12236 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12237 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12238 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12239 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12240 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12241 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12242 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12243 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12244 )
12245{
12246 SCIP_Bool resolve;
12247 char algo;
12248
12249 assert(lp != NULL);
12250 assert(set != NULL);
12251 assert(lperror != NULL);
12252
12253 /* flush changes to the LP solver */
12254 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12255 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12256
12257 /* select LP algorithm to apply */
12258 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12259 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12260
12261 switch( algo )
12262 {
12263 case 's':
12264 /* select simplex method */
12265 if( lp->dualfeasible || !lp->primalfeasible )
12266 {
12267 SCIPsetDebugMsg(set, "solving dual LP\n");
12268 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12269 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12270 }
12271 else
12272 {
12273 SCIPsetDebugMsg(set, "solving primal LP\n");
12274 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12275 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12276 }
12277 break;
12278
12279 case 'p':
12280 SCIPsetDebugMsg(set, "solving primal LP\n");
12281 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12282 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12283 break;
12284
12285 case 'd':
12286 SCIPsetDebugMsg(set, "solving dual LP\n");
12287 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12288 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12289 break;
12290
12291 case 'b':
12292 SCIPsetDebugMsg(set, "solving barrier LP\n");
12293 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12294 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12295 break;
12296
12297 case 'c':
12298 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12299 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12300 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12301 break;
12302
12303 default:
12304 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12306 }
12307 assert(!(*lperror) || !lp->solved);
12308
12309 return SCIP_OKAY;
12310}
12311
12312#ifndef NDEBUG
12313/** checks if the lazy bounds are valid */
12314static
12316 SCIP_LP* lp, /**< LP data */
12317 SCIP_SET* set /**< global SCIP settings */
12318 )
12319{
12320 SCIP_COL* col;
12321 int c;
12322
12323 assert(lp->flushed);
12324
12325 for( c = 0; c < lp->nlazycols; ++c )
12326 {
12327 col = lp->lazycols[c];
12328
12329 /* in case lazy bounds are given, check that the primal solution satisfies them */
12330 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12331 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12332 }
12333}
12334#else
12335#define checkLazyBounds(lp, set) /**/
12336#endif
12337
12338/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12339 * diving
12340 */
12341static
12343 SCIP_LP* lp, /**< LP data */
12344 SCIP_SET* set /**< global SCIP settings */
12345 )
12346{
12347 SCIP_COL* col;
12348 int c;
12349
12350 assert(lp->nlazycols > 0);
12351
12352 /* return, if we are in diving, and bounds were already applied
12353 * or if we are not in diving and bounds were not applied
12354 */
12355 if( lp->diving == lp->divinglazyapplied )
12356 return SCIP_OKAY;
12357
12358 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12359 lp->diving, lp->divinglazyapplied);
12360
12361 for( c = 0; c < lp->nlazycols; ++c )
12362 {
12363 col = lp->lazycols[c];
12364
12365 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12366 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12367 {
12368 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12369 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12370 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12371
12372 /* insert column in the chgcols list (if not already there) */
12373 SCIP_CALL( insertColChgcols(col, set, lp) );
12374
12375 /* mark bound change in the column */
12376 col->lbchanged = TRUE;
12377 }
12378
12379 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12380 if( !SCIPsetIsInfinity(set, col->lazyub) )
12381 {
12382 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12383 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12384 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12385
12386 /* insert column in the chgcols list (if not already there) */
12387 SCIP_CALL( insertColChgcols(col, set, lp) );
12388
12389 /* mark bound change in the column */
12390 col->ubchanged = TRUE;
12391 }
12392 }
12393
12394 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12395 * if not, we just removed them
12396 */
12397 lp->divinglazyapplied = lp->diving;
12398
12399 return SCIP_OKAY;
12400}
12401
12402/** returns the iteration limit for an LP resolving call */
12403static
12405 SCIP_SET* set, /**< global SCIP settings */
12406 SCIP_STAT* stat, /**< dynamic problem statistics */
12407 int itlim /**< hard iteration limit */
12408 )
12409{
12410 /* no limit set or average not yet reliable */
12411 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12412 return itlim;
12413 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12414 if( itlim == -1 )
12415 itlim = INT_MAX;
12416 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12417 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12418 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12419}
12420
12421
12422
12423/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12425 SCIP_LP* lp, /**< LP data */
12426 SCIP_SET* set, /**< global SCIP settings */
12427 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12428 BMS_BLKMEM* blkmem, /**< block memory buffers */
12429 SCIP_STAT* stat, /**< problem statistics */
12430 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12431 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12432 SCIP_PROB* prob, /**< problem data */
12433 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12434 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12435 * (limit is computed within the method w.r.t. the average LP iterations) */
12436 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12437 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12438 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
12439 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12440 )
12441{
12442 SCIP_RETCODE retcode;
12443 SCIP_Bool needprimalray;
12444 SCIP_Bool needdualray;
12445 int harditlim;
12446 int resolveitlim;
12447
12448 assert(lp != NULL);
12449 assert(prob != NULL);
12450 assert(prob->nvars >= lp->ncols);
12451 assert(lperror != NULL);
12452
12453 retcode = SCIP_OKAY;
12454 *lperror = FALSE;
12455
12456 if( lp->flushed && lp->solved )
12457 {
12458 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12459 return SCIP_OKAY;
12460 }
12461
12462 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12463 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12464
12465 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12466 needprimalray = TRUE;
12467 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12468 || (set->conf_enable && set->conf_useinflp != 'o'));
12469
12470 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12471 harditlim = (int) MIN(itlim, INT_MAX);
12472 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12473 assert(harditlim == -1 || (resolveitlim <= harditlim));
12474
12475 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12476 * or removed from the LP (diving was ended)
12477 */
12478 if( lp->nlazycols > 0 )
12479 {
12480 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12481 * first resolve LP?
12482 */
12484 assert(lp->diving == lp->divinglazyapplied);
12485 }
12486
12487 /* flush changes to the LP solver */
12488 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12489 assert(lp->flushed);
12490
12491 /* 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
12492 * to run again anyway, since there seems to be some time left / the time limit was increased
12493 */
12494 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12495 {
12496 SCIP_Bool* primalfeaspointer;
12497 SCIP_Bool* dualfeaspointer;
12498 SCIP_Bool primalfeasible;
12499 SCIP_Bool dualfeasible;
12500 SCIP_Bool farkasvalid;
12501 SCIP_Bool rayfeasible;
12502 SCIP_Bool tightprimfeastol;
12503 SCIP_Bool tightdualfeastol;
12504 SCIP_Bool fromscratch;
12505 SCIP_Bool wasfromscratch;
12506 int scaling;
12507 SCIP_Longint oldnlps;
12508 int fastmip;
12509
12510 /* set initial LP solver settings */
12511 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12512 tightprimfeastol = FALSE;
12513 tightdualfeastol = FALSE;
12514 fromscratch = FALSE;
12515 primalfeasible = FALSE;
12516 dualfeasible = FALSE;
12517 wasfromscratch = (stat->nlps == 0);
12518 scaling = set->lp_scaling;
12519
12520 SOLVEAGAIN:
12521 /* solve the LP */
12522 oldnlps = stat->nlps;
12523 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12524 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12525 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12526 assert(!(*lperror) || !lp->solved);
12527
12528 /* check for error */
12529 if( *lperror )
12530 {
12531 retcode = SCIP_OKAY;
12532 goto TERMINATE;
12533 }
12534
12535 /* evaluate solution status */
12536 switch( SCIPlpGetSolstat(lp) )
12537 {
12539 /* get LP solution and possibly check the solution's feasibility again */
12540 if( set->lp_checkprimfeas )
12541 {
12542 primalfeaspointer = &primalfeasible;
12543 lp->primalchecked = TRUE;
12544 }
12545 else
12546 {
12547 /* believe in the primal feasibility of the LP solution */
12548 primalfeasible = TRUE;
12549 primalfeaspointer = NULL;
12550 lp->primalchecked = FALSE;
12551 }
12552 if( set->lp_checkdualfeas )
12553 {
12554 dualfeaspointer = &dualfeasible;
12555 lp->dualchecked = TRUE;
12556 }
12557 else
12558 {
12559 /* believe in the dual feasibility of the LP solution */
12560 dualfeasible = TRUE;
12561 dualfeaspointer = NULL;
12562 lp->dualchecked = FALSE;
12563 }
12564
12565 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12566
12567 /* in debug mode, check that lazy bounds (if present) are not violated */
12568 checkLazyBounds(lp, set);
12569
12570 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12571 {
12572 /* update ages and remove obsolete columns and rows from LP */
12573 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12574 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12575 {
12576 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12577 }
12578
12579 if( !lp->solved )
12580 {
12581 /* resolve LP after removing obsolete columns and rows */
12582 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12583 aging = FALSE; /* to prevent infinite loops */
12584 goto SOLVEAGAIN;
12585 }
12586 }
12587 if( !primalfeasible || !dualfeasible )
12588 {
12590
12591 if( (fastmip > 0) && simplex )
12592 {
12593 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12594 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12595 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12596 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12597 fastmip = 0;
12598 goto SOLVEAGAIN;
12599 }
12600 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12601 {
12602 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12603 * tolerance
12604 */
12605 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12606 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again with tighter feasibility tolerance\n",
12607 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12608 tightprimfeastol = tightprimfeastol || !primalfeasible;
12609 tightdualfeastol = tightdualfeastol || !dualfeasible;
12610 goto SOLVEAGAIN;
12611 }
12612 else if( !fromscratch && !wasfromscratch && simplex )
12613 {
12614 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12615 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12616 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12617 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12618 fromscratch = TRUE;
12619 goto SOLVEAGAIN;
12620 }
12621 else
12622 {
12623 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12624 lp->solved = FALSE;
12626 *lperror = TRUE;
12627 }
12628 }
12629 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12630 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12631 lp->lpsolstat, lp->cutoffbound);
12632 break;
12633
12635 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12636 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->lp_alwaysgetduals || set->misc_exactsolve )
12637 {
12638 if( SCIPlpiHasDualRay(lp->lpi) )
12639 {
12640 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12641 }
12642 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12643 * with the primal simplex due to numerical problems) - treat this case like an LP error
12644 */
12645 else
12646 {
12647 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12648 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12649 lp->solved = FALSE;
12651 farkasvalid = FALSE;
12652 *lperror = TRUE;
12653 }
12654 }
12655 else
12656 farkasvalid = TRUE;
12657
12658 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12659 if( !farkasvalid && !(*lperror) )
12660 {
12662
12663 if( (fastmip > 0) && simplex )
12664 {
12665 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12666 * without FASTMIP
12667 */
12668 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12669 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12670 stat->nnodes, stat->nlps);
12671 fastmip = 0;
12672 goto SOLVEAGAIN;
12673 }
12674 else if( !tightdualfeastol )
12675 {
12676 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12677 * solve again with tighter feasibility tolerance
12678 */
12679 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12680 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter dual feasibility tolerance\n",
12681 stat->nnodes, stat->nlps);
12682 tightdualfeastol = TRUE;
12683 goto SOLVEAGAIN;
12684 }
12685 else if( !fromscratch && simplex )
12686 {
12687 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12688 * from scratch
12689 */
12690 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12691 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
12692 stat->nnodes, stat->nlps);
12693 fromscratch = TRUE;
12694 goto SOLVEAGAIN;
12695 }
12696 else
12697 {
12698 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12699 * helped forget about the LP at this node and mark it to be unsolved
12700 */
12701 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12702 lp->solved = FALSE;
12704 *lperror = TRUE;
12705 }
12706 }
12707
12708 break;
12709
12711 if( set->lp_checkprimfeas )
12712 {
12713 /* get unbounded LP solution and check the solution's feasibility again */
12714 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12715
12716 lp->primalchecked = TRUE;
12717 }
12718 else
12719 {
12720 /* get unbounded LP solution believing in the feasibility of the LP solution */
12722
12723 primalfeasible = TRUE;
12724 rayfeasible = TRUE;
12725 lp->primalchecked = FALSE;
12726 }
12727
12728 /* in debug mode, check that lazy bounds (if present) are not violated */
12729 checkLazyBounds(lp, set);
12730
12731 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12732 primalfeasible, rayfeasible);
12733
12734 if( !primalfeasible || !rayfeasible )
12735 {
12737
12738 if( (fastmip > 0) && simplex )
12739 {
12740 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12741 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12742 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12743 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12744 fastmip = 0;
12745 goto SOLVEAGAIN;
12746 }
12747 else if( !tightprimfeastol )
12748 {
12749 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12750 * tolerance
12751 */
12752 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12753 "(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",
12754 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12755 tightprimfeastol = TRUE;
12756 goto SOLVEAGAIN;
12757 }
12758 else if( !fromscratch && simplex )
12759 {
12760 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12761 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12762 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12763 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12764 fromscratch = TRUE;
12765 goto SOLVEAGAIN;
12766 }
12767 else if( scaling > 0 )
12768 {
12769 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12770 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12771 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12772 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12773 scaling = 0;
12774 goto SOLVEAGAIN;
12775 }
12776 else
12777 {
12778 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12779 * forget about the LP at this node and mark it to be unsolved
12780 */
12781 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12782 lp->solved = FALSE;
12784 *lperror = TRUE;
12785 }
12786 }
12787
12788 break;
12789
12791 assert(!lpCutoffDisabled(set, prob, lp));
12792 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12793 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12794 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12795 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12796 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12797 * FASTMIP and solve again.
12798 */
12799 if( !SCIPprobAllColsInLP(prob, set, lp) )
12800 {
12801 SCIP_LPI* lpi;
12802 SCIP_Real objval;
12803
12804 lpi = SCIPlpGetLPI(lp);
12805
12806 assert(lpi != NULL);
12807 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12808 * the assert by using !SCIPsetIsFeasNegative()
12809 */
12810 assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim));
12811
12812 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12813
12814 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12815 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12816 {
12817 SCIP_Real tmpcutoff;
12818 char tmppricingchar;
12819 SCIP_LPSOLSTAT solstat;
12820
12821 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12822
12823 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12824 fromscratch = FALSE;
12825
12826 /* temporarily disable cutoffbound, which also disables the objective limit */
12827 tmpcutoff = lp->cutoffbound;
12828 lp->cutoffbound = SCIPlpiInfinity(lpi);
12829
12830 /* set lp pricing strategy to steepest edge */
12831 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12832 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12833
12834 /* resolve LP with an iteration limit of 1 */
12835 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12836 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12837
12838 /* reinstall old cutoff bound and lp pricing strategy */
12839 lp->cutoffbound = tmpcutoff;
12840 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12841
12842 /* get objective value */
12843 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12844
12845 /* get solution status for the lp */
12846 solstat = SCIPlpGetSolstat(lp);
12847 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12848
12849 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12850
12851 /* the solution is still not exceeding the objective limit and the solving process
12852 * was stopped due to time or iteration limit, solve again with fastmip turned off
12853 */
12854 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12855 SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12856 {
12858 if( !(*lperror) && (fastmip > 0) && simplex )
12859 {
12860 fastmip = 0;
12861 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12862 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12863
12864 /* get objective value */
12865 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12866
12867 /* get solution status for the lp */
12868 solstat = SCIPlpGetSolstat(lp);
12869
12870 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12871 }
12872 }/*lint !e438*/
12873
12874 /* check for lp errors */
12875 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12876 {
12877 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12878 lp->solved = FALSE;
12880
12881 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12882 goto TERMINATE;
12883 }
12884
12885 lp->solved = TRUE;
12886
12887 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12888 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12889 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12890 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12891 {
12892 /* get LP solution and possibly check the solution's feasibility again */
12893 if( set->lp_checkprimfeas )
12894 {
12895 primalfeaspointer = &primalfeasible;
12896 lp->primalchecked = TRUE;
12897 }
12898 else
12899 {
12900 /* believe in the primal feasibility of the LP solution */
12901 primalfeasible = TRUE;
12902 primalfeaspointer = NULL;
12903 lp->primalchecked = FALSE;
12904 }
12905 if( set->lp_checkdualfeas )
12906 {
12907 dualfeaspointer = &dualfeasible;
12908 lp->dualchecked = TRUE;
12909 }
12910 else
12911 {
12912 /* believe in the dual feasibility of the LP solution */
12913 dualfeasible = TRUE;
12914 dualfeaspointer = NULL;
12915 lp->dualchecked = FALSE;
12916 }
12917
12918 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12919
12920 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12921 if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12922 {
12923 checkLazyBounds(lp, set);
12924 }
12925
12926 /* if objective value is larger than the cutoff bound, set solution status to objective
12927 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12928 * this was already done in the lpSolve() method
12929 */
12930 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12931 {
12934 }
12935
12936 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12937 * the cutoffbound; mark the LP to be unsolved
12938 */
12939 if( !primalfeasible || !dualfeasible
12940 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12941 !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
12942 {
12943 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12944 lp->solved = FALSE;
12946 *lperror = TRUE;
12947 }
12948
12949 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12950 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12951 lp->lpsolstat, lp->cutoffbound);
12952 }
12953 /* infeasible solution */
12954 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12955 {
12956 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12957
12958 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas )
12959 {
12960 if( SCIPlpiHasDualRay(lp->lpi) )
12961 {
12962 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12963 }
12964 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12965 * with the primal simplex due to numerical problems) - treat this case like an LP error
12966 */
12967 else
12968 {
12969 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12970 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12971 lp->solved = FALSE;
12973 farkasvalid = FALSE;
12974 *lperror = TRUE;
12975 }
12976 }
12977 else
12978 farkasvalid = TRUE;
12979
12980 if( !farkasvalid )
12981 {
12983
12984 if( !tightprimfeastol )
12985 {
12986 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12987 * solve again with tighter feasibility tolerance
12988 */
12989 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12990 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12991 stat->nnodes, stat->nlps);
12992 tightprimfeastol = TRUE;
12993 goto SOLVEAGAIN;
12994 }
12995 else if( simplex )
12996 {
12997 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12998 * from scratch
12999 */
13000 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
13001 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again from scratch\n",
13002 stat->nnodes, stat->nlps);
13003 fromscratch = TRUE;
13004 goto SOLVEAGAIN;
13005 }
13006 else
13007 {
13008 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
13009 * helped forget about the LP at this node and mark it to be unsolved
13010 */
13011 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
13012 lp->solved = FALSE;
13014 *lperror = TRUE;
13015 }
13016 }
13017 }
13018 /* unbounded solution */
13019 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13020 {
13021 if( set->lp_checkprimfeas )
13022 {
13023 /* get unbounded LP solution and check the solution's feasibility again */
13024 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13025
13026 lp->primalchecked = TRUE;
13027 }
13028 else
13029 {
13030 /* get unbounded LP solution believing in its feasibility */
13032
13033 primalfeasible = TRUE;
13034 rayfeasible = TRUE;
13035 lp->primalchecked = FALSE;
13036 }
13037
13038 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13039
13040 /* in debug mode, check that lazy bounds (if present) are not violated */
13041 checkLazyBounds(lp, set);
13042
13043 if( !primalfeasible || !rayfeasible )
13044 {
13045 /* unbounded solution is infeasible (this can happen due to numerical problems):
13046 * forget about the LP at this node and mark it to be unsolved
13047 *
13048 * @todo: like in the default LP solving evaluation, solve without fastmip,
13049 * with tighter feasibility tolerance and from scratch
13050 */
13051 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13052 lp->solved = FALSE;
13054 *lperror = TRUE;
13055 }
13056 }
13057
13058 assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
13059 assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
13061 }
13062 else
13063 {
13064 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13065 }
13066 }
13067 SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13068 break;
13069
13071 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13072 break;
13073
13075 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13076
13077 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13078 stat->nclockskipsleft = 0;
13079 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13080 {
13081 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13082 "you might consider switching the clock type of SCIP\n");
13084 }
13085 break;
13086
13089 SCIPerrorMessage("error in LP solver\n");
13090 retcode = SCIP_LPERROR;
13091 goto TERMINATE;
13092
13093 default:
13094 SCIPerrorMessage("unknown LP solution status\n");
13095 retcode = SCIP_ERROR;
13096 goto TERMINATE;
13097 }
13098 }
13099 assert(!(*lperror) || !lp->solved);
13100
13101 TERMINATE:
13102 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13103 * may happen that we continue to solve from scratch during strong branching */
13104 if( lp->lpifromscratch )
13105 {
13106 SCIP_Bool success;
13107 (void) lpSetFromscratch(lp, FALSE, &success);
13108 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13109 SCIP_UNUSED(success);
13110 }
13111
13112 return retcode;
13113}
13114
13115/** gets solution status of current LP */
13117 SCIP_LP* lp /**< current LP data */
13118 )
13119{
13120 assert(lp != NULL);
13121 assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
13122
13123 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13124}
13125
13126/** gets objective value of current LP
13127 *
13128 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13129 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13130 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13131 */
13133 SCIP_LP* lp, /**< current LP data */
13134 SCIP_SET* set, /**< global SCIP settings */
13135 SCIP_PROB* prob /**< problem data */
13136 )
13137{
13138 assert(lp != NULL);
13139 assert(lp->solved);
13140 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13141 assert(set != NULL);
13142
13143 if( !lp->flushed )
13144 return SCIP_INVALID;
13146 return lp->lpobjval;
13147 else if( lp->looseobjvalinf > 0 )
13148 return -SCIPsetInfinity(set);
13149 else
13150 {
13151 /* recalculate the loose objective value, if needed */
13152 if( !lp->looseobjvalid )
13154
13155 return lp->lpobjval + lp->looseobjval;
13156 }
13157}
13158
13159/** gets part of objective value of current LP that results from COLUMN variables only */
13161 SCIP_LP* lp /**< current LP data */
13162 )
13163{
13164 assert(lp != NULL);
13165 assert(lp->solved);
13166
13167 return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13168}
13169
13170/** gets part of objective value of current LP that results from LOOSE variables only */
13172 SCIP_LP* lp, /**< current LP data */
13173 SCIP_SET* set, /**< global SCIP settings */
13174 SCIP_PROB* prob /**< problem data */
13175 )
13176{
13177 assert(lp != NULL);
13178 assert(lp->solved);
13179 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13180 assert(set != NULL);
13181
13182 if( !lp->flushed )
13183 return SCIP_INVALID;
13184 else if( lp->looseobjvalinf > 0 )
13185 return -SCIPsetInfinity(set);
13186 else
13187 return getFiniteLooseObjval(lp, set, prob);
13188}
13189
13190/** remembers the current LP objective value as root solution value */
13192 SCIP_LP* lp, /**< current LP data */
13193 SCIP_SET* set, /**< global SCIP settings */
13194 SCIP_PROB* prob /**< problem data */
13195 )
13196{
13197 assert(lp != NULL);
13198
13200 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13201}
13202
13203/** invalidates the root LP solution value */
13205 SCIP_LP* lp /**< current LP data */
13206 )
13207{
13208 assert(lp != NULL);
13209
13212}
13213
13214/** recomputes local and global pseudo objective values */
13216 SCIP_LP* lp, /**< current LP data */
13217 SCIP_SET* set, /**< global SCIP settings */
13218 SCIP_PROB* prob /**< problem data */
13219 )
13220{
13221 SCIP_VAR** vars;
13222 int nvars;
13223 int v;
13224
13225 assert(lp != NULL);
13226 assert(set != NULL);
13227 assert(prob != NULL);
13228
13229 vars = prob->vars;
13230 nvars = prob->nvars;
13231
13232 lp->glbpseudoobjvalinf = 0;
13233 lp->glbpseudoobjval = 0.0;
13234
13235 lp->pseudoobjvalinf = 0;
13236 lp->pseudoobjval = 0.0;
13237
13238 for( v = 0; v < nvars; ++v )
13239 {
13240 SCIP_Real obj = SCIPvarGetObj(vars[v]);
13241
13242 if( SCIPsetIsPositive(set, obj) )
13243 {
13244 /* update the global pseudo objective value */
13245 if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
13246 ++(lp->glbpseudoobjvalinf);
13247 else
13248 lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
13249
13250 /* update the local pseudo objective value */
13251 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
13252 ++(lp->pseudoobjvalinf);
13253 else
13254 lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
13255 }
13256
13257 if( SCIPsetIsNegative(set, obj) )
13258 {
13259 /* update the global pseudo objective value */
13261 ++(lp->glbpseudoobjvalinf);
13262 else
13263 lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
13264
13265 /* update the local pseudo objective value */
13266 if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
13267 ++(lp->pseudoobjvalinf);
13268 else
13269 lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
13270 }
13271 }
13272
13273 /* the recomputed values are reliable */
13275 lp->glbpseudoobjvalid = TRUE;
13276 lp->relpseudoobjval = lp->pseudoobjval;
13277 lp->pseudoobjvalid = TRUE;
13278}
13279
13280/** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13281 * global bound
13282 */
13284 SCIP_LP* lp, /**< current LP data */
13285 SCIP_SET* set, /**< global SCIP settings */
13286 SCIP_PROB* prob /**< problem data */
13287 )
13288{
13289 assert(lp != NULL);
13290 assert(lp->glbpseudoobjvalinf >= 0);
13291 assert(set != NULL);
13292
13293 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13294 return -SCIPsetInfinity(set);
13295 else
13296 {
13297 /* recalculate the global pseudo solution value, if needed */
13298 if( !lp->glbpseudoobjvalid )
13300
13301 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13303 return -SCIPsetInfinity(set);
13304
13306 return SCIPsetInfinity(set);
13307
13308 return lp->glbpseudoobjval;
13309 }
13310}
13311
13312/** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13313 * objective function) local bound
13314 */
13316 SCIP_LP* lp, /**< current LP data */
13317 SCIP_SET* set, /**< global SCIP settings */
13318 SCIP_PROB* prob /**< problem data */
13319 )
13320{
13321 assert(lp != NULL);
13322 assert(lp->pseudoobjvalinf >= 0);
13323 assert(set != NULL);
13324
13325 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13326 return -SCIPsetInfinity(set);
13327 else
13328 {
13329 /* recalculate the pseudo solution value, if needed */
13330 if( !lp->pseudoobjvalid )
13332
13333 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13335 return -SCIPsetInfinity(set);
13336
13338 return SCIPsetInfinity(set);
13339
13340 return lp->pseudoobjval;
13341 }
13342}
13343
13344/** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13346 SCIP_LP* lp, /**< current LP data */
13347 SCIP_SET* set, /**< global SCIP settings */
13348 SCIP_PROB* prob, /**< problem data */
13349 SCIP_VAR* var, /**< problem variable */
13350 SCIP_Real oldbound, /**< old value for bound */
13351 SCIP_Real newbound, /**< new value for bound */
13352 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13353 )
13354{
13355 SCIP_Real pseudoobjval;
13356 int pseudoobjvalinf;
13357 SCIP_Real obj;
13358
13359 pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13360 pseudoobjvalinf = lp->pseudoobjvalinf;
13361 obj = SCIPvarGetObj(var);
13362 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13363 {
13364 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13365 pseudoobjvalinf--;
13366 else
13367 pseudoobjval -= oldbound * obj;
13368 assert(pseudoobjvalinf >= 0);
13369 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13370 pseudoobjvalinf++;
13371 else
13372 pseudoobjval += newbound * obj;
13373 }
13374 assert(pseudoobjvalinf >= 0);
13375
13376 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13377 return -SCIPsetInfinity(set);
13378 else
13379 return pseudoobjval;
13380}
13381
13382/** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13383 * perform calculations with interval arithmetic to get an exact lower bound
13384 */
13386 SCIP_LP* lp, /**< current LP data */
13387 SCIP_SET* set, /**< global SCIP settings */
13388 SCIP_VAR* var, /**< problem variable */
13389 SCIP_Real oldbound, /**< old value for bound */
13390 SCIP_Real newbound, /**< new value for bound */
13391 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13392 )
13393{
13394 SCIP_Real pseudoobjval;
13395 int pseudoobjvalinf;
13396 SCIP_Real obj;
13397
13398 assert(lp->pseudoobjvalid);
13399
13400 pseudoobjval = lp->pseudoobjval;
13401 pseudoobjvalinf = lp->pseudoobjvalinf;
13402 obj = SCIPvarGetObj(var);
13403 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13404 {
13405 SCIP_INTERVAL objint;
13406 SCIP_INTERVAL bd;
13407 SCIP_INTERVAL prod;
13408 SCIP_INTERVAL psval;
13409
13410 SCIPintervalSet(&psval, pseudoobjval);
13411 SCIPintervalSet(&objint, SCIPvarGetObj(var));
13412
13413 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13414 pseudoobjvalinf--;
13415 else
13416 {
13417 SCIPintervalSet(&bd, oldbound);
13418 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13419 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13420 }
13421 assert(pseudoobjvalinf >= 0);
13422 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13423 pseudoobjvalinf++;
13424 else
13425 {
13426 SCIPintervalSet(&bd, newbound);
13427 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13428 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13429 }
13430
13431 pseudoobjval = SCIPintervalGetInf(psval);
13432 }
13433 assert(pseudoobjvalinf >= 0);
13434
13435 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13436 return -SCIPsetInfinity(set);
13437 else
13438 return pseudoobjval;
13439}
13440
13441/** compute the objective delta due the new objective coefficient */
13442static
13444 SCIP_SET* set, /**< global SCIP settings */
13445 SCIP_Real oldobj, /**< old objective value of variable */
13446 SCIP_Real newobj, /**< new objective value of variable */
13447 SCIP_Real lb, /**< lower bound of variable */
13448 SCIP_Real ub, /**< upper bound of variable */
13449 SCIP_Real* deltaval, /**< pointer to store the delta value */
13450 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13451 )
13452{
13453 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13454 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13455 assert(!SCIPsetIsInfinity(set, lb));
13456 assert(!SCIPsetIsInfinity(set, -ub));
13457 assert(!SCIPsetIsEQ(set, oldobj, newobj));
13458
13459 (*deltaval) = 0.0;
13460 (*deltainf) = 0;
13461
13462 if( SCIPsetIsPositive(set, oldobj) )
13463 {
13464 /* sign of objective did not change */
13465 if( SCIPsetIsPositive(set, newobj) )
13466 {
13467 /* if the bound is finite, calculate the deltaval */
13468 if( !SCIPsetIsInfinity(set, -lb) )
13469 (*deltaval) = lb * (newobj - oldobj);
13470 }
13471 /* sign of objective did change, so the best bound does change */
13472 else if( SCIPsetIsNegative(set, newobj) )
13473 {
13474 if( SCIPsetIsInfinity(set, -lb) )
13475 {
13476 /* old best bound was infinite while new one is not */
13477 if( !SCIPsetIsInfinity(set, ub) )
13478 {
13479 (*deltainf) = -1;
13480 (*deltaval) = ub * newobj;
13481 }
13482 }
13483 else
13484 {
13485 /* new best bound is infinite while old one was not */
13486 if( SCIPsetIsInfinity(set, ub) )
13487 {
13488 (*deltainf) = 1;
13489 (*deltaval) = -lb * oldobj;
13490 }
13491 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13492 else
13493 {
13494 (*deltaval) = (ub * newobj) - (lb * oldobj);
13495 }
13496 }
13497 }
13498 /* new objective is 0.0 */
13499 else
13500 {
13501 if( SCIPsetIsInfinity(set, -lb) )
13502 (*deltainf) = -1;
13503 else
13504 (*deltaval) = -lb * oldobj;
13505 }
13506 }
13507 else if( SCIPsetIsNegative(set, oldobj) )
13508 {
13509 /* sign of objective did not change */
13510 if( SCIPsetIsNegative(set, newobj) )
13511 {
13512 /* if the bound is finite, calculate the deltaval */
13513 if( !SCIPsetIsInfinity(set, ub) )
13514 (*deltaval) = ub * (newobj - oldobj);
13515 }
13516 /* sign of objective did change, so the best bound does change */
13517 else if( SCIPsetIsPositive(set, newobj) )
13518 {
13519 if( SCIPsetIsInfinity(set, ub) )
13520 {
13521 /* old best bound was infinite while new one is not */
13522 if( !SCIPsetIsInfinity(set, -lb) )
13523 {
13524 (*deltainf) = -1;
13525 (*deltaval) = lb * newobj;
13526 }
13527 }
13528 else
13529 {
13530 /* new best bound is infinite while old one was not */
13531 if( SCIPsetIsInfinity(set, -lb) )
13532 {
13533 (*deltainf) = 1;
13534 (*deltaval) = -ub * oldobj;
13535 }
13536 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13537 else
13538 {
13539 (*deltaval) = (lb * newobj) - (ub * oldobj);
13540 }
13541 }
13542 }
13543 /* new objective is 0.0 */
13544 else
13545 {
13546 if( SCIPsetIsInfinity(set, ub) )
13547 (*deltainf) = -1;
13548 else
13549 (*deltaval) = -ub * oldobj;
13550 }
13551 }
13552 /* old objective was 0.0 */
13553 else
13554 {
13555 if( SCIPsetIsNegative(set, newobj) )
13556 {
13557 if( SCIPsetIsInfinity(set, ub) )
13558 (*deltainf) = 1;
13559 else
13560 (*deltaval) = ub * newobj;
13561 }
13562 else if( SCIPsetIsPositive(set, newobj) )
13563 {
13564 if( SCIPsetIsInfinity(set, -lb) )
13565 (*deltainf) = 1;
13566 else
13567 (*deltaval) = lb * newobj;
13568 }
13569 }
13570}
13571
13572/** compute the objective delta due the new lower bound */
13573static
13575 SCIP_SET* set, /**< global SCIP settings */
13576 SCIP_Real obj, /**< objective value of variable */
13577 SCIP_Real oldlb, /**< old lower bound of variable */
13578 SCIP_Real newlb, /**< new lower bound of variable */
13579 SCIP_Real* deltaval, /**< pointer to store the delta value */
13580 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13581 )
13582{
13583 assert(obj > 0.0);
13584 assert(!SCIPsetIsInfinity(set, obj));
13585 assert(!SCIPsetIsInfinity(set, oldlb));
13586 assert(!SCIPsetIsInfinity(set, newlb));
13587 assert(newlb != oldlb); /*lint !e777*/
13588
13589 if( SCIPsetIsInfinity(set, -newlb) )
13590 {
13591 assert(!SCIPsetIsInfinity(set, -oldlb));
13592
13593 *deltainf = 1;
13594 *deltaval = -obj * oldlb;
13595 }
13596 else if( SCIPsetIsInfinity(set, -oldlb) )
13597 {
13598 assert(!SCIPsetIsInfinity(set, -newlb));
13599
13600 *deltainf = -1;
13601 *deltaval = obj * newlb;
13602 }
13603 else
13604 {
13605 *deltainf = 0;
13606 *deltaval = obj * (newlb - oldlb);
13607 }
13608}
13609
13610/** compute the objective delta due the new upper bound */
13611static
13613 SCIP_SET* set, /**< global SCIP settings */
13614 SCIP_Real obj, /**< objective value of variable */
13615 SCIP_Real oldub, /**< old upper bound of variable */
13616 SCIP_Real newub, /**< new upper bound of variable */
13617 SCIP_Real* deltaval, /**< pointer to store the delta value */
13618 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13619 )
13620{
13621 assert(obj < 0.0);
13622 assert(!SCIPsetIsInfinity(set, -obj));
13623 assert(!SCIPsetIsInfinity(set, -oldub));
13624 assert(!SCIPsetIsInfinity(set, -newub));
13625 assert(newub != oldub); /*lint !e777*/
13626
13627 if( SCIPsetIsInfinity(set, newub) )
13628 {
13629 assert(!SCIPsetIsInfinity(set, oldub));
13630
13631 *deltainf = 1;
13632 *deltaval = -obj * oldub;
13633 }
13634 else if( SCIPsetIsInfinity(set, oldub) )
13635 {
13636 assert(!SCIPsetIsInfinity(set, newub));
13637
13638 *deltainf = -1;
13639 *deltaval = obj * newub;
13640 }
13641 else
13642 {
13643 *deltainf = 0;
13644 *deltaval = obj * (newub - oldub);
13645 }
13646}
13647
13648/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13649static
13651 SCIP_LP* lp, /**< current LP data */
13652 SCIP_SET* set, /**< global SCIP settings */
13653 SCIP_VAR* var, /**< problem variable that changed */
13654 SCIP_Real deltaval, /**< delta value in the objective function */
13655 int deltainf, /**< delta value for the number of variables with infinite best bound */
13656 SCIP_Bool local, /**< should the local pseudo objective value be updated? */
13657 SCIP_Bool loose, /**< should the loose objective value be updated? */
13658 SCIP_Bool global /**< should the global pseudo objective value be updated? */
13659 )
13660{
13661 assert(lp != NULL);
13662 assert(lp->looseobjvalinf >= 0);
13663 assert(lp->pseudoobjvalinf >= 0);
13664 assert(lp->glbpseudoobjvalinf >= 0);
13665
13666 /* update the pseudo objective value */
13667 if( local )
13668 {
13669 lp->pseudoobjvalinf += deltainf;
13670 if( lp->pseudoobjvalid )
13671 {
13672 lp->pseudoobjval += deltaval;
13673
13674 /* if the absolute value was increased, this is regarded as reliable,
13675 * otherwise, we check whether we can still trust the updated value
13676 */
13678 lp->relpseudoobjval = lp->pseudoobjval;
13680 lp->pseudoobjvalid = FALSE;
13681 }
13682
13683 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13685 loose = TRUE;
13686 }
13687 /* update the loose objective value */
13688 if( loose )
13689 {
13690 lp->looseobjvalinf += deltainf;
13691
13692 if( deltaval != 0.0 && lp->looseobjvalid )
13693 {
13694 lp->looseobjval += deltaval;
13695
13696 /* if the absolute value was increased, this is regarded as reliable,
13697 * otherwise, we check whether we can still trust the updated value
13698 */
13699 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13700 lp->rellooseobjval = lp->looseobjval;
13702 lp->looseobjvalid = FALSE;
13703 }
13704 }
13705 /* update the root pseudo objective values */
13706 if( global )
13707 {
13708 lp->glbpseudoobjvalinf += deltainf;
13709 if( lp->glbpseudoobjvalid )
13710 {
13711 lp->glbpseudoobjval += deltaval;
13712
13713 /* if the absolute value was increased, this is regarded as reliable,
13714 * otherwise, we check whether we can still trust the updated value
13715 */
13720 }
13721 }
13722
13723 assert(lp->looseobjvalinf >= 0);
13724 assert(lp->pseudoobjvalinf >= 0);
13725 assert(lp->glbpseudoobjvalinf >= 0);
13726}
13727
13728/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13729 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13730 */
13731static
13733 SCIP_LP* lp, /**< current LP data */
13734 SCIP_SET* set, /**< global SCIP settings */
13735 SCIP_VAR* var, /**< problem variable that changed */
13736 SCIP_Real oldobj, /**< old objective value of variable */
13737 SCIP_Real oldlb, /**< old objective value of variable */
13738 SCIP_Real oldub, /**< old objective value of variable */
13739 SCIP_Real newobj, /**< new objective value of variable */
13740 SCIP_Real newlb, /**< new objective value of variable */
13741 SCIP_Real newub /**< new objective value of variable */
13742 )
13743{
13744 SCIP_INTERVAL deltaval;
13745 SCIP_INTERVAL bd;
13746 SCIP_INTERVAL obj;
13747 SCIP_INTERVAL prod;
13748 SCIP_INTERVAL psval;
13749 int deltainf;
13750
13751 assert(lp != NULL);
13752 assert(lp->pseudoobjvalinf >= 0);
13753 assert(lp->looseobjvalinf >= 0);
13754 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13755 assert(!SCIPsetIsInfinity(set, oldlb));
13756 assert(!SCIPsetIsInfinity(set, -oldub));
13757 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13758 assert(!SCIPsetIsInfinity(set, newlb));
13759 assert(!SCIPsetIsInfinity(set, -newub));
13760 assert(var != NULL);
13761
13763 {
13764 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13765 return SCIP_INVALIDDATA;
13766 }
13767
13768 assert(SCIPvarGetProbindex(var) >= 0);
13769
13770 SCIPintervalSet(&deltaval, 0.0);
13771 deltainf = 0;
13772
13773 /* subtract old pseudo objective value */
13774 if( oldobj > 0.0 )
13775 {
13776 if( SCIPsetIsInfinity(set, -oldlb) )
13777 deltainf--;
13778 else
13779 {
13780 SCIPintervalSet(&bd, oldlb);
13781 SCIPintervalSet(&obj, oldobj);
13782 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13783 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
13784 }
13785 }
13786 else if( oldobj < 0.0 )
13787 {
13788 if( SCIPsetIsInfinity(set, oldub) )
13789 deltainf--;
13790 else
13791 {
13792 SCIPintervalSet(&bd, oldub);
13793 SCIPintervalSet(&obj, oldobj);
13794 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13795 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
13796 }
13797 }
13798
13799 /* add new pseudo objective value */
13800 if( newobj > 0.0 )
13801 {
13802 if( SCIPsetIsInfinity(set, -newlb) )
13803 deltainf++;
13804 else
13805 {
13806 SCIPintervalSet(&bd, newlb);
13807 SCIPintervalSet(&obj, newobj);
13808 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13809 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
13810 }
13811 }
13812 else if( newobj < 0.0 )
13813 {
13814 if( SCIPsetIsInfinity(set, newub) )
13815 deltainf++;
13816 else
13817 {
13818 SCIPintervalSet(&bd, newub);
13819 SCIPintervalSet(&obj, newobj);
13820 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13821 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
13822 }
13823 }
13824
13825 /* update the pseudo and loose objective values */
13826 SCIPintervalSet(&psval, lp->pseudoobjval);
13827 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13828 lp->pseudoobjval = SCIPintervalGetInf(psval);
13829 lp->pseudoobjvalinf += deltainf;
13831 {
13832 SCIPintervalSet(&psval, lp->looseobjval);
13833 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13834 lp->looseobjval = SCIPintervalGetInf(psval);
13835 lp->looseobjvalinf += deltainf;
13836 }
13837
13838 assert(lp->pseudoobjvalinf >= 0);
13839 assert(lp->looseobjvalinf >= 0);
13840
13841 return SCIP_OKAY;
13842}
13843
13844/** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13846 SCIP_LP* lp, /**< current LP data */
13847 SCIP_SET* set, /**< global SCIP settings */
13848 SCIP_VAR* var, /**< problem variable that changed */
13849 SCIP_Real oldobj, /**< old objective coefficient of variable */
13850 SCIP_Real newobj /**< new objective coefficient of variable */
13851 )
13852{
13853 assert(set != NULL);
13854 assert(var != NULL);
13855
13856 if( set->misc_exactsolve )
13857 {
13858 if( oldobj != newobj ) /*lint !e777*/
13859 {
13861 newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
13862 }
13863 }
13864 else
13865 {
13866 if( !SCIPsetIsEQ(set, oldobj, newobj) )
13867 {
13868 SCIP_Real deltaval;
13869 int deltainf;
13870
13872 assert(SCIPvarGetProbindex(var) >= 0);
13873
13874 /* the objective coefficient can only be changed during presolving, that implies that the global and local
13875 * domain of the variable are the same
13876 */
13877 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
13878 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
13879
13880 /* compute the pseudo objective delta due the new objective coefficient */
13881 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
13882
13883 /* update the local pseudo objective value */
13884 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13885
13886 /* compute the pseudo objective delta due the new objective coefficient */
13887 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
13888
13889 /* update the global pseudo objective value */
13890 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13891 }
13892 }
13893
13894 return SCIP_OKAY;
13895}
13896
13897
13898/** updates current root pseudo objective value for a global change in a variable's lower bound */
13900 SCIP_LP* lp, /**< current LP data */
13901 SCIP_SET* set, /**< global SCIP settings */
13902 SCIP_VAR* var, /**< problem variable that changed */
13903 SCIP_Real oldlb, /**< old lower bound of variable */
13904 SCIP_Real newlb /**< new lower bound of variable */
13905 )
13906{
13907 assert(set != NULL);
13908 assert(var != NULL);
13909
13910 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13911 {
13912 SCIP_Real deltaval;
13913 int deltainf;
13914
13915 /* compute the pseudo objective delta due the new lower bound */
13916 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13917
13918 /* update the root pseudo objective values */
13919 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13920 }
13921
13922 return SCIP_OKAY;
13923}
13924
13925/** updates current pseudo and loose objective value for a change in a variable's lower bound */
13927 SCIP_LP* lp, /**< current LP data */
13928 SCIP_SET* set, /**< global SCIP settings */
13929 SCIP_VAR* var, /**< problem variable that changed */
13930 SCIP_Real oldlb, /**< old lower bound of variable */
13931 SCIP_Real newlb /**< new lower bound of variable */
13932 )
13933{
13934 assert(set != NULL);
13935 assert(var != NULL);
13936
13937 if( set->misc_exactsolve )
13938 {
13939 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13940 {
13941 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
13942 SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
13943 }
13944 }
13945 else
13946 {
13947 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13948 {
13949 SCIP_Real deltaval;
13950 int deltainf;
13951
13953 assert(SCIPvarGetProbindex(var) >= 0);
13954
13955 /* compute the pseudo objective delta due the new lower bound */
13956 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13957
13958 /* update the pseudo and loose objective values */
13959 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13960 }
13961 }
13962
13963 return SCIP_OKAY;
13964}
13965
13966/** updates current root pseudo objective value for a global change in a variable's upper bound */
13968 SCIP_LP* lp, /**< current LP data */
13969 SCIP_SET* set, /**< global SCIP settings */
13970 SCIP_VAR* var, /**< problem variable that changed */
13971 SCIP_Real oldub, /**< old upper bound of variable */
13972 SCIP_Real newub /**< new upper bound of variable */
13973 )
13974{
13975 assert(set != NULL);
13976 assert(var != NULL);
13977
13978 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13979 {
13980 SCIP_Real deltaval;
13981 int deltainf;
13982
13983 /* compute the pseudo objective delta due the new upper bound */
13984 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13985
13986 /* update the root pseudo objective values */
13987 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13988 }
13989
13990 return SCIP_OKAY;
13991}
13992
13993/** updates current pseudo objective value for a change in a variable's upper bound */
13995 SCIP_LP* lp, /**< current LP data */
13996 SCIP_SET* set, /**< global SCIP settings */
13997 SCIP_VAR* var, /**< problem variable that changed */
13998 SCIP_Real oldub, /**< old upper bound of variable */
13999 SCIP_Real newub /**< new upper bound of variable */
14000 )
14001{
14002 assert(set != NULL);
14003 assert(var != NULL);
14004
14005 if( set->misc_exactsolve )
14006 {
14007 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14008 {
14009 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
14010 SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
14011 }
14012 }
14013 else
14014 {
14015 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14016 {
14017 SCIP_Real deltaval;
14018 int deltainf;
14019
14021 assert(SCIPvarGetProbindex(var) >= 0);
14022
14023 /* compute the pseudo objective delta due the new upper bound */
14024 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14025
14026 /* update the pseudo and loose objective values */
14027 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14028 }
14029 }
14030
14031 return SCIP_OKAY;
14032}
14033
14034/** informs LP, that given variable was added to the problem */
14036 SCIP_LP* lp, /**< current LP data */
14037 SCIP_SET* set, /**< global SCIP settings */
14038 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
14039 )
14040{
14041 assert(lp != NULL);
14043 assert(SCIPvarGetProbindex(var) >= 0);
14044
14045 /* add the variable to the loose objective value sum */
14046 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
14047
14048 /* update the loose variables counter */
14050 lp->nloosevars++;
14051
14052 return SCIP_OKAY;
14053}
14054
14055/** informs LP, that given variable is to be deleted from the problem */
14057 SCIP_LP* lp, /**< current LP data */
14058 SCIP_SET* set, /**< global SCIP settings */
14059 SCIP_VAR* var /**< variable that will be deleted from the problem */
14060 )
14061{
14062 assert(lp != NULL);
14064 assert(SCIPvarGetProbindex(var) >= 0);
14065
14066 /* subtract the variable from the loose objective value sum */
14067 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
14068
14069 /* update the loose variables counter */
14071 {
14073 }
14074
14075 return SCIP_OKAY;
14076}
14077
14078/** informs LP, that given formerly loose problem variable is now a column variable */
14079static
14081 SCIP_LP* lp, /**< current LP data */
14082 SCIP_SET* set, /**< global SCIP settings */
14083 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14084 )
14085{
14086 SCIP_Real obj;
14087 SCIP_Real lb;
14088 SCIP_Real ub;
14089
14090 assert(lp != NULL);
14091 assert(lp->nloosevars > 0);
14093 assert(SCIPvarGetProbindex(var) >= 0);
14094 assert(lp->looseobjvalinf >= 0);
14095
14096 obj = SCIPvarGetObj(var);
14097
14098 /* update loose objective value */
14099 if( SCIPsetIsPositive(set, obj) )
14100 {
14101 lb = SCIPvarGetLbLocal(var);
14102 if( SCIPsetIsInfinity(set, -lb) )
14103 lp->looseobjvalinf--;
14104 else
14105 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14106 }
14107 else if( SCIPsetIsNegative(set, obj) )
14108 {
14109 ub = SCIPvarGetUbLocal(var);
14110 if( SCIPsetIsInfinity(set, ub) )
14111 lp->looseobjvalinf--;
14112 else
14113 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14114 }
14115
14117
14118 assert(lp->looseobjvalinf >= 0);
14119
14120 return SCIP_OKAY;
14121}
14122
14123/** informs LP, that given formerly loose problem variable is now a column variable
14124 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14125 */
14126static
14128 SCIP_LP* lp, /**< current LP data */
14129 SCIP_SET* set, /**< global SCIP settings */
14130 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14131 )
14132{
14133 SCIP_INTERVAL bd;
14134 SCIP_INTERVAL ob;
14135 SCIP_INTERVAL prod;
14136 SCIP_INTERVAL loose;
14137 SCIP_Real obj;
14138 SCIP_Real lb;
14139 SCIP_Real ub;
14140
14141 assert(lp != NULL);
14142 assert(lp->nloosevars > 0);
14144 assert(SCIPvarGetProbindex(var) >= 0);
14145
14146 obj = SCIPvarGetObj(var);
14147
14148 SCIPintervalSet(&loose, lp->looseobjval);
14149
14150 /* update loose objective value corresponding to the deletion of variable */
14151 if( obj > 0.0 )
14152 {
14153 lb = SCIPvarGetLbLocal(var);
14154 if( SCIPsetIsInfinity(set, -lb) )
14155 lp->looseobjvalinf--;
14156 else
14157 {
14158 SCIPintervalSet(&bd, lb);
14159 SCIPintervalSet(&ob, obj);
14160 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14161 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
14162 }
14163 }
14164 else if( SCIPsetIsNegative(set, obj) )
14165 {
14166 ub = SCIPvarGetUbLocal(var);
14167 if( SCIPsetIsInfinity(set, ub) )
14168 lp->looseobjvalinf--;
14169 else
14170 {
14171 SCIPintervalSet(&bd, ub);
14172 SCIPintervalSet(&ob, obj);
14173 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14174 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
14175 }
14176 }
14177 lp->nloosevars--;
14178
14179 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14180 if( lp->nloosevars == 0 )
14181 {
14182 assert(lp->looseobjvalinf == 0);
14183 lp->looseobjval = 0.0;
14184 }
14185 else
14186 lp->looseobjval = SCIPintervalGetInf(loose);
14187
14188 return SCIP_OKAY;
14189}
14190
14191/** informs LP, that given formerly loose problem variable is now a column variable */
14193 SCIP_LP* lp, /**< current LP data */
14194 SCIP_SET* set, /**< global SCIP settings */
14195 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14196 )
14197{
14198 assert(set != NULL);
14199
14200 if( set->misc_exactsolve )
14201 {
14203 }
14204 else
14205 {
14206 SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
14207 }
14208
14209 return SCIP_OKAY;
14210}
14211
14212/** informs LP, that given formerly column problem variable is now again a loose variable */
14213static
14215 SCIP_LP* lp, /**< current LP data */
14216 SCIP_SET* set, /**< global SCIP settings */
14217 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14218 )
14219{
14220 SCIP_Real obj;
14221 SCIP_Real lb;
14222 SCIP_Real ub;
14223
14224 assert(lp != NULL);
14225 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14226 assert(SCIPvarGetProbindex(var) >= 0);
14227 assert(lp->looseobjvalinf >= 0);
14228
14229 obj = SCIPvarGetObj(var);
14230
14231 /* update loose objective value corresponding to the addition of variable */
14232 if( SCIPsetIsPositive(set, obj) )
14233 {
14234 lb = SCIPvarGetLbLocal(var);
14235 if( SCIPsetIsInfinity(set, -lb) )
14236 lp->looseobjvalinf++;
14237 else
14238 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14239 }
14240 else if( SCIPsetIsNegative(set, obj) )
14241 {
14242 ub = SCIPvarGetUbLocal(var);
14243 if( SCIPsetIsInfinity(set, ub) )
14244 lp->looseobjvalinf++;
14245 else
14246 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14247 }
14248 lp->nloosevars++;
14249
14250 assert(lp->looseobjvalinf >= 0);
14251
14252 return SCIP_OKAY;
14253}
14254
14255/** informs LP, that given formerly column problem variable is now again a loose variable
14256 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14257 */
14258static
14260 SCIP_LP* lp, /**< current LP data */
14261 SCIP_SET* set, /**< global SCIP settings */
14262 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14263 )
14264{
14265 SCIP_INTERVAL bd;
14266 SCIP_INTERVAL ob;
14267 SCIP_INTERVAL prod;
14268 SCIP_INTERVAL loose;
14269 SCIP_Real obj;
14270 SCIP_Real lb;
14271 SCIP_Real ub;
14272
14273 assert(lp != NULL);
14274 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14275 assert(SCIPvarGetProbindex(var) >= 0);
14276
14277 obj = SCIPvarGetObj(var);
14278
14279 SCIPintervalSet(&loose, lp->looseobjval);
14280
14281 /* update loose objective value corresponding to the deletion of variable */
14282 if( obj > 0.0 )
14283 {
14284 lb = SCIPvarGetLbLocal(var);
14285 if( SCIPsetIsInfinity(set, -lb) )
14286 lp->looseobjvalinf++;
14287 else
14288 {
14289 SCIPintervalSet(&bd, lb);
14290 SCIPintervalSet(&ob, obj);
14291 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14292 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
14293 }
14294 }
14295 else if( SCIPsetIsNegative(set, obj) )
14296 {
14297 ub = SCIPvarGetUbLocal(var);
14298 if( SCIPsetIsInfinity(set, ub) )
14299 lp->looseobjvalinf++;
14300 else
14301 {
14302 SCIPintervalSet(&bd, ub);
14303 SCIPintervalSet(&ob, obj);
14304 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14305 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
14306 }
14307 }
14308 lp->nloosevars++;
14309
14310 lp->looseobjval = SCIPintervalGetInf(loose);
14311
14312 return SCIP_OKAY;
14313}
14314
14315/** informs LP, that given formerly column problem variable is now again a loose variable */
14317 SCIP_LP* lp, /**< current LP data */
14318 SCIP_SET* set, /**< global SCIP settings */
14319 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14320 )
14321{
14322 assert(set != NULL);
14323
14324 if( set->misc_exactsolve )
14325 {
14327 }
14328 else
14329 {
14330 SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
14331 }
14332
14333 return SCIP_OKAY;
14334}
14335
14336/** decrease the number of loose variables by one */
14338 SCIP_LP* lp /**< current LP data */
14339 )
14340{
14341 assert(lp != NULL);
14342 assert(lp->nloosevars > 0);
14343
14344 lp->nloosevars--;
14345
14346 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14347 if( lp->nloosevars == 0 )
14348 {
14349 assert(lp->looseobjvalinf == 0);
14350 lp->looseobjval = 0.0;
14351 }
14352}
14353
14354/** stores the LP solution in the columns and rows */
14356 SCIP_LP* lp, /**< current LP data */
14357 SCIP_SET* set, /**< global SCIP settings */
14358 SCIP_STAT* stat, /**< problem statistics */
14359 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14360 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
14361 )
14362{
14363 SCIP_COL** lpicols;
14364 SCIP_ROW** lpirows;
14365 SCIP_Real* primsol;
14366 SCIP_Real* dualsol;
14367 SCIP_Real* activity = NULL;
14368 SCIP_Real* redcost;
14369 SCIP_Real primalbound;
14370 SCIP_Real dualbound;
14371 SCIP_Bool stillprimalfeasible;
14372 SCIP_Bool stilldualfeasible;
14373 int* cstat;
14374 int* rstat;
14375 SCIP_Longint lpcount;
14376 int nlpicols;
14377 int nlpirows;
14378 int c;
14379 int r;
14380
14381 assert(lp != NULL);
14382 assert(lp->flushed);
14383 assert(lp->solved);
14384 assert(set != NULL);
14385 assert(stat != NULL);
14386 assert(lp->validsollp <= stat->lpcount);
14387
14388 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
14389
14390 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14391 * corresponding flag immediately to FALSE to skip all checks
14392 */
14393 if( primalfeasible == NULL )
14394 stillprimalfeasible = FALSE;
14395 else
14396 {
14397 *primalfeasible = TRUE;
14398 stillprimalfeasible = TRUE;
14399 }
14400 if( dualfeasible == NULL )
14401 stilldualfeasible = FALSE;
14402 else
14403 {
14404 *dualfeasible = TRUE;
14405 stilldualfeasible = TRUE;
14406 }
14407
14408 /* check if the values are already calculated */
14409 if( lp->validsollp == stat->lpcount )
14410 return SCIP_OKAY;
14411 lp->validsollp = stat->lpcount;
14412
14413 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14414 stat->lpcount, SCIPlpGetSolstat(lp));
14415
14416 lpicols = lp->lpicols;
14417 lpirows = lp->lpirows;
14418 nlpicols = lp->nlpicols;
14419 nlpirows = lp->nlpirows;
14420 lpcount = stat->lpcount;
14421
14422 /* get temporary memory */
14423 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
14424 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14425#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14426 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14427#endif
14428 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14429 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14430 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14431
14432 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14433 if( lp->solisbasic )
14434 {
14435 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14436 }
14437 else
14438 {
14439 BMSclearMemoryArray(cstat, nlpicols);
14440 BMSclearMemoryArray(rstat, nlpirows);
14441 }
14442
14443 primalbound = 0.0;
14444 dualbound = 0.0;
14445
14446 /* copy primal solution and reduced costs into columns */
14447 for( c = 0; c < nlpicols; ++c )
14448 {
14449 assert( 0 <= cstat[c] && cstat[c] < 4 );
14450 lpicols[c]->primsol = primsol[c];
14451 if( !SCIPisFinite(lpicols[c]->primsol) )
14452 {
14453 /* calculating with nan or +/-inf can have many unexpected effects
14454 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14455 * this should trigger a resolve of the LP, or a stop with an LP error
14456 */
14457 stillprimalfeasible = FALSE;
14458 stilldualfeasible = FALSE;
14459 lpicols[c]->primsol = 0.0;
14460 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14461 }
14462 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14463 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14464 lpicols[c]->redcost = redcost[c];
14465 lpicols[c]->basisstatus = (unsigned int) cstat[c];
14466 lpicols[c]->validredcostlp = lpcount;
14467 if( stillprimalfeasible )
14468 {
14469 stillprimalfeasible =
14470 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14471 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14472 primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14473 }
14474 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14475 {
14476 double compslack;
14477
14478 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14479 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14480 * variables, which would magnify even the tiniest violation in the dual multiplier
14481 */
14482 if( stilldualfeasible )
14483 {
14484 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14485 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14486 }
14487 if( stilldualfeasible )
14488 {
14489 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14490 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14491 }
14492
14493 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14494 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14495 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14496 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14497 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14498 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14499 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14500 dualfeasible != NULL ? stilldualfeasible : TRUE);
14501 }
14502 else
14503 {
14504 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14505 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14506 {
14507 lpicols[c]->redcost = 0.0;
14508 }
14509
14510 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14511 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14512 * bounds, its reduced cost must be zero
14513 */
14514 if( stilldualfeasible
14515 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14516 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14517 if( stilldualfeasible
14518 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14519 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14520
14521 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14522 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14523 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14524 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14525 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14526 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14527 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14528 dualfeasible != NULL ? stilldualfeasible : TRUE);
14529 }
14530
14531 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14532 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14533 * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14534 */
14535 if( stilldualfeasible )
14536 {
14537 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14538 dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14539 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14540 dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14541 }
14542 }
14543
14544 /* copy dual solution and activities into rows */
14545 for( r = 0; r < nlpirows; ++r )
14546 {
14547 assert( 0 <= rstat[r] && rstat[r] < 4 );
14548 lpirows[r]->dualsol = dualsol[r];
14549#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14550 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14551#else
14552 /* calculate row activity if invalid */
14553 if( lpirows[r]->validactivitylp != stat->lpcount )
14554 SCIProwRecalcLPActivity(lpirows[r], stat);
14555#endif
14556 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14557 lpirows[r]->validactivitylp = lpcount;
14558 if( stillprimalfeasible )
14559 {
14560 stillprimalfeasible =
14561 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14562 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14563 }
14564 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14565 {
14566 double compslack;
14567
14568 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14569 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14570 * variables, which would magnify even the tiniest violation in the dual multiplier
14571 */
14572 if( stilldualfeasible )
14573 {
14574 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14575 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14576 }
14577 if( stilldualfeasible )
14578 {
14579 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14580 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14581 }
14582
14583 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14584 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14585 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14586 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14587 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14588 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14589 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14590 dualfeasible != NULL ? stilldualfeasible : TRUE);
14591 }
14592 else
14593 {
14594 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14595 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14596 * strictly within left-hand and right-hand side, its dual multiplier must be zero
14597 */
14598 if( stilldualfeasible &&
14599 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14600 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14601 if( stilldualfeasible &&
14602 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14603 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14604
14605 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14606 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14607 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14608 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14609 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14610 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14611 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14612 dualfeasible != NULL ? stilldualfeasible : TRUE);
14613 }
14614
14615 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14616 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14617 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14618 */
14619 if( stilldualfeasible )
14620 {
14621 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14622 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14623 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14624 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14625 }
14626 }
14627
14628 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14629 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14630 * infinity
14631 */
14632 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14633 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14634 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14635 {
14636 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14637 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14638 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14639 }
14640
14641 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14642 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14643 */
14644 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14645 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14646 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14647 {
14648 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14649 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14650 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14651 }
14652
14653 if( primalfeasible != NULL )
14654 *primalfeasible = stillprimalfeasible;
14655 if( dualfeasible != NULL )
14656 *dualfeasible = stilldualfeasible;
14657
14658 /* free temporary memory */
14659 SCIPsetFreeBufferArray(set, &rstat);
14660 SCIPsetFreeBufferArray(set, &cstat);
14661 SCIPsetFreeBufferArray(set, &redcost);
14662#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14663 SCIPsetFreeBufferArray(set, &activity);
14664#endif
14665 SCIPsetFreeBufferArray(set, &dualsol);
14666 SCIPsetFreeBufferArray(set, &primsol);
14667
14668 return SCIP_OKAY;
14669}
14670
14671/** stores LP solution with infinite objective value in the columns and rows */
14673 SCIP_LP* lp, /**< current LP data */
14674 SCIP_SET* set, /**< global SCIP settings */
14675 SCIP_STAT* stat, /**< problem statistics */
14676 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14677 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14678 )
14679{
14680 SCIP_COL** lpicols;
14681 SCIP_ROW** lpirows;
14682 SCIP_Real* primsol;
14683 SCIP_Real* activity;
14684 SCIP_Real* ray;
14685 SCIP_Real rayobjval;
14686 SCIP_Real rayscale;
14687 SCIP_Longint lpcount;
14688 SCIP_COL* col;
14689 int nlpicols;
14690 int nlpirows;
14691 int c;
14692 int r;
14693
14694 assert(lp != NULL);
14695 assert(lp->flushed);
14696 assert(lp->solved);
14698 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
14699 assert(set != NULL);
14700 assert(stat != NULL);
14701 assert(lp->validsollp <= stat->lpcount);
14702
14703 if( primalfeasible != NULL )
14704 *primalfeasible = TRUE;
14705 if( rayfeasible != NULL )
14706 *rayfeasible = TRUE;
14707
14708 /* check if the values are already calculated */
14709 if( lp->validsollp == stat->lpcount )
14710 return SCIP_OKAY;
14711 lp->validsollp = stat->lpcount;
14712
14713 /* check if the LP solver is able to provide a primal unbounded ray */
14714 if( !SCIPlpiHasPrimalRay(lp->lpi) )
14715 {
14716 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14717 return SCIP_LPERROR;
14718 }
14719
14720 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14721
14722 /* get temporary memory */
14723 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
14724 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14726
14727 /* get primal unbounded ray */
14728 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14729
14730 lpicols = lp->lpicols;
14731 lpirows = lp->lpirows;
14732 nlpicols = lp->nlpicols;
14733 nlpirows = lp->nlpirows;
14734 lpcount = stat->lpcount;
14735
14736 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14737 rayobjval = 0.0;
14738 for( c = 0; c < nlpicols; ++c )
14739 {
14740 assert(lpicols[c] != NULL);
14741 assert(lpicols[c]->var != NULL);
14742
14743 col = lpicols[c];
14744
14745 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14746 if( rayfeasible != NULL )
14747 {
14748 *rayfeasible = *rayfeasible
14749 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14750 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub));
14751 }
14752
14753 if( ! SCIPsetIsZero(set, ray[c]) )
14754 rayobjval += ray[c] * col->obj;
14755
14756 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14757 * heuristically try to construct a primal solution.
14758 */
14759 primsol[c] = 0.0;
14760 if( SCIPsetIsFeasZero(set, ray[c]) )
14761 {
14762 /* if the ray component is 0, we try to satisfy as many rows as possible */
14763 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14764 primsol[c] = col->lb;
14765 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14766 primsol[c] = col->ub;
14767 }
14768
14769 /* make sure we respect the bounds */
14770 primsol[c] = MAX(primsol[c], col->lb);
14771 primsol[c] = MIN(primsol[c], col->ub);
14772
14773 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14774 }
14775
14776 /* check feasibility of heuristic primal solution */
14777 for( r = 0; r < nlpirows; ++r )
14778 {
14779 SCIP_Real act;
14780 SCIP_ROW* row;
14781
14782 row = lpirows[r];
14783 assert( row != NULL );
14784 act = row->constant;
14785
14786 for( c = 0; c < row->nlpcols; ++c )
14787 {
14788 col = row->cols[c];
14789
14790 assert( col != NULL );
14791 assert( col->lppos >= 0 );
14792 assert( row->linkpos[c] >= 0 );
14793 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14794
14795 act += row->vals[c] * primsol[col->lppos];
14796 }
14797
14798 if( row->nunlinked > 0 )
14799 {
14800 for( c = row->nlpcols; c < row->len; ++c )
14801 {
14802 col = row->cols[c];
14803 assert( col != NULL );
14804
14805 if( col->lppos >= 0 )
14806 act += row->vals[c] * primsol[col->lppos];
14807 }
14808 }
14809
14810 /* check feasibility */
14811 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14812 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14813 break;
14814 }
14815
14816 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14817 if( r < nlpirows )
14818 {
14819 /* get primal feasible point */
14820 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
14821
14822 /* check bounds of primal solution */
14823 if( primalfeasible != NULL )
14824 {
14825 assert( *primalfeasible );
14826 for( c = 0; c < nlpicols; ++c )
14827 {
14828 assert( lpicols[c] != NULL );
14829 assert( lpicols[c]->var != NULL );
14830
14831 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14832 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14833 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14834 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14835 {
14836 *primalfeasible = FALSE;
14837 break;
14838 }
14839 }
14840 }
14841 }
14842
14843 /* compute activity and check feasibility of primal solution and ray */
14844 for( r = 0; r < nlpirows; ++r )
14845 {
14846 SCIP_Real primact;
14847 SCIP_Real rayact = 0.0;
14848 SCIP_ROW* row;
14849
14850 row = lpirows[r];
14851 assert( row != NULL );
14852
14853 primact = row->constant;
14854
14855 for( c = 0; c < row->nlpcols; ++c )
14856 {
14857 col = row->cols[c];
14858
14859 assert( col != NULL );
14860 assert( col->lppos >= 0 );
14861 assert( row->linkpos[c] >= 0 );
14862 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14863
14864 primact += row->vals[c] * primsol[col->lppos];
14865 rayact += row->vals[c] * ray[col->lppos];
14866 }
14867
14868 if( row->nunlinked > 0 )
14869 {
14870 for( c = row->nlpcols; c < row->len; ++c )
14871 {
14872 col = row->cols[c];
14873 assert( col != NULL );
14874
14875 if( col->lppos >= 0 )
14876 {
14877 primact += row->vals[c] * primsol[col->lppos];
14878 rayact += row->vals[c] * ray[col->lppos];
14879 }
14880 }
14881 }
14882
14883 /* check feasibility of primal solution */
14884 if( primalfeasible != NULL && *primalfeasible )
14885 {
14886 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14887 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14888 *primalfeasible = FALSE;
14889 }
14890
14891 /* check feasibility of ray */
14892 if( rayfeasible != NULL && *rayfeasible )
14893 {
14894 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14895 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14896 *rayfeasible = FALSE;
14897 }
14898
14899 /* store activity of primal solution */
14900 activity[r] = primact;
14901 }
14902
14903 if( primalfeasible != NULL && !(*primalfeasible) )
14904 {
14905 /* if the finite point is already infeasible, we do not have to add the ray */
14906 rayscale = 0.0;
14907 }
14908 else if( rayfeasible != NULL && !(*rayfeasible) )
14909 {
14910 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14911 rayscale = 0.0;
14912 }
14913 else if( !SCIPsetIsNegative(set, rayobjval) )
14914 {
14915 /* due to numerical problems, the objective of the ray might be nonnegative
14916 *
14917 * @todo How to check for negative objective value here?
14918 */
14919 if( rayfeasible != NULL )
14920 *rayfeasible = FALSE;
14921
14922 rayscale = 0.0;
14923 }
14924 else
14925 {
14926 assert(rayobjval != 0.0);
14927
14928 /* scale the ray, such that the resulting point has infinite objective value */
14929 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14930 assert(SCIPsetIsFeasPositive(set, rayscale));
14931
14932 /* ensure that unbounded point does not violate the bounds of the variables */
14933 for( c = 0; c < nlpicols; ++c )
14934 {
14935 if( SCIPsetIsPositive(set, ray[c]) )
14936 {
14937 if( !SCIPsetIsInfinity(set, primsol[c]) )
14938 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14939 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14940 else
14941 {
14942 assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14943 rayscale = MIN(rayscale, 1.0 / ray[c]);
14944 }
14945 }
14946 else if( SCIPsetIsNegative(set, ray[c]) )
14947 {
14948 if( !SCIPsetIsInfinity(set, -primsol[c]) )
14949 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14950 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14951 else
14952 {
14953 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14954 rayscale = MIN(rayscale, -1.0 / ray[c]);
14955 }
14956 }
14957
14958 assert(SCIPsetIsFeasPositive(set, rayscale));
14959 }
14960 }
14961
14962 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14963
14964 /* calculate the unbounded point: x' = x + rayscale * ray */
14965 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14966 * typically large values in scaling. */
14967 for( c = 0; c < nlpicols; ++c )
14968 {
14969 if( SCIPsetIsZero(set, ray[c]) )
14970 lpicols[c]->primsol = primsol[c];
14971 else
14972 {
14973 SCIP_Real primsolval;
14974 primsolval = primsol[c] + rayscale * ray[c];
14975 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14976 }
14977 lpicols[c]->redcost = SCIP_INVALID;
14978 lpicols[c]->validredcostlp = -1;
14979 }
14980
14981 /* transfer solution */
14982 for( r = 0; r < nlpirows; ++r )
14983 {
14984 lpirows[r]->dualsol = SCIP_INVALID;
14985 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14986 lpirows[r]->validactivitylp = lpcount;
14987 }
14988
14989 /* free temporary memory */
14991 SCIPsetFreeBufferArray(set, &activity);
14992 SCIPsetFreeBufferArray(set, &primsol);
14993
14994 return SCIP_OKAY;
14995}
14996
14997/** returns primal ray proving the unboundedness of the current LP */
14999 SCIP_LP* lp, /**< current LP data */
15000 SCIP_SET* set, /**< global SCIP settings */
15001 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
15002 * so the size of this array should be at least number of active variables
15003 * (all entries have to be initialized to 0 before) */
15004 )
15005{
15006 SCIP_COL** lpicols;
15007 SCIP_Real* lpiray;
15008 SCIP_VAR* var;
15009 int nlpicols;
15010 int c;
15011
15012 assert(lp != NULL);
15013 assert(set != NULL);
15014 assert(ray != NULL);
15015 assert(lp->flushed);
15016 assert(lp->solved);
15018 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
15019
15020 /* check if the LP solver is able to provide a primal unbounded ray */
15021 if( !SCIPlpiHasPrimalRay(lp->lpi) )
15022 {
15023 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15024 return SCIP_LPERROR;
15025 }
15026
15027 /* get temporary memory */
15029
15030 SCIPsetDebugMsg(set, "getting primal ray values\n");
15031
15032 /* get primal unbounded ray */
15033 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15034
15035 lpicols = lp->lpicols;
15036 nlpicols = lp->nlpicols;
15037
15038 /* store the ray values of active problem variables */
15039 for( c = 0; c < nlpicols; c++ )
15040 {
15041 assert(lpicols[c] != NULL);
15042
15043 var = lpicols[c]->var;
15044 assert(var != NULL);
15045 assert(SCIPvarGetProbindex(var) != -1);
15046 ray[SCIPvarGetProbindex(var)] = lpiray[c];
15047 }
15048
15049 SCIPsetFreeBufferArray(set, &lpiray);
15050
15051 return SCIP_OKAY;
15052}
15053
15054/** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15055 * lp/checkfarkas = TRUE.
15056 *
15057 * @note the check will not be performed if @p valid is NULL.
15058 */
15060 SCIP_LP* lp, /**< current LP data */
15061 SCIP_SET* set, /**< global SCIP settings */
15062 SCIP_STAT* stat, /**< problem statistics */
15063 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
15064 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */
15065 )
15066{
15067 SCIP_COL** lpicols;
15068 SCIP_ROW** lpirows;
15069 SCIP_Real* dualfarkas;
15070 SCIP_Real* farkascoefs;
15071 SCIP_Real farkaslhs;
15072 SCIP_Real maxactivity;
15073 SCIP_Bool checkfarkas;
15074 int nlpicols;
15075 int nlpirows;
15076 int c;
15077 int r;
15078
15079 assert(lp != NULL);
15080 assert(lp->flushed);
15081 assert(lp->solved);
15082 assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
15083 assert(set != NULL);
15084 assert(stat != NULL);
15085 assert(lp->validfarkaslp <= stat->lpcount);
15086
15087 if( valid != NULL )
15088 *valid = TRUE;
15089
15090 /* check if the values are already calculated */
15091 if( lp->validfarkaslp == stat->lpcount )
15092 return SCIP_OKAY;
15093 lp->validfarkaslp = stat->lpcount;
15094
15095 farkascoefs = NULL;
15096 maxactivity = 0.0;
15097 farkaslhs = 0.0;
15098 checkfarkas = set->lp_checkfarkas && valid != NULL;
15099
15100 /* get temporary memory */
15101 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15102
15103 if( checkfarkas )
15104 {
15105 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15106 BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15107 }
15108
15109 /* get dual Farkas infeasibility proof */
15110 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15111
15112 lpicols = lp->lpicols;
15113 lpirows = lp->lpirows;
15114 nlpicols = lp->nlpicols;
15115 nlpirows = lp->nlpirows;
15116
15117 /* store infeasibility proof in rows */
15118 SCIPsetDebugMsg(set, "LP is infeasible:\n");
15119 for( r = 0; r < nlpirows; ++r )
15120 {
15121 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15122 lpirows[r]->dualfarkas = dualfarkas[r];
15123 lpirows[r]->dualsol = SCIP_INVALID;
15124 lpirows[r]->activity = 0.0;
15125 lpirows[r]->validactivitylp = -1L;
15126 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15127
15128 if( checkfarkas && dualfarkas[r] != 0.0 ) /*lint !e777*/
15129 {
15130 assert(valid != NULL);
15131 assert(farkascoefs != NULL);
15132
15133 /* the infeasibility proof would be invalid if
15134 * (i) dualfarkas[r] > 0 and lhs = -inf
15135 * (ii) dualfarkas[r] < 0 and rhs = inf
15136 * however, due to numerics we accept slightly negative / positive values
15137 */
15138 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15139 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15140 {
15141 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15142 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15143
15144 *valid = FALSE;
15145 goto TERMINATE;
15146 }
15147
15148 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15149 * within tolerances (see above) but slighty positive / negative
15150 */
15151 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15152 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15153 continue;
15154
15155 /* iterate over all columns and scale with dual solution */
15156 for( c = 0; c < lpirows[r]->len; c++ )
15157 {
15158 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15159
15160 if( pos == -1 )
15161 continue;
15162
15163 assert(pos >= 0 && pos < nlpicols);
15164
15165 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15166 }
15167
15168 /* the row contributes with its left-hand side to the proof */
15169 if( dualfarkas[r] > 0.0 )
15170 {
15171 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15172
15173 farkaslhs += dualfarkas[r] * lpirows[r]->lhs;
15174 }
15175 /* the row contributes with its right-hand side to the proof */
15176 else if( dualfarkas[r] < 0.0 )
15177 {
15178 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15179
15180 farkaslhs += dualfarkas[r] * lpirows[r]->rhs;
15181 }
15182
15183 maxactivity += dualfarkas[r] * lpirows[r]->constant;
15184 }
15185 }
15186
15187 /* set columns as invalid */
15188 for( c = 0; c < nlpicols; ++c )
15189 {
15190 lpicols[c]->primsol = SCIP_INVALID;
15191 lpicols[c]->redcost = SCIP_INVALID;
15192 lpicols[c]->validredcostlp = -1L;
15193 lpicols[c]->validfarkaslp = -1L;
15194
15195 if( checkfarkas )
15196 {
15197 assert(valid != NULL);
15198 assert(farkascoefs != NULL);
15199 assert(SCIPcolGetLPPos(lpicols[c]) == c);
15200
15201 /* skip coefficients that are too close to zero */
15202 if( SCIPsetIsDualfeasZero(set, farkascoefs[c]) )
15203 continue;
15204
15205 /* calculate the maximal activity */
15206 if( farkascoefs[c] > 0.0 )
15207 {
15208 maxactivity += farkascoefs[c] * lpicols[c]->ub;
15209
15210 if( SCIPsetIsInfinity(set, lpicols[c]->ub) )
15211 {
15212 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15213 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15214
15215 *valid = FALSE;
15216 goto TERMINATE;
15217 }
15218 }
15219 else
15220 {
15221 maxactivity += farkascoefs[c] * lpicols[c]->lb;
15222
15223 if( SCIPsetIsInfinity(set, -lpicols[c]->lb) )
15224 {
15225 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15226 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15227
15228 *valid = FALSE;
15229 goto TERMINATE;
15230 }
15231 }
15232 }
15233 }
15234
15235 /* check whether the farkasproof is valid for relative epsilon tolerance to allow feasibility tightening */
15236 if( checkfarkas
15237 && ( SCIPsetIsInfinity(set, maxactivity) || SCIPsetIsInfinity(set, -farkaslhs) || SCIPsetIsRelGE(set, maxactivity, farkaslhs) ) )
15238 {
15239 assert(valid != NULL);
15240
15241 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15242
15243 if( forcedlpsolve && SCIPsetIsLT(set, maxactivity, farkaslhs) )
15244 SCIPmessagePrintWarning(set->scip->messagehdlr, "Unreliable farkas proof forced valid, result might not be optimal.\n");
15245 else
15246 *valid = FALSE;
15247 }
15248
15249 TERMINATE:
15250 /* free temporary memory */
15251 if( checkfarkas )
15252 SCIPsetFreeBufferArray(set, &farkascoefs);
15253
15254 SCIPsetFreeBufferArray(set, &dualfarkas);
15255
15256 return SCIP_OKAY;
15257}
15258
15259/** get number of iterations used in last LP solve */
15261 SCIP_LP* lp, /**< current LP data */
15262 int* iterations /**< pointer to store the iteration count */
15263 )
15264{
15265 assert(lp != NULL);
15266
15267 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15268
15269 return SCIP_OKAY;
15270}
15271
15272/** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15273 * resets age of non-zero columns and sharp rows
15274 */
15276 SCIP_LP* lp, /**< current LP data */
15277 SCIP_STAT* stat /**< problem statistics */
15278 )
15279{
15280 SCIP_COL** lpicols;
15281 SCIP_ROW** lpirows;
15282 int nlpicols;
15283 int nlpirows;
15284 int c;
15285 int r;
15286
15287 assert(lp != NULL);
15288 assert(lp->flushed);
15289 assert(lp->solved);
15290 assert(lp->nlpicols == lp->ncols);
15291 assert(lp->nlpirows == lp->nrows);
15292 assert(stat != NULL);
15293 assert(lp->validsollp == stat->lpcount);
15294
15295 SCIPdebugMessage("updating LP ages\n");
15296
15297 lpicols = lp->lpicols;
15298 lpirows = lp->lpirows;
15299 nlpicols = lp->nlpicols;
15300 nlpirows = lp->nlpirows;
15301
15302 for( c = 0; c < nlpicols; ++c )
15303 {
15304 assert(lpicols[c] == lp->cols[c]);
15305 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
15306 lpicols[c]->age++;
15307 else
15308 lpicols[c]->age = 0;
15309 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15310 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15311 }
15312
15313 for( r = 0; r < nlpirows; ++r )
15314 {
15315 lpirows[r]->nlpsaftercreation++;
15316 assert(lpirows[r] == lp->rows[r]);
15317
15318 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15319 {
15320 lpirows[r]->age++;
15321 }
15322 else
15323 {
15324 lpirows[r]->activeinlpcounter++;
15325 lpirows[r]->age = 0;
15326 }
15327 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15328 }
15329
15330 return SCIP_OKAY;
15331}
15332
15333/* deletes the marked columns from the LP and the LP interface */
15334static
15336 SCIP_LP* lp, /**< current LP data */
15337 SCIP_SET* set, /**< global SCIP settings */
15338 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
15339 )
15340{
15341 SCIP_COL* col;
15342 int ncols;
15343 int c;
15344
15345 assert(lp != NULL);
15346 assert(lp->flushed);
15347 assert(lp->ncols == lp->nlpicols);
15348 assert(!lp->diving);
15349 assert(coldstat != NULL);
15350 assert(lp->nlazycols <= lp->ncols);
15351
15352 ncols = lp->ncols;
15353
15354 /* delete columns in LP solver */
15355 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15356
15357 /* update LP data respectively */
15358 for( c = 0; c < ncols; ++c )
15359 {
15360 col = lp->cols[c];
15361 assert(col != NULL);
15362 assert(col == lp->lpicols[c]);
15363 assert(coldstat[c] <= c);
15364 col->lppos = coldstat[c];
15365 if( coldstat[c] == -1 )
15366 {
15367 assert(col->removable);
15368
15369 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15370 * function vector norms
15371 */
15372 markColDeleted(col);
15373 colUpdateDelLP(col, set);
15374 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15375 col->lpdepth = -1;
15376
15377 lp->cols[c] = NULL;
15378 lp->lpicols[c] = NULL;
15379 lp->ncols--;
15380 lp->nremovablecols--;
15381 lp->nlpicols--;
15382 }
15383 else if( coldstat[c] < c )
15384 {
15385 assert(lp->cols[coldstat[c]] == NULL);
15386 assert(lp->lpicols[coldstat[c]] == NULL);
15387 lp->cols[coldstat[c]] = col;
15388 lp->lpicols[coldstat[c]] = col;
15389 lp->cols[coldstat[c]]->lppos = coldstat[c];
15390 lp->cols[coldstat[c]]->lpipos = coldstat[c];
15391 lp->cols[c] = NULL;
15392 lp->lpicols[c] = NULL;
15393 }
15394 }
15395
15396 /* remove columns which are deleted from the lazy column array */
15397 c = 0;
15398 while( c < lp->nlazycols )
15399 {
15400 if( lp->lazycols[c]->lpipos < 0 )
15401 {
15402 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15403 lp->nlazycols--;
15404 }
15405 else
15406 c++;
15407 }
15408
15409 /* mark LP to be unsolved */
15410 if( lp->ncols < ncols )
15411 {
15412 assert(lp->ncols == lp->nlpicols);
15413 assert(lp->nchgcols == 0);
15414 assert(lp->flushed);
15415
15416 lp->lpifirstchgcol = lp->nlpicols;
15417
15418 /* mark the current solution invalid */
15419 lp->solved = FALSE;
15420 lp->primalfeasible = FALSE;
15421 lp->primalchecked = FALSE;
15422 lp->lpobjval = SCIP_INVALID;
15424 }
15425
15427 checkLinks(lp);
15428
15429 return SCIP_OKAY;
15430}
15431
15432/* deletes the marked rows from the LP and the LP interface */
15433static
15435 SCIP_LP* lp, /**< current LP data */
15436 BMS_BLKMEM* blkmem, /**< block memory buffers */
15437 SCIP_SET* set, /**< global SCIP settings */
15438 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15439 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15440 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
15441 )
15442{
15443 SCIP_ROW* row;
15444 int nrows;
15445 int r;
15446
15447 assert(lp != NULL);
15448 assert(lp->flushed);
15449 assert(lp->nrows == lp->nlpirows);
15450 assert(!lp->diving);
15451 assert(rowdstat != NULL);
15452
15453 nrows = lp->nrows;
15454
15455 /* delete rows in LP solver */
15456 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15457
15458 /* update LP data respectively */
15459 for( r = 0; r < nrows; ++r )
15460 {
15461 row = lp->rows[r];
15462 assert(row == lp->lpirows[r]);
15463 assert(rowdstat[r] <= r);
15464 assert(row != NULL);
15465 row->lppos = rowdstat[r];
15466 if( rowdstat[r] == -1 )
15467 {
15468 if( row->removable )
15469 lp->nremovablerows--;
15470
15471 /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15472 markRowDeleted(row);
15473 rowUpdateDelLP(row);
15474 row->lpdepth = -1;
15475
15476 /* check, if row deletion events are tracked
15477 * if so, issue ROWDELETEDLP event
15478 */
15479 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15480 {
15481 SCIP_EVENT* event;
15482
15483 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15484 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15485 }
15486
15487 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15488 SCIProwUnlock(lp->rows[r]);
15489 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15490 assert(lp->lpirows[r] == NULL);
15491 assert(lp->rows[r] == NULL);
15492 lp->nrows--;
15493 lp->nlpirows--;
15494 }
15495 else if( rowdstat[r] < r )
15496 {
15497 assert(lp->rows[rowdstat[r]] == NULL);
15498 assert(lp->lpirows[rowdstat[r]] == NULL);
15499 lp->rows[rowdstat[r]] = row;
15500 lp->lpirows[rowdstat[r]] = row;
15501 lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15502 lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15503 lp->rows[r] = NULL;
15504 lp->lpirows[r] = NULL;
15505 }
15506 }
15507
15508 /* mark LP to be unsolved */
15509 if( lp->nrows < nrows )
15510 {
15511 assert(lp->nrows == lp->nlpirows);
15512 assert(lp->nchgrows == 0);
15513 assert(lp->flushed);
15514
15515 lp->lpifirstchgrow = lp->nlpirows;
15516
15517 /* mark the current solution invalid */
15518 lp->solved = FALSE;
15519 lp->dualfeasible = FALSE;
15520 lp->dualchecked = FALSE;
15521 lp->lpobjval = SCIP_INVALID;
15523 }
15524
15525 checkLinks(lp);
15526
15527 return SCIP_OKAY;
15528}
15529
15530/** removes all non-basic columns, that are too old, beginning with the given firstcol */
15531static
15533 SCIP_LP* lp, /**< current LP data */
15534 SCIP_SET* set, /**< global SCIP settings */
15535 SCIP_STAT* stat, /**< problem statistics */
15536 int firstcol /**< first column to check for clean up */
15537 )
15538{
15539 SCIP_COL** cols;
15540#ifndef NDEBUG
15541 SCIP_COL** lpicols;
15542#endif
15543 int* coldstat;
15544 int ncols;
15545 int ndelcols;
15546 int c;
15547
15548 assert(lp != NULL);
15549 assert(lp->flushed);
15550 assert(lp->ncols == lp->nlpicols);
15551 assert(lp->nremovablecols <= lp->ncols);
15552 assert(!lp->diving);
15553 assert(set != NULL);
15554 assert(stat != NULL);
15555
15556 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15557 return SCIP_OKAY;
15558
15559 ncols = lp->ncols;
15560 cols = lp->cols;
15561#ifndef NDEBUG
15562 lpicols = lp->lpicols;
15563#endif
15564
15565 /* get temporary memory */
15566 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15567
15568 /* mark obsolete columns to be deleted */
15569 ndelcols = 0;
15570 BMSclearMemoryArray(coldstat, ncols);
15571 for( c = firstcol; c < ncols; ++c )
15572 {
15573 assert(cols[c] == lpicols[c]);
15574 assert(cols[c]->lppos == c);
15575 assert(cols[c]->lpipos == c);
15576 if( cols[c]->removable
15577 && 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 */
15578 && cols[c]->age > set->lp_colagelimit
15580 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15581 {
15582 assert(cols[c]->primsol == 0.0);
15583 coldstat[c] = 1;
15584 ndelcols++;
15585 cols[c]->obsoletenode = stat->nnodes;
15586 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15587 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15588 }
15589 }
15590
15591 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15592
15593 /* delete the marked columns in the LP solver interface, update the LP respectively */
15594 if( ndelcols > 0 )
15595 {
15596 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15597 }
15598 assert(lp->ncols == ncols - ndelcols);
15599
15600 /* release temporary memory */
15601 SCIPsetFreeBufferArray(set, &coldstat);
15602
15603 return SCIP_OKAY;
15604}
15605
15606/** removes all basic rows, that are too old, beginning with the given firstrow */
15607static
15609 SCIP_LP* lp, /**< current LP data */
15610 BMS_BLKMEM* blkmem, /**< block memory buffers */
15611 SCIP_SET* set, /**< global SCIP settings */
15612 SCIP_STAT* stat, /**< problem statistics */
15613 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15614 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15615 int firstrow /**< first row to check for clean up */
15616 )
15617{
15618 SCIP_ROW** rows;
15619#ifndef NDEBUG
15620 SCIP_ROW** lpirows;
15621#endif
15622 int* rowdstat;
15623 int nrows;
15624 int ndelrows;
15625 int r;
15626
15627 assert(lp != NULL);
15628 assert(lp->flushed);
15629 assert(lp->nrows == lp->nlpirows);
15630 assert(lp->nremovablerows <= lp->nrows);
15631 assert(!lp->diving);
15632 assert(set != NULL);
15633 assert(stat != NULL);
15634
15635 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15636 return SCIP_OKAY;
15637
15638 nrows = lp->nrows;
15639 rows = lp->rows;
15640#ifndef NDEBUG
15641 lpirows = lp->lpirows;
15642#endif
15643
15644 /* get temporary memory */
15645 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15646
15647 /* mark obsolete rows to be deleted */
15648 ndelrows = 0;
15649 BMSclearMemoryArray(rowdstat, nrows);
15650 for( r = firstrow; r < nrows; ++r )
15651 {
15652 assert(rows[r] == lpirows[r]);
15653 assert(rows[r]->lppos == r);
15654 assert(rows[r]->lpipos == r);
15655 if( rows[r]->removable
15656 && 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 */
15657 && rows[r]->age > set->lp_rowagelimit
15659 {
15660 rowdstat[r] = 1;
15661 ndelrows++;
15662 rows[r]->obsoletenode = stat->nnodes;
15663 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15664 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15665 }
15666 }
15667
15668 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15669
15670 /* delete the marked rows in the LP solver interface, update the LP respectively */
15671 if( ndelrows > 0 )
15672 {
15673 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15674 }
15675 assert(lp->nrows == nrows - ndelrows);
15676
15677 /* release temporary memory */
15678 SCIPsetFreeBufferArray(set, &rowdstat);
15679
15680 return SCIP_OKAY;
15681}
15682
15683/** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15685 SCIP_LP* lp, /**< current LP data */
15686 BMS_BLKMEM* blkmem, /**< block memory buffers */
15687 SCIP_SET* set, /**< global SCIP settings */
15688 SCIP_STAT* stat, /**< problem statistics */
15689 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15690 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15691 )
15692{
15693 assert(lp != NULL);
15694 assert(lp->solved);
15695 assert(!lp->diving);
15697 assert(set != NULL);
15698
15699 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15700 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15701
15702 if( lp->firstnewcol < lp->ncols )
15703 {
15704 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15705 }
15706 if( lp->firstnewrow < lp->nrows )
15707 {
15708 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15709 }
15710
15711 return SCIP_OKAY;
15712}
15713
15714/** removes all non-basic columns and basic rows in whole LP, that are too old */
15716 SCIP_LP* lp, /**< current LP data */
15717 BMS_BLKMEM* blkmem, /**< block memory buffers */
15718 SCIP_SET* set, /**< global SCIP settings */
15719 SCIP_STAT* stat, /**< problem statistics */
15720 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15721 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15722 )
15723{
15724 assert(lp != NULL);
15725 assert(lp->solved);
15726 assert(!lp->diving);
15728 assert(set != NULL);
15729
15730 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15731
15732 if( 0 < lp->ncols )
15733 {
15734 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15735 }
15736 if( 0 < lp->nrows )
15737 {
15738 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15739 }
15740
15741 return SCIP_OKAY;
15742}
15743
15744/** removes all non-basic columns at 0.0 beginning with the given firstcol */
15745static
15747 SCIP_LP* lp, /**< current LP data */
15748 SCIP_SET* set, /**< global SCIP settings */
15749 SCIP_STAT* stat, /**< problem statistics */
15750 int firstcol /**< first column to check for clean up */
15751 )
15752{
15753 SCIP_COL** cols;
15754 SCIP_COL** lpicols;
15755 int* coldstat;
15756 int ncols;
15757 int ndelcols;
15758 int c;
15759
15760 assert(lp != NULL);
15761 assert(lp->flushed);
15762 assert(lp->ncols == lp->nlpicols);
15763 assert(!lp->diving);
15764 assert(stat != NULL);
15765 assert(lp->validsollp == stat->lpcount);
15766 assert(0 <= firstcol && firstcol < lp->ncols);
15767
15768 if( lp->nremovablecols == 0 || !lp->solisbasic )
15769 return SCIP_OKAY;
15770
15771 ncols = lp->ncols;
15772 cols = lp->cols;
15773 lpicols = lp->lpicols;
15774
15775 /* get temporary memory */
15776 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15777
15778 /* mark unused columns to be deleted */
15779 ndelcols = 0;
15780 BMSclearMemoryArray(coldstat, ncols);
15781 for( c = firstcol; c < ncols; ++c )
15782 {
15783 assert(cols[c] == lpicols[c]);
15784 assert(cols[c]->lppos == c);
15785 assert(cols[c]->lpipos == c);
15786 if( lpicols[c]->removable
15787 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15788 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15789 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15790 {
15791 coldstat[c] = 1;
15792 ndelcols++;
15793 }
15794 }
15795
15796 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15797
15798 /* delete the marked columns in the LP solver interface, update the LP respectively */
15799 if( ndelcols > 0 )
15800 {
15801 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15802 }
15803 assert(lp->ncols == ncols - ndelcols);
15804
15805 /* release temporary memory */
15806 SCIPsetFreeBufferArray(set, &coldstat);
15807
15808 return SCIP_OKAY;
15809}
15810
15811/** removes all basic rows beginning with the given firstrow */
15812static
15814 SCIP_LP* lp, /**< current LP data */
15815 BMS_BLKMEM* blkmem, /**< block memory buffers */
15816 SCIP_SET* set, /**< global SCIP settings */
15817 SCIP_STAT* stat, /**< problem statistics */
15818 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15819 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15820 int firstrow /**< first row to check for clean up */
15821 )
15822{
15823#ifndef NDEBUG
15824 SCIP_ROW** rows;
15825#endif
15826 SCIP_ROW** lpirows;
15827 int* rowdstat;
15828 int nrows;
15829 int ndelrows;
15830 int r;
15831
15832 assert(lp != NULL);
15833 assert(lp->flushed);
15834 assert(lp->ncols == lp->nlpicols);
15835 assert(lp->nrows == lp->nlpirows);
15836 assert(!lp->diving);
15837 assert(stat != NULL);
15838 assert(lp->validsollp == stat->lpcount);
15839 assert(0 <= firstrow && firstrow < lp->nrows);
15840
15841 if( lp->nremovablerows == 0 || !lp->solisbasic )
15842 return SCIP_OKAY;
15843
15844#ifndef NDEBUG
15845 rows = lp->rows;
15846#endif
15847 nrows = lp->nrows;
15848 lpirows = lp->lpirows;
15849
15850 /* get temporary memory */
15851 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15852
15853 /* mark unused rows to be deleted */
15854 ndelrows = 0;
15855 BMSclearMemoryArray(rowdstat, nrows);
15856 for( r = firstrow; r < nrows; ++r )
15857 {
15858 assert(rows[r] == lpirows[r]);
15859 assert(rows[r]->lppos == r);
15860 assert(rows[r]->lpipos == r);
15861 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15862 {
15863 rowdstat[r] = 1;
15864 ndelrows++;
15865 }
15866 }
15867
15868 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15869
15870 /* delete the marked rows in the LP solver interface, update the LP respectively */
15871 if( ndelrows > 0 )
15872 {
15873 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15874 }
15875 assert(lp->nrows == nrows - ndelrows);
15876
15877 /* release temporary memory */
15878 SCIPsetFreeBufferArray(set, &rowdstat);
15879
15880 return SCIP_OKAY;
15881}
15882
15883/** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15885 SCIP_LP* lp, /**< current LP data */
15886 BMS_BLKMEM* blkmem, /**< block memory buffers */
15887 SCIP_SET* set, /**< global SCIP settings */
15888 SCIP_STAT* stat, /**< problem statistics */
15889 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15890 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15891 SCIP_Bool root /**< are we at the root node? */
15892 )
15893{
15894 SCIP_Bool cleanupcols;
15895 SCIP_Bool cleanuprows;
15896
15897 assert(lp != NULL);
15898 assert(lp->solved);
15899 assert(!lp->diving);
15901 assert(set != NULL);
15902
15903 /* check, if we want to clean up the columns and rows */
15904 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15905 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15906
15907 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15908 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15909
15910 if( cleanupcols && lp->firstnewcol < lp->ncols )
15911 {
15912 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15913 }
15914 if( cleanuprows && lp->firstnewrow < lp->nrows )
15915 {
15916 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15917 }
15918
15919 return SCIP_OKAY;
15920}
15921
15922/** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15924 SCIP_LP* lp, /**< current LP data */
15925 BMS_BLKMEM* blkmem, /**< block memory buffers */
15926 SCIP_SET* set, /**< global SCIP settings */
15927 SCIP_STAT* stat, /**< problem statistics */
15928 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15929 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15930 SCIP_Bool root /**< are we at the root node? */
15931 )
15932{
15933 SCIP_Bool cleanupcols;
15934 SCIP_Bool cleanuprows;
15935
15936 assert(lp != NULL);
15937 assert(lp->solved);
15938 assert(!lp->diving);
15940 assert(set != NULL);
15941
15942 /* check, if we want to clean up the columns and rows */
15943 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15944 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15945
15946 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15947 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15948
15949 if( cleanupcols && 0 < lp->ncols )
15950 {
15951 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15952 }
15953 if( cleanuprows && 0 < lp->nrows )
15954 {
15955 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15956 }
15957
15958 return SCIP_OKAY;
15959}
15960
15961/** removes all redundant rows that were added at the current node */
15963 SCIP_LP* lp, /**< current LP data */
15964 BMS_BLKMEM* blkmem, /**< block memory buffers */
15965 SCIP_SET* set, /**< global SCIP settings */
15966 SCIP_STAT* stat, /**< problem statistics */
15967 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15968 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15969 )
15970{
15971#ifndef NDEBUG
15972 SCIP_ROW** rows;
15973#endif
15974 SCIP_ROW** lpirows;
15975 int* rowdstat;
15976 int nrows;
15977 int ndelrows;
15978 int r;
15979
15980 assert(lp != NULL);
15981 assert(lp->flushed);
15982 assert(lp->ncols == lp->nlpicols);
15983 assert(lp->nrows == lp->nlpirows);
15984 assert(!lp->diving);
15985 assert(stat != NULL);
15986 assert(lp->validsollp == stat->lpcount);
15987 assert(lp->firstnewrow <= lp->nrows);
15988
15989 if( lp->firstnewrow == lp->nrows )
15990 return SCIP_OKAY;
15991
15992#ifndef NDEBUG
15993 rows = lp->rows;
15994#endif
15995 nrows = lp->nrows;
15996 lpirows = lp->lpirows;
15997
15998 /* get temporary memory */
15999 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
16000
16001 /* mark redundant rows to be deleted (only delete basic rows!) */
16002 ndelrows = 0;
16003 BMSclearMemoryArray(rowdstat, nrows);
16004 for( r = lp->firstnewrow; r < nrows; ++r )
16005 {
16006 assert(rows[r] == lpirows[r]);
16007 assert(rows[r]->lppos == r);
16008 assert(rows[r]->lpipos == r);
16009 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
16010 && SCIProwIsRedundant(lpirows[r], set, stat) )
16011 {
16012 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
16013 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
16014 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
16015 rowdstat[r] = 1;
16016 ndelrows++;
16017 }
16018 }
16019
16020 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
16021
16022 /* delete the marked rows in the LP solver interface, update the LP respectively */
16023 if( ndelrows > 0 )
16024 {
16025 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
16026 }
16027 assert(lp->nrows == nrows - ndelrows);
16028
16029 /* release temporary memory */
16030 SCIPsetFreeBufferArray(set, &rowdstat);
16031
16032 return SCIP_OKAY;
16033}
16034
16035/** initiates LP diving */
16037 SCIP_LP* lp, /**< current LP data */
16038 BMS_BLKMEM* blkmem, /**< block memory */
16039 SCIP_SET* set, /**< global SCIP settings */
16040 SCIP_STAT* stat /**< problem statistics */
16041 )
16042{
16043 int c;
16044 int r;
16045
16046 assert(lp != NULL);
16047 assert(lp->flushed || !lp->solved);
16048 assert(!lp->diving);
16049 assert(!lp->probing);
16050 assert(lp->divelpistate == NULL);
16051 assert(lp->divelpwasprimfeas);
16052 assert(lp->divelpwasdualfeas);
16053 assert(lp->validsollp <= stat->lpcount);
16054 assert(blkmem != NULL);
16055 assert(set != NULL);
16056 assert(lp->ndivechgsides == 0);
16057
16058 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16059 lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16060
16061#ifndef NDEBUG
16062 for( c = 0; c < lp->ncols; ++c )
16063 {
16064 assert(lp->cols[c] != NULL);
16065 assert(lp->cols[c]->var != NULL);
16066 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16067 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16068 assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16069 assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16070 assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16071 }
16072#endif
16073
16074 /* save current LPI state (basis information) */
16075 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16080
16081 /* save current LP values dependent on the solution */
16082 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16083 assert(lp->storedsolvals != NULL);
16084 if( !set->lp_resolverestore && lp->solved )
16085 {
16086 SCIP_Bool store = TRUE;
16087
16088 switch ( lp->lpsolstat )
16089 {
16091 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16092 assert(lp->validsollp == stat->lpcount);
16093 break;
16096 assert(lp->validsollp == stat->lpcount);
16097 break;
16101 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16102 assert(lp->validsollp == stat->lpcount);
16103 break;
16105 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, FALSE, NULL) );
16106 break;
16109 default:
16110 store = FALSE;
16111 }
16112
16113 if ( store )
16114 {
16115 for( c = 0; c < lp->ncols; ++c )
16116 {
16117 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16118 }
16119 for( r = 0; r < lp->nrows; ++r )
16120 {
16122 }
16123 }
16124 }
16125
16126 /* store LPI iteration limit */
16128
16129 /* remember the number of domain changes */
16130 lp->divenolddomchgs = stat->domchgcount;
16131
16132 /* store current number of rows */
16133 lp->ndivingrows = lp->nrows;
16134
16135 /* switch to diving mode */
16136 lp->diving = TRUE;
16137
16138 return SCIP_OKAY;
16139}
16140
16141/** quits LP diving and resets bounds and objective values of columns to the current node's values */
16143 SCIP_LP* lp, /**< current LP data */
16144 BMS_BLKMEM* blkmem, /**< block memory */
16145 SCIP_SET* set, /**< global SCIP settings */
16146 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16147 SCIP_STAT* stat, /**< problem statistics */
16148 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16149 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16150 SCIP_PROB* prob, /**< problem data */
16151 SCIP_VAR** vars, /**< array with all active variables */
16152 int nvars /**< number of active variables */
16153 )
16154{
16155 SCIP_VAR* var;
16156 int v;
16157
16158 assert(lp != NULL);
16159 assert(lp->diving);
16160 assert(blkmem != NULL);
16161 assert(nvars == 0 || vars != NULL);
16162
16163 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16164
16165 /* reset all columns' objective values and bounds to its original values */
16166 for( v = 0; v < nvars; ++v )
16167 {
16168 var = vars[v];
16169 assert(var != NULL);
16171 {
16175 }
16176 }
16177
16178 /* remove rows which were added in diving mode */
16179 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16180
16181 /* undo changes to left hand sides and right hand sides */
16182 while( lp->ndivechgsides > 0 )
16183 {
16184 SCIP_Real oldside;
16185 SCIP_SIDETYPE sidetype;
16186 SCIP_ROW* row;
16187
16188 lp->ndivechgsides--;
16189 oldside = lp->divechgsides[lp->ndivechgsides];
16190 sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16191 row = lp->divechgrows[lp->ndivechgsides];
16192
16193 if( sidetype == SCIP_SIDETYPE_LEFT )
16194 {
16195 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16196 }
16197 else
16198 {
16199 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16200 }
16201 }
16202
16203 /* restore LPI iteration limit */
16205
16206 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16207 * happens
16208 */
16209 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16211 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16212 lp->divelpwasprimfeas = TRUE;
16213 lp->divelpwasdualfeas = TRUE;
16216 assert(lp->divelpistate == NULL);
16217
16218 /* switch to standard (non-diving) mode */
16219 lp->diving = FALSE;
16220 lp->divingobjchg = FALSE;
16221
16222 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16223 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16224 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16225 * the parameter resolverestore to TRUE
16226 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16227 */
16228 assert(lp->storedsolvals != NULL);
16229 if( lp->storedsolvals->lpissolved
16230 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16231 {
16232 SCIP_Bool lperror;
16233
16234 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, FALSE, &lperror) );
16235 if( lperror )
16236 {
16237 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16238 lp->resolvelperror = TRUE;
16239 }
16244 {
16245 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16246 "LP was not resolved to a sufficient status after diving\n");
16247 lp->resolvelperror = TRUE;
16248 }
16249 }
16250 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16251 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16252 * re-solve as above can lead to a different LP status
16253 */
16254 else
16255 {
16256 int c;
16257 int r;
16258
16259 /* if there are lazy bounds, remove them from the LP */
16260 if( lp->nlazycols > 0 )
16261 {
16262 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16263 * first resolve LP?
16264 */
16266 assert(lp->diving == lp->divinglazyapplied);
16267
16268 /* flush changes to the LP solver */
16269 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16270 }
16271
16272 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16273 SCIPstatIncrement(stat, set, lpcount);
16274
16275 /* restore LP solution values in lp data, columns and rows */
16276 if( lp->storedsolvals->lpissolved &&
16283 )
16284 {
16285 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16286
16287 for( c = 0; c < lp->ncols; ++c )
16288 {
16289 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16290 }
16291 for( r = 0; r < lp->nrows; ++r )
16292 {
16293 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16294 }
16295 }
16296 else
16297 {
16298 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16299 }
16300 }
16301
16302#ifndef NDEBUG
16303 {
16304 int c;
16305 for( c = 0; c < lp->ncols; ++c )
16306 {
16307 assert(lp->cols[c] != NULL);
16308 assert(lp->cols[c]->var != NULL);
16309 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16310 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16311 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16312 assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16313 assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16314 }
16315 }
16316#endif
16317
16318 return SCIP_OKAY;
16319}
16320
16321#define DIVESTACKGROWFACT 1.5
16322
16323/** records a current row side such that any change will be undone after diving */
16325 SCIP_LP* lp, /**< LP data object */
16326 SCIP_ROW* row, /**< row affected by the change */
16327 SCIP_SIDETYPE sidetype /**< side type */
16328 )
16329{
16330 assert(lp != NULL);
16331 assert(row != NULL);
16332
16333 if( lp->ndivechgsides == lp->divechgsidessize )
16334 {
16336 }
16337 assert(lp->ndivechgsides < lp->divechgsidessize);
16338
16339 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16340 lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16341 lp->divechgrows[lp->ndivechgsides] = row;
16342 lp->ndivechgsides++;
16343
16344 return SCIP_OKAY;
16345}
16346
16347/** informs the LP that probing mode was initiated */
16349 SCIP_LP* lp /**< current LP data */
16350 )
16351{
16352 assert(lp != NULL);
16353 assert(!lp->probing);
16354 assert(!lp->strongbranching);
16355 assert(!lp->strongbranchprobing);
16356
16357 lp->probing = TRUE;
16358
16359 return SCIP_OKAY;
16360}
16361
16362/** informs the LP that probing mode was finished */
16364 SCIP_LP* lp /**< current LP data */
16365 )
16366{
16367 assert(lp != NULL);
16368 assert(lp->probing);
16369 assert(!lp->strongbranching);
16370 assert(!lp->strongbranchprobing);
16371
16372 lp->probing = FALSE;
16373
16374 return SCIP_OKAY;
16375}
16376
16377/** informs the LP that the probing mode is now used for strongbranching */
16379 SCIP_LP* lp /**< current LP data */
16380 )
16381{
16382 assert(lp != NULL);
16383 assert(lp->probing);
16384 assert(!lp->strongbranching);
16385 assert(!lp->strongbranchprobing);
16386
16388}
16389
16390/** informs the LP that the probing mode is not used for strongbranching anymore */
16392 SCIP_LP* lp /**< current LP data */
16393 )
16394{
16395 assert(lp != NULL);
16396 assert(lp->probing);
16397 assert(!lp->strongbranching);
16398 assert(lp->strongbranchprobing);
16399
16401}
16402
16403/** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16404 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16405 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16406 * we have only left hand sides):
16407 * min{cx | b <= Ax, lb <= x <= ub}
16408 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
16409 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
16410 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
16411 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
16412 */
16413static
16415 SCIP_LP* lp, /**< current LP data */
16416 SCIP_SET* set, /**< global SCIP settings */
16417 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16418 SCIP_Real* bound /**< result of interval arithmetic minimization */
16419 )
16420{
16421 SCIP_INTERVAL* yinter;
16423 SCIP_INTERVAL ytb;
16424 SCIP_INTERVAL prod;
16425 SCIP_INTERVAL diff;
16427 SCIP_INTERVAL minprod;
16429 SCIP_ROW* row;
16430 SCIP_COL* col;
16431 SCIP_Real y;
16432 SCIP_Real c;
16433 int i;
16434 int j;
16435
16436 assert(lp != NULL);
16437 assert(lp->solved);
16438 assert(set != NULL);
16439 assert(bound != NULL);
16440
16441 /* allocate buffer for storing y in interval arithmetic */
16442 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16443
16444 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16445 SCIPintervalSet(&ytb, 0.0);
16446 for( j = 0; j < lp->nrows; ++j )
16447 {
16448 row = lp->rows[j];
16449 assert(row != NULL);
16450
16451 y = (usefarkas ? row->dualfarkas : row->dualsol);
16452
16454 {
16455 SCIPintervalSet(&yinter[j], y);
16456 SCIPintervalSet(&b, row->lhs - row->constant);
16457 }
16458 else if( SCIPsetIsFeasNegative(set, y) )
16459 {
16460 SCIPintervalSet(&yinter[j], y);
16461 SCIPintervalSet(&b, row->rhs - row->constant);
16462 }
16463 else
16464 {
16465 SCIPintervalSet(&yinter[j], 0.0);
16466 SCIPintervalSet(&b, 0.0);
16467 }
16468
16469 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16470 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16471 }
16472
16473 /* calculate min{(c^T - y^TA)x} */
16474 SCIPintervalSet(&minprod, 0.0);
16475 for( j = 0; j < lp->ncols; ++j )
16476 {
16477 col = lp->cols[j];
16478 assert(col != NULL);
16479 assert(col->nunlinked == 0);
16480
16482
16483 c = usefarkas ? 0.0 : col->obj;
16484 SCIPintervalSet(&diff, c);
16485
16486 for( i = 0; i < col->nlprows; ++i )
16487 {
16488 assert(col->rows[i] != NULL);
16489 assert(col->rows[i]->lppos >= 0);
16490 assert(col->linkpos[i] >= 0);
16491 SCIPintervalSet(&a, col->vals[i]);
16492 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16493 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16494 }
16495
16496#ifndef NDEBUG
16497 for( i = col->nlprows; i < col->len; ++i )
16498 {
16499 assert(col->rows[i] != NULL);
16500 assert(col->rows[i]->lppos == -1);
16501 assert(col->rows[i]->dualsol == 0.0);
16502 assert(col->rows[i]->dualfarkas == 0.0);
16503 assert(col->linkpos[i] >= 0);
16504 }
16505#endif
16506
16507 SCIPintervalSetBounds(&x, col->lb, col->ub);
16508 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16509 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16510 }
16511
16512 /* add y^Tb */
16513 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16514
16515 /* free buffer for storing y in interval arithmetic */
16516 SCIPsetFreeBufferArray(set, &yinter);
16517
16518 *bound = SCIPintervalGetInf(minprod);
16519
16520 return SCIP_OKAY;
16521}
16522
16523/** gets proven lower (dual) bound of last LP solution */
16525 SCIP_LP* lp, /**< current LP data */
16526 SCIP_SET* set, /**< global SCIP settings */
16527 SCIP_Real* bound /**< pointer to store proven dual bound */
16528 )
16529{
16531
16532 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16533
16534 return SCIP_OKAY;
16535}
16536
16537/** gets proven dual bound of last LP solution */
16539 SCIP_LP* lp, /**< current LP data */
16540 SCIP_SET* set, /**< global SCIP settings */
16541 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
16542 )
16543{
16545
16546 assert(proved != NULL);
16547
16548 SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16549
16550 *proved = (bound > 0.0);
16551
16552 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16553
16554 return SCIP_OKAY;
16555}
16556
16557
16558
16559/** writes LP to a file */
16561 SCIP_LP* lp, /**< current LP data */
16562 const char* fname /**< file name */
16563 )
16564{
16565 assert(lp != NULL);
16566 assert(lp->flushed);
16567 assert(fname != NULL);
16568
16569 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16570
16571 return SCIP_OKAY;
16572}
16573
16574/** writes MIP relaxation of the current B&B node to a file */
16576 SCIP_LP* lp, /**< current LP data */
16577 SCIP_SET* set, /**< global SCIP settings */
16578 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16579 const char* fname, /**< file name */
16580 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
16581 * troubles with reserved symbols? */
16582 SCIP_Bool origobj, /**< should the original objective function be used? */
16583 SCIP_OBJSENSE objsense, /**< objective sense */
16584 SCIP_Real objscale, /**< objective scaling factor */
16585 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
16586 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
16587 )
16588{
16589 FILE* file;
16590 int i;
16591 int j;
16592 char rowname[SCIP_MAXSTRLEN];
16593 SCIP_Real coeff;
16594
16595 assert(lp != NULL);
16596 assert(lp->flushed);
16597 assert(fname != NULL);
16598
16599 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16600 file = fopen(fname, "w");
16601 if( file == NULL )
16602 {
16603 SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16604 SCIPprintSysError(fname);
16605 return SCIP_FILECREATEERROR;
16606 }
16607
16608 /* print comments */
16609 if( genericnames )
16610 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16611 else
16612 {
16613 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16614 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16615 }
16616
16617 if( origobj && objoffset != 0.0 )
16618 {
16619 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16620 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16621 }
16622
16623 /* print objective function */
16624 /**@note the transformed problem in SCIP is always a minimization problem */
16625 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16626 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16627 else
16628 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16629
16630 /* print objective */
16631 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16632 j = 0;
16633 for( i = 0; i < lp->ncols; ++i )
16634 {
16635 if( lp->cols[i]->obj != 0.0 )
16636 {
16637 coeff = lp->cols[i]->obj;
16638 if( origobj )
16639 {
16640 coeff *= (SCIP_Real) objsense;
16641 coeff *= objscale;
16642 }
16643
16644 if( genericnames )
16645 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16646 else
16647 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16648
16649 ++j;
16650 if( j % 10 == 0 )
16651 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16652 }
16653 }
16654 /* add artificial variable 'objoffset' to transfer objective offset */
16655 if( origobj && objoffset != 0.0 )
16656 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16657
16658 /* print constraint section */
16659 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16660 for( i = 0; i < lp->nrows; i++ )
16661 {
16662 char type = 'i';
16663
16664 /* skip removable rows if we want to write them as lazy constraints */
16665 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16666 continue;
16667
16668 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16669 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16670 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16671 * type 'i' means: lhs and rhs are both infinite */
16672 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16673 type = 'r';
16674 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16675 type = 'l';
16676 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16677 type = 'e';
16678 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16679 type = 'b';
16680
16681 /* print name of row */
16682 if( genericnames )
16683 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16684 else
16685 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16686
16687 WRITEROW:
16688 switch( type )
16689 {
16690 case 'r':
16691 case 'l':
16692 case 'e':
16693 if( strlen(rowname) > 0 )
16694 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16695 break;
16696 case 'i':
16697 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16698 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16699 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16700 type = 'b';
16701 /*lint -fallthrough*/
16702 case 'b':
16703 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16704 break;
16705 default:
16706 assert(type == 'B');
16707 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16708 break;
16709 }
16710
16711 /* print coefficients and variables */
16712 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16713 {
16714 if( genericnames )
16715 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16716 else
16717 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16718
16719 if( (j+1) % 10 == 0 )
16720 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16721 }
16722
16723 /* print right hand side */
16724 switch( type )
16725 {
16726 case 'b':
16727 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16728 type = 'B';
16729 goto WRITEROW;
16730 case 'l':
16731 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16732 break;
16733 case 'B':
16734 case 'r':
16735 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16736 break;
16737 case 'e':
16738 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16739 break;
16740 default:
16741 SCIPerrorMessage("Undefined row type!\n");
16742 fclose(file);
16743 return SCIP_ERROR;
16744 }
16745 }
16746
16747 if ( lazyconss )
16748 {
16749 /* print lazy constraint section */
16750 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16751 for( i = 0; i < lp->nrows; i++ )
16752 {
16753 char type = 'i';
16754
16755 /* skip non-removable rows if we want to write lazy constraints */
16756 if ( ! SCIProwIsRemovable(lp->rows[i]) )
16757 continue;
16758
16759 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16760 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16761 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16762 * type 'i' means: lhs and rhs are both infinite */
16763 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16764 type = 'r';
16765 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16766 type = 'l';
16767 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16768 type = 'e';
16769 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16770 type = 'b';
16771
16772 /* print name of row */
16773 if( genericnames )
16774 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16775 else
16776 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16777
16778 WRITELAZYROW:
16779 switch( type )
16780 {
16781 case 'r':
16782 case 'l':
16783 case 'e':
16784 if( strlen(rowname) > 0 )
16785 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16786 break;
16787 case 'i':
16788 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16789 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16790 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16791 type = 'b';
16792 /*lint -fallthrough*/
16793 case 'b':
16794 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16795 break;
16796 default:
16797 assert(type == 'B');
16798 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16799 break;
16800 }
16801
16802 /* print coefficients and variables */
16803 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16804 {
16805 if( genericnames )
16806 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16807 else
16808 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16809
16810 if( (j+1) % 10 == 0 )
16811 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16812 }
16813
16814 /* print right hand side */
16815 switch( type )
16816 {
16817 case 'b':
16818 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16819 type = 'B';
16820 goto WRITELAZYROW;
16821 case 'l':
16822 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16823 break;
16824 case 'B':
16825 case 'r':
16826 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16827 break;
16828 case 'e':
16829 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16830 break;
16831 default:
16832 SCIPerrorMessage("Undefined row type!\n");
16833 fclose(file);
16834 return SCIP_ERROR;
16835 }
16836 }
16837 }
16838
16839 /* print variable bounds */
16840 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16841 for( i = 0; i < lp->ncols; ++i )
16842 {
16843 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16844 {
16845 /* print lower bound as far this one is not infinity */
16846 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16847 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16848
16849 /* print variable name */
16850 if( genericnames )
16851 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16852 else
16853 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16854
16855 /* print upper bound as far this one is not infinity */
16856 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16857 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16858 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16859 }
16860 }
16861 if( origobj && objoffset != 0.0 )
16862 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16863
16864 /* print integer variables */
16865 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16866 j = 0;
16867 for( i = 0; i < lp->ncols; ++i )
16868 {
16869 if( SCIPvarIsIntegral(lp->cols[i]->var) )
16870 {
16871 /* print variable name */
16872 if( genericnames )
16873 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16874 else
16875 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16876
16877 j++;
16878 if( j % 10 == 0 )
16879 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16880 }
16881 }
16882
16883 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16884 fclose(file);
16885
16886 return SCIP_OKAY;
16887}
16888
16889/*
16890 * simple functions implemented as defines
16891 */
16892
16893/* In debug mode, the following methods are implemented as function calls to ensure
16894 * type validity.
16895 * In optimized mode, the methods are implemented as defines to improve performance.
16896 * However, we want to have them in the library anyways, so we have to undef the defines.
16897 */
16898
16899#undef SCIPcolGetObj
16900#undef SCIPcolGetLb
16901#undef SCIPcolGetUb
16902#undef SCIPcolGetBestBound
16903#undef SCIPcolGetPrimsol
16904#undef SCIPcolGetMinPrimsol
16905#undef SCIPcolGetMaxPrimsol
16906#undef SCIPcolGetBasisStatus
16907#undef SCIPcolGetVar
16908#undef SCIPcolGetIndex
16909#undef SCIPcolGetVarProbindex
16910#undef SCIPcolIsIntegral
16911#undef SCIPcolIsRemovable
16912#undef SCIPcolGetLPPos
16913#undef SCIPcolGetLPDepth
16914#undef SCIPcolIsInLP
16915#undef SCIPcolGetNNonz
16916#undef SCIPcolGetNLPNonz
16917#undef SCIPcolGetRows
16918#undef SCIPcolGetVals
16919#undef SCIPcolGetStrongbranchNode
16920#undef SCIPcolGetNStrongbranchs
16921#undef SCIPcolGetAge
16922#undef SCIPboundtypeOpposite
16923#undef SCIProwGetNNonz
16924#undef SCIProwGetNLPNonz
16925#undef SCIProwGetCols
16926#undef SCIProwGetVals
16927#undef SCIProwGetConstant
16928#undef SCIProwGetNorm
16929#undef SCIProwGetSumNorm
16930#undef SCIProwGetLhs
16931#undef SCIProwGetRhs
16932#undef SCIProwGetDualsol
16933#undef SCIProwGetDualfarkas
16934#undef SCIProwGetBasisStatus
16935#undef SCIProwGetName
16936#undef SCIProwGetIndex
16937#undef SCIProwGetAge
16938#undef SCIProwGetRank
16939#undef SCIProwIsIntegral
16940#undef SCIProwIsLocal
16941#undef SCIProwIsModifiable
16942#undef SCIProwIsRemovable
16943#undef SCIProwGetOrigintype
16944#undef SCIProwGetOriginCons
16945#undef SCIProwGetOriginConshdlr
16946#undef SCIProwGetOriginSepa
16947#undef SCIProwIsInGlobalCutpool
16948#undef SCIProwGetLPPos
16949#undef SCIProwGetLPDepth
16950#undef SCIProwIsInLP
16951#undef SCIProwGetActiveLPCount
16952#undef SCIProwGetNLPsAfterCreation
16953#undef SCIProwChgRank
16954#undef SCIPlpGetCols
16955#undef SCIPlpGetNCols
16956#undef SCIPlpGetRows
16957#undef SCIPlpGetNRows
16958#undef SCIPlpGetNewcols
16959#undef SCIPlpGetNNewcols
16960#undef SCIPlpGetNewrows
16961#undef SCIPlpGetNNewrows
16962#undef SCIPlpGetObjNorm
16963#undef SCIPlpGetRootObjval
16964#undef SCIPlpGetRootColumnObjval
16965#undef SCIPlpGetRootLooseObjval
16966#undef SCIPlpGetLPI
16967#undef SCIPlpSetIsRelax
16968#undef SCIPlpIsRelax
16969#undef SCIPlpIsSolved
16970#undef SCIPlpIsSolBasic
16971#undef SCIPlpDiving
16972#undef SCIPlpDivingObjChanged
16973#undef SCIPlpMarkDivingObjChanged
16974#undef SCIPlpUnmarkDivingObjChanged
16975#undef SCIPlpDivingRowsChanged
16976#undef SCIPlpIsFeasEQ
16977#undef SCIPlpIsFeasLT
16978#undef SCIPlpIsFeasLE
16979#undef SCIPlpIsFeasGT
16980#undef SCIPlpIsFeasGE
16981#undef SCIPlpIsFeasZero
16982#undef SCIPlpIsFeasPositive
16983#undef SCIPlpIsFeasNegative
16984
16985/** gets objective value of column */
16987 SCIP_COL* col /**< LP column */
16988 )
16989{
16990 assert(col != NULL);
16991
16992 return col->obj;
16993}
16994
16995/** gets lower bound of column */
16997 SCIP_COL* col /**< LP column */
16998 )
16999{
17000 assert(col != NULL);
17001
17002 return col->lb;
17003}
17004
17005/** gets upper bound of column */
17007 SCIP_COL* col /**< LP column */
17008 )
17009{
17010 assert(col != NULL);
17011
17012 return col->ub;
17013}
17014
17015/** gets best bound of column with respect to the objective function */
17017 SCIP_COL* col /**< LP column */
17018 )
17019{
17020 assert(col != NULL);
17021
17022 if( col->obj >= 0.0 )
17023 return col->lb;
17024 else
17025 return col->ub;
17026}
17027
17028/** gets the primal LP solution of a column */
17030 SCIP_COL* col /**< LP column */
17031 )
17032{
17033 assert(col != NULL);
17034
17035 if( col->lppos >= 0 )
17036 return col->primsol;
17037 else
17038 return 0.0;
17039}
17040
17041/** gets the minimal LP solution value, this column ever assumed */
17043 SCIP_COL* col /**< LP column */
17044 )
17045{
17046 assert(col != NULL);
17047
17048 return col->minprimsol;
17049}
17050
17051/** gets the maximal LP solution value, this column ever assumed */
17053 SCIP_COL* col /**< LP column */
17054 )
17055{
17056 assert(col != NULL);
17057
17058 return col->maxprimsol;
17059}
17060
17061/** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17062 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17063 */
17065 SCIP_COL* col /**< LP column */
17066 )
17067{
17068 assert(col != NULL);
17069 assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
17070
17071 return (SCIP_BASESTAT)col->basisstatus;
17072}
17073
17074/** gets variable this column represents */
17076 SCIP_COL* col /**< LP column */
17077 )
17078{
17079 assert(col != NULL);
17080
17081 return col->var;
17082}
17083
17084/** gets unique index of col */
17086 SCIP_COL* col /**< LP col */
17087 )
17088{
17089 assert(col != NULL);
17090
17091 return col->index;
17092}
17093
17094/** gets probindex of corresponding variable */
17096 SCIP_COL* col /**< LP col */
17097 )
17098{
17099 assert(col != NULL);
17100
17101 return col->var_probindex;
17102}
17103
17104/** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17106 SCIP_COL* col /**< LP column */
17107 )
17108{
17109 assert(col != NULL);
17110 assert(SCIPvarIsIntegral(col->var) == col->integral);
17111
17112 return col->integral;
17113}
17114
17115/** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17117 SCIP_COL* col /**< LP column */
17118 )
17119{
17120 assert(col != NULL);
17121
17122 return col->removable;
17123}
17124
17125/** gets position of column in current LP, or -1 if it is not in LP */
17127 SCIP_COL* col /**< LP column */
17128 )
17129{
17130 assert(col != NULL);
17131 assert((col->lppos == -1) == (col->lpdepth == -1));
17132
17133 return col->lppos;
17134}
17135
17136/** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17138 SCIP_COL* col /**< LP column */
17139 )
17140{
17141 assert(col != NULL);
17142 assert((col->lppos == -1) == (col->lpdepth == -1));
17143
17144 return col->lpdepth;
17145}
17146
17147/** returns TRUE iff column is member of current LP */
17149 SCIP_COL* col /**< LP column */
17150 )
17151{
17152 assert(col != NULL);
17153 assert((col->lppos == -1) == (col->lpdepth == -1));
17154
17155 return (col->lppos >= 0);
17156}
17157
17158/** get number of nonzero entries in column vector */
17160 SCIP_COL* col /**< LP column */
17161 )
17162{
17163 assert(col != NULL);
17164
17165 return col->len;
17166}
17167
17168/** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17169 *
17170 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17171 * 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
17172 */
17174 SCIP_COL* col /**< LP column */
17175 )
17176{
17177 assert(col != NULL);
17178 assert(col->nunlinked == 0);
17179
17180 return col->nlprows;
17181}
17182
17183/** gets array with rows of nonzero entries */
17185 SCIP_COL* col /**< LP column */
17186 )
17187{
17188 assert(col != NULL);
17189
17190 return col->rows;
17191}
17192
17193/** gets array with coefficients of nonzero entries */
17195 SCIP_COL* col /**< LP column */
17196 )
17197{
17198 assert(col != NULL);
17199
17200 return col->vals;
17201}
17202
17203/** gets node number of the last node in current branch and bound run, where strong branching was used on the
17204 * given column, or -1 if strong branching was never applied to the column in current run
17205 */
17207 SCIP_COL* col /**< LP column */
17208 )
17209{
17210 assert(col != NULL);
17211
17212 return col->sbnode;
17213}
17214
17215/** gets number of times, strong branching was applied in current run on the given column */
17217 SCIP_COL* col /**< LP column */
17218 )
17219{
17220 assert(col != NULL);
17221
17222 return col->nsbcalls;
17223}
17224
17225/** 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 */
17227 SCIP_COL* col /**< LP column */
17228 )
17229{
17230 assert(col != NULL);
17231
17232 return col->age;
17233}
17234
17235/** gets opposite bound type of given bound type */
17237 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
17238 )
17239{
17240 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17241
17243}
17244
17245/** get number of nonzero entries in row vector */
17247 SCIP_ROW* row /**< LP row */
17248 )
17249{
17250 assert(row != NULL);
17251
17252 return row->len;
17253}
17254
17255/** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17256 *
17257 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17258 * 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
17259 */
17261 SCIP_ROW* row /**< LP row */
17262 )
17263{
17264 assert(row != NULL);
17265 assert(row->nunlinked == 0);
17266
17267 return row->nlpcols;
17268}
17269
17270/** gets array with columns of nonzero entries */
17272 SCIP_ROW* row /**< LP row */
17273 )
17274{
17275 assert(row != NULL);
17276
17277 return row->cols;
17278}
17279
17280/** gets array with coefficients of nonzero entries */
17282 SCIP_ROW* row /**< LP row */
17283 )
17284{
17285 assert(row != NULL);
17286
17287 return row->vals;
17288}
17289
17290/** gets constant shift of row */
17292 SCIP_ROW* row /**< LP row */
17293 )
17294{
17295 assert(row != NULL);
17296
17297 return row->constant;
17298}
17299
17300/** gets Euclidean norm of row vector */
17302 SCIP_ROW* row /**< LP row */
17303 )
17304{
17305 assert(row != NULL);
17306
17307 checkRowSqrnorm(row);
17308
17309 return sqrt(row->sqrnorm);
17310}
17311
17312/** gets sum norm of row vector (sum of absolute values of coefficients) */
17314 SCIP_ROW* row /**< LP row */
17315 )
17316{
17317 assert(row != NULL);
17318
17319 checkRowSumnorm(row);
17320
17321 return row->sumnorm;
17322}
17323
17324/** returns the left hand side of the row */
17326 SCIP_ROW* row /**< LP row */
17327 )
17328{
17329 assert(row != NULL);
17330
17331 return row->lhs;
17332}
17333
17334/** returns the right hand side of the row */
17336 SCIP_ROW* row /**< LP row */
17337 )
17338{
17339 assert(row != NULL);
17340
17341 return row->rhs;
17342}
17343
17344/** gets the dual LP solution of a row */
17346 SCIP_ROW* row /**< LP row */
17347 )
17348{
17349 assert(row != NULL);
17350
17351 if( row->lppos >= 0 )
17352 return row->dualsol;
17353 else
17354 return 0.0;
17355}
17356
17357/** gets the dual Farkas coefficient of a row in an infeasible LP */
17359 SCIP_ROW* row /**< LP row */
17360 )
17361{
17362 assert(row != NULL);
17363
17364 if( row->lppos >= 0 )
17365 return row->dualfarkas;
17366 else
17367 return 0.0;
17368}
17369
17370/** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17371 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17372 */
17374 SCIP_ROW* row /**< LP row */
17375 )
17376{
17377 assert(row != NULL);
17378 assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
17379
17380 return (SCIP_BASESTAT)row->basisstatus;
17381}
17382
17383/** returns the name of the row */
17384const char* SCIProwGetName(
17385 SCIP_ROW* row /**< LP row */
17386 )
17387{
17388 assert(row != NULL);
17389
17390 return row->name;
17391}
17392
17393/** gets unique index of row */
17395 SCIP_ROW* row /**< LP row */
17396 )
17397{
17398 assert(row != NULL);
17399
17400 return row->index;
17401}
17402
17403/** gets age of row */
17405 SCIP_ROW* row /**< LP row */
17406 )
17407{
17408 assert(row != NULL);
17409
17410 return row->age;
17411}
17412
17413/** gets rank of row */
17415 SCIP_ROW* row /**< LP row */
17416 )
17417{
17418 assert(row != NULL);
17419
17420 return row->rank;
17421}
17422
17423/** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17425 SCIP_ROW* row /**< LP row */
17426 )
17427{
17428 assert(row != NULL);
17429
17430 return row->integral;
17431}
17432
17433/** returns TRUE iff row is only valid locally */
17435 SCIP_ROW* row /**< LP row */
17436 )
17437{
17438 assert(row != NULL);
17439
17440 return row->local;
17441}
17442
17443/** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17445 SCIP_ROW* row /**< LP row */
17446 )
17447{
17448 assert(row != NULL);
17449
17450 return row->modifiable;
17451}
17452
17453/** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17455 SCIP_ROW* row /**< LP row */
17456 )
17457{
17458 assert(row != NULL);
17459
17460 return row->removable;
17461}
17462
17463/** returns type of origin that created the row */
17465 SCIP_ROW* row /**< LP row */
17466 )
17467{
17468 assert( row != NULL );
17469
17470 return (SCIP_ROWORIGINTYPE) row->origintype;
17471}
17472
17473/** returns origin constraint that created the row (NULL if not available) */
17475 SCIP_ROW* row /**< LP row */
17476 )
17477{
17478 assert( row != NULL );
17479
17481 {
17482 assert( row->origin != NULL );
17483 return (SCIP_CONS*) row->origin;
17484 }
17485 return NULL;
17486}
17487
17488/** returns origin constraint handler that created the row (NULL if not available) */
17490 SCIP_ROW* row /**< LP row */
17491 )
17492{
17493 assert( row != NULL );
17494
17496 {
17497 assert( row->origin != NULL );
17498 return (SCIP_CONSHDLR*) row->origin;
17499 }
17501 {
17502 assert(row->origin != NULL);
17503 return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17504 }
17505 return NULL;
17506}
17507
17508/** returns origin separator that created the row (NULL if not available) */
17510 SCIP_ROW* row /**< LP row */
17511 )
17512{
17513 assert( row != NULL );
17514
17516 {
17517 assert( row->origin != NULL );
17518 return (SCIP_SEPA*) row->origin;
17519 }
17520 return NULL;
17521}
17522
17523/** returns TRUE iff row is member of the global cut pool */
17525 SCIP_ROW* row /**< LP row */
17526 )
17527{
17528 assert(row != NULL);
17529
17530 return row->inglobalcutpool;
17531}
17532
17533/** gets position of row in current LP, or -1 if it is not in LP */
17535 SCIP_ROW* row /**< LP row */
17536 )
17537{
17538 assert(row != NULL);
17539 assert((row->lppos == -1) == (row->lpdepth == -1));
17540
17541 return row->lppos;
17542}
17543
17544/** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17546 SCIP_ROW* row /**< LP row */
17547 )
17548{
17549 assert(row != NULL);
17550 assert((row->lppos == -1) == (row->lpdepth == -1));
17551
17552 return row->lpdepth;
17553}
17554
17555/** returns TRUE iff row is member of current LP */
17557 SCIP_ROW* row /**< LP row */
17558 )
17559{
17560 assert(row != NULL);
17561 assert((row->lppos == -1) == (row->lpdepth == -1));
17562
17563 return (row->lppos >= 0);
17564}
17565
17566/** changes the rank of LP row */
17568 SCIP_ROW* row, /**< LP row */
17569 int rank /**< new value for rank */
17570 )
17571{
17572 assert(row != NULL);
17573
17574 row->rank = rank;
17575}
17576
17577/** returns the number of times that this row has been sharp in an optimal LP solution */
17579 SCIP_ROW* row /**< row */
17580 )
17581{
17582 assert(row != NULL);
17583
17584 return row->activeinlpcounter;
17585}
17586
17587/** returns the number of LPs since this row has been created */
17589 SCIP_ROW* row /**< row */
17590 )
17591{
17592 assert(row != NULL);
17593
17594 return row->nlpsaftercreation;
17595}
17596
17597/** gets array with columns of the LP */
17599 SCIP_LP* lp /**< current LP data */
17600 )
17601{
17602 assert(lp != NULL);
17603
17604 return lp->cols;
17605}
17606
17607/** gets current number of columns in LP */
17609 SCIP_LP* lp /**< current LP data */
17610 )
17611{
17612 assert(lp != NULL);
17613
17614 return lp->ncols;
17615}
17616
17617/** gets current number of unfixed columns in LP */
17619 SCIP_LP* lp, /**< current LP data */
17620 SCIP_Real eps /**< numerical tolerance */
17621 )
17622{
17623 SCIP_COL** lpcols;
17624 int nlpcols;
17625 int nunfixedcols;
17626 int c;
17627
17628 assert(lp != NULL);
17629 assert(eps > 0.0);
17630
17631 lpcols = lp->cols;
17632 nlpcols = lp->ncols;
17633
17634 nunfixedcols = 0;
17635 for( c = 0; c < nlpcols; ++c )
17636 {
17637 if( lpcols[c]->ub - lpcols[c]->lb > eps )
17638 ++nunfixedcols;
17639 }
17640
17641 return nunfixedcols;
17642}
17643
17644/** gets array with rows of the LP */
17646 SCIP_LP* lp /**< current LP data */
17647 )
17648{
17649 assert(lp != NULL);
17650
17651 return lp->rows;
17652}
17653
17654/** gets current number of rows in LP */
17656 SCIP_LP* lp /**< current LP data */
17657 )
17658{
17659 assert(lp != NULL);
17660
17661 return lp->nrows;
17662}
17663
17664/** gets array with newly added columns after the last mark */
17666 SCIP_LP* lp /**< current LP data */
17667 )
17668{
17669 assert(lp != NULL);
17670 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17671
17672 return &(lp->cols[lp->firstnewcol]);
17673}
17674
17675/** gets number of newly added columns after the last mark */
17677 SCIP_LP* lp /**< current LP data */
17678 )
17679{
17680 assert(lp != NULL);
17681 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17682
17683 return lp->ncols - lp->firstnewcol;
17684}
17685
17686/** gets array with newly added rows after the last mark */
17688 SCIP_LP* lp /**< current LP data */
17689 )
17690{
17691 assert(lp != NULL);
17692 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17693
17694 return &(lp->rows[lp->firstnewrow]);
17695}
17696
17697/** gets number of newly added rows after the last mark */
17699 SCIP_LP* lp /**< current LP data */
17700 )
17701{
17702 assert(lp != NULL);
17703 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17704
17705 return lp->nrows - lp->firstnewrow;
17706}
17707
17708/** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17710 SCIP_SET* set, /**< global SCIP settings */
17711 SCIP_LP* lp /**< LP data */
17712 )
17713{
17714 if( lp->objsqrnormunreliable )
17715 {
17716 SCIP_COL** cols;
17717 int c;
17718
17719 cols = lp->cols;
17720 assert(cols != NULL || lp->ncols == 0);
17721
17722 lp->objsqrnorm = 0.0;
17723
17724 for( c = lp->ncols - 1; c >= 0; --c )
17725 {
17726 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
17727 }
17728 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17729
17730 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17731 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17732
17734 }
17735 return;
17736}
17737
17738/** gets Euclidean norm of objective function vector of column variables, only use this method if
17739 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17741 SCIP_LP* lp /**< LP data */
17742 )
17743{
17744 assert(lp != NULL);
17745 assert(!lp->objsqrnormunreliable);
17746 assert(lp->objsqrnorm >= 0.0);
17747
17748 return sqrt(lp->objsqrnorm);
17749}
17750
17751/** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17753 SCIP_LP* lp, /**< LP data */
17754 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
17755 )
17756{
17757 assert(lp != NULL);
17758
17759 lp->rootlpisrelax = isrelax;
17760}
17761
17762/** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17764 SCIP_LP* lp /**< LP data */
17765 )
17766{
17767 assert(lp != NULL);
17768
17769 return lp->rootlpisrelax;
17770}
17771
17772/** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17774 SCIP_LP* lp /**< LP data */
17775 )
17776{
17777 assert(lp != NULL);
17778
17779 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17780}
17781
17782/** gets part of the objective value of the root node LP that results from COLUMN variables only;
17783 * returns SCIP_INVALID if the root node LP was not (yet) solved
17784 */
17786 SCIP_LP* lp /**< LP data */
17787 )
17788{
17789 assert(lp != NULL);
17790
17791 return lp->rootlpobjval;
17792}
17793
17794/** gets part of the objective value of the root node LP that results from LOOSE variables only;
17795 * returns SCIP_INVALID if the root node LP was not (yet) solved
17796 */
17798 SCIP_LP* lp /**< LP data */
17799 )
17800{
17801 assert(lp != NULL);
17802
17803 return lp->rootlooseobjval;
17804}
17805
17806/** gets the LP solver interface */
17808 SCIP_LP* lp /**< current LP data */
17809 )
17810{
17811 assert(lp != NULL);
17812
17813 return lp->lpi;
17814}
17815
17816/** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17818 SCIP_LP* lp, /**< LP data */
17819 SCIP_Bool relax /**< is the current lp a relaxation? */
17820 )
17821{
17822 assert(lp != NULL);
17823
17824 lp->isrelax = relax;
17825}
17826
17827/** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17828 * solution value a valid local lower bound?
17829 */
17831 SCIP_LP* lp /**< LP data */
17832 )
17833{
17834 assert(lp != NULL);
17835
17836 return lp->isrelax;
17837}
17838
17839/** returns whether the current LP is flushed and solved */
17841 SCIP_LP* lp /**< current LP data */
17842 )
17843{
17844 assert(lp != NULL);
17845
17846 return lp->flushed && lp->solved;
17847}
17848
17849/** return whether the current LP solution passed the primal feasibility check */
17851 SCIP_LP* lp /**< current LP data */
17852 )
17853{
17854 assert(lp != NULL);
17855
17856 return (lp->primalchecked && lp->primalfeasible);
17857}
17858
17859/** return whether the current LP solution passed the dual feasibility check */
17861 SCIP_LP* lp /**< current LP data */
17862 )
17863{
17864 assert(lp != NULL);
17865
17866 return (lp->dualchecked && lp->dualfeasible);
17867}
17868
17869/** returns whether the current LP solution is a basic solution */
17871 SCIP_LP* lp /**< current LP data */
17872 )
17873{
17874 assert(lp != NULL);
17875
17876 return lp->solisbasic;
17877}
17878
17879/** returns whether the LP is in diving mode */
17881 SCIP_LP* lp /**< current LP data */
17882 )
17883{
17884 assert(lp != NULL);
17885
17886 return lp->diving;
17887}
17888
17889/** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17891 SCIP_LP* lp /**< current LP data */
17892 )
17893{
17894 assert(lp != NULL);
17895
17896 return lp->divingobjchg;
17897}
17898
17899/** marks the diving LP to have a changed objective function */
17901 SCIP_LP* lp /**< current LP data */
17902 )
17903{
17904 assert(lp != NULL);
17905 assert(lp->diving || lp->probing);
17906
17907 lp->divingobjchg = TRUE;
17908}
17909
17910/** marks the diving LP to not have a changed objective function anymore */
17912 SCIP_LP* lp /**< current LP data */
17913 )
17914{
17915 assert(lp != NULL);
17916 assert(lp->diving || lp->probing);
17917
17918 lp->divingobjchg = FALSE;
17919}
17920
17921/* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17923 SCIP_LP* lp /**< current LP data */
17924 )
17925{
17926 assert(lp != NULL);
17927 assert(lp->diving || lp->ndivechgsides == 0);
17928
17929 return (lp->ndivechgsides > 0);
17930}
17931
17932/** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17933static
17935 SCIP_LPI* lpi, /**< auxiliary LP interface */
17936 SCIP_SET* set, /**< global SCIP settings */
17937 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17938 SCIP_LP* lp, /**< LP data */
17939 SCIP_PROB* prob, /**< problem data */
17940 SCIP_Bool relaxrows, /**< should the rows be relaxed */
17941 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
17942 SCIP_Real timelimit, /**< time limit for LP solver */
17943 int iterlimit, /**< iteration limit for LP solver */
17944 SCIP_Real* point, /**< array to store relative interior point on exit */
17945 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
17946 )
17947{
17948 SCIP_RETCODE retcode;
17949 SCIP_Real* primal;
17950 SCIP_Real* obj;
17951 SCIP_Real* lb;
17952 SCIP_Real* ub;
17953 SCIP_Real* matvals;
17954 SCIP_Real* matlhs;
17955 SCIP_Real* matrhs;
17956 SCIP_Real objval;
17957 SCIP_Real alpha;
17958 int* matinds;
17959 int* matbeg;
17960#ifndef NDEBUG
17961 int nslacks;
17962#endif
17963 int nnewcols;
17964 int ntotnonz = 0;
17965 int ntotrows = 0;
17966 int matrowidx;
17967 int matidx;
17968 int cnt;
17969 int j;
17970 int i;
17971
17972 assert(lpi != NULL);
17973
17974 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17975 if( retcode != SCIP_OKAY )
17976 {
17977 /* stop execution on error, since result is likely to be unsuable */
17978 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17979 return SCIP_LPERROR;
17980 }
17981
17983 if( retcode != SCIP_OKAY )
17984 {
17985 /* stop execution on error, since result is likely to be unsuable */
17986 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17987 return SCIP_LPERROR;
17988 }
17989
17990 /* get storage */
17991 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17992 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17993 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17994 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17995
17996 /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17997 for( j = 0; j < lp->ncols; ++j )
17998 {
17999 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
18000 obj[j] = 0.0;
18001 lb[j] = -SCIPlpiInfinity(lpi);
18002 ub[j] = SCIPlpiInfinity(lpi);
18003 /* note: we could also use the original bounds - free variables seem to be faster. */
18004 }
18005
18006 /* add artificial alpha variable */
18007 nnewcols = lp->ncols;
18008 obj[nnewcols] = 0.0;
18009 lb[nnewcols] = 1.0;
18010 ub[nnewcols] = SCIPlpiInfinity(lpi);
18011 ++nnewcols;
18012
18013 /* create slacks for rows */
18014 for( i = 0; i < lp->nrows; ++i )
18015 {
18016 SCIP_ROW* row;
18017
18018 row = lp->rows[i];
18019 assert( row != NULL );
18020
18021 if( SCIProwIsModifiable(row) )
18022 continue;
18023
18024 /* make sure row is sorted */
18025 rowSortLP(row);
18026 assert( row->lpcolssorted );
18027
18028 /* check whether we have an equation */
18029 if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
18030 {
18031 assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
18032 assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
18033 ntotnonz += row->nlpcols + 1;
18034 ++ntotrows;
18035 }
18036 else
18037 {
18038 /* otherwise add slacks for each side if necessary */
18039 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18040 {
18041 if ( relaxrows )
18042 {
18043 lb[nnewcols] = 0.0;
18044 ub[nnewcols] = 1.0;
18045 obj[nnewcols++] = 1.0;
18046 ntotnonz += row->nlpcols + 2;
18047 }
18048 else
18049 ntotnonz += row->nlpcols + 1;
18050 ++ntotrows;
18051 }
18052 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18053 {
18054 if ( relaxrows )
18055 {
18056 lb[nnewcols] = 0.0;
18057 ub[nnewcols] = 1.0;
18058 obj[nnewcols++] = 1.0;
18059 ntotnonz += row->nlpcols + 2;
18060 }
18061 else
18062 ntotnonz += row->nlpcols + 1;
18063 ++ntotrows;
18064 }
18065 }
18066 }
18067
18068 /* create slacks for objective cutoff row */
18069 if( inclobjcutoff && relaxrows )
18070 {
18071 /* add slacks for right hand side */
18072 lb[nnewcols] = 0.0;
18073 ub[nnewcols] = 1.0;
18074 obj[nnewcols++] = 1.0;
18075 ntotnonz += lp->ncols + 2;
18076 ++ntotrows;
18077 }
18078
18079 /* create slacks for bounds */
18080 for( j = 0; j < lp->ncols; ++j )
18081 {
18082 SCIP_COL* col;
18083
18084 col = lp->cols[j];
18085 assert( col != NULL );
18086
18087 /* no slacks for fixed variables */
18088 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18089 {
18090 ++ntotrows;
18091 ntotnonz += 2;
18092 }
18093 else
18094 {
18095 /* add slacks for each bound if necessary */
18096 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18097 {
18098 lb[nnewcols] = 0.0;
18099 ub[nnewcols] = 1.0;
18100 obj[nnewcols++] = 1.0;
18101 ntotnonz += 3;
18102 ++ntotrows;
18103 }
18104 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18105 {
18106 lb[nnewcols] = 0.0;
18107 ub[nnewcols] = 1.0;
18108 obj[nnewcols++] = 1.0;
18109 ntotnonz += 3;
18110 ++ntotrows;
18111 }
18112 }
18113 }
18114#ifndef NDEBUG
18115 nslacks = nnewcols - lp->ncols - 1;
18116 assert( nslacks >= 0 );
18117 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18118#endif
18119
18120 /* add columns */
18121 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18122
18123 /* free storage */
18127
18128 /* prepare storage for rows */
18129 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18130 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18131 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18132 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18133 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18134
18135 /* create rows arising from original rows */
18136 cnt = 0;
18137 matrowidx = 0;
18138 matidx = 0;
18139 for( i = 0; i < lp->nrows; ++i )
18140 {
18141 SCIP_ROW* row;
18142 SCIP_COL** rowcols;
18143 SCIP_Real* rowvals;
18144 SCIP_Real lhs;
18145 SCIP_Real rhs;
18146 int nnonz;
18147
18148 row = lp->rows[i];
18149 assert( row != NULL );
18150
18151 if( SCIProwIsModifiable(row) )
18152 continue;
18153 assert( row->lpcolssorted );
18154
18155 /* get row data */
18156 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18157 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18158 nnonz = row->nlpcols;
18159 assert( nnonz <= lp->ncols );
18160 rowcols = row->cols;
18161 rowvals = row->vals;
18162
18163 /* if we have an equation */
18164 if( SCIPsetIsEQ(set, lhs, rhs) )
18165 {
18166 /* set up indices */
18167 matbeg[matrowidx] = matidx;
18168 for( j = 0; j < nnonz; ++j )
18169 {
18170 assert( rowcols[j] != NULL );
18171 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18172 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18173 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18174 matinds[matidx] = rowcols[j]->lppos;
18175 matvals[matidx++] = rowvals[j];
18176 assert( matidx <= ntotnonz );
18177 }
18178
18179 /* add artificial variable */
18180 if ( ! SCIPsetIsZero(set, rhs) )
18181 {
18182 matinds[matidx] = lp->ncols;
18183 matvals[matidx++] = -rhs;
18184 assert( matidx <= ntotnonz );
18185 }
18186
18187 matlhs[matrowidx] = 0.0;
18188 matrhs[matrowidx++] = 0.0;
18189 assert( matrowidx <= ntotrows );
18190 }
18191 else
18192 {
18193 SCIP_Real abslhs = REALABS(lhs);
18194 SCIP_Real absrhs = REALABS(rhs);
18195
18196 assert(!SCIPsetIsEQ(set, lhs, rhs));
18197
18198 /* treat lhs */
18199 if( !SCIPsetIsInfinity(set, abslhs) )
18200 {
18201 /* set up indices */
18202 matbeg[matrowidx] = matidx;
18203 for( j = 0; j < nnonz; ++j )
18204 {
18205 assert( rowcols[j] != NULL );
18206 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18207 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18208 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18209 matinds[matidx] = rowcols[j]->lppos;
18210 matvals[matidx++] = rowvals[j];
18211 assert( matidx <= ntotnonz );
18212 }
18213
18214 /* add artificial variable */
18215 if ( ! SCIPsetIsZero(set, lhs) )
18216 {
18217 matinds[matidx] = lp->ncols;
18218 matvals[matidx++] = -lhs;
18219 assert( matidx <= ntotnonz );
18220 }
18221
18222 if( relaxrows )
18223 {
18224 /* add slack variable */
18225 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/
18226 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18227 assert( matidx <= ntotnonz );
18228 ++cnt;
18229 }
18230
18231 matlhs[matrowidx] = 0.0;
18232 matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18233 assert( matrowidx <= ntotrows );
18234 }
18235
18236 /* treat rhs */
18237 if( !SCIPsetIsInfinity(set, absrhs) )
18238 {
18239 /* set up indices */
18240 matbeg[matrowidx] = matidx;
18241 for( j = 0; j < nnonz; ++j )
18242 {
18243 assert( rowcols[j] != NULL );
18244 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18245 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18246 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18247 matinds[matidx] = rowcols[j]->lppos;
18248 matvals[matidx++] = rowvals[j];
18249 assert( matidx <= ntotnonz );
18250 }
18251
18252 /* add artificial variable */
18253 if ( ! SCIPsetIsZero(set, rhs) )
18254 {
18255 matinds[matidx] = lp->ncols;
18256 matvals[matidx++] = -rhs;
18257 assert( matidx <= ntotnonz );
18258 }
18259
18260 if( relaxrows )
18261 {
18262 /* add slack variable */
18263 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/
18264 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18265 ++cnt;
18266 }
18267
18268 matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18269 matrhs[matrowidx++] = 0.0;
18270 assert( matrowidx <= ntotrows );
18271 }
18272 }
18273 }
18274
18275 /* create row arising from objective cutoff */
18276 if( inclobjcutoff )
18277 {
18278 SCIP_Real rhs;
18279
18280 /* get row data */
18281 assert(lp->looseobjvalinf == 0);
18282 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18283
18284 /* set up indices and coefficients */
18285 matbeg[matrowidx] = matidx;
18286 for( j = 0; j < lp->ncols; ++j )
18287 {
18288 assert( lp->cols[j] != NULL );
18289 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18290 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18291
18292 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18293 {
18294 matinds[matidx] = lp->cols[j]->lppos;
18295 matvals[matidx++] = lp->cols[j]->obj;
18296 assert( matidx <= ntotnonz );
18297 }
18298 }
18299
18300 /* treat rhs */
18301
18302 /* add artificial variable */
18303 if ( ! SCIPsetIsZero(set, rhs) )
18304 {
18305 matinds[matidx] = lp->ncols;
18306 matvals[matidx++] = -rhs;
18307 assert( matidx <= ntotnonz );
18308 }
18309
18310 if( relaxrows )
18311 {
18312 SCIP_Real absrhs = REALABS(rhs);
18313
18314 /* add slack variable */
18315 matvals[matidx] = MAX(1.0, absrhs);
18316 matinds[matidx++] = lp->ncols + 1 + cnt;
18317 assert( matidx <= ntotnonz );
18318 ++cnt;
18319 }
18320 matlhs[matrowidx] = -SCIPsetInfinity(set);
18321 matrhs[matrowidx++] = 0.0;
18322 assert( matrowidx <= ntotrows );
18323 }
18324
18325 /* create rows arising from bounds */
18326 for( j = 0; j < lp->ncols; ++j )
18327 {
18328 SCIP_COL* col;
18329 SCIP_Real abscollb;
18330 SCIP_Real abscolub;
18331
18332 col = lp->cols[j];
18333 assert( col != NULL );
18334 assert( col->lppos == j );
18335
18336 /* fixed variable */
18337 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18338 {
18339 /* set up index of column */
18340 matbeg[matrowidx] = matidx;
18341
18342 matinds[matidx] = j;
18343 matvals[matidx++] = 1.0;
18344 assert( matidx <= ntotnonz );
18345
18346 /* add artificial variable */
18347 if ( ! SCIPsetIsZero(set, col->ub) )
18348 {
18349 matinds[matidx] = lp->ncols;
18350 matvals[matidx++] = -col->ub;
18351 assert( matidx <= ntotnonz );
18352 }
18353
18354 matlhs[matrowidx] = 0.0;
18355 matrhs[matrowidx++] = 0.0;
18356 assert( matrowidx <= ntotrows );
18357
18358 continue;
18359 }
18360
18361 abscollb = REALABS(col->lb);
18362 abscolub = REALABS(col->ub);
18363
18364 /* lower bound */
18365 if ( ! SCIPsetIsInfinity(set, abscollb) )
18366 {
18367 /* set up index of column */
18368 matbeg[matrowidx] = matidx;
18369
18370 matinds[matidx] = j;
18371 matvals[matidx++] = 1.0;
18372 assert( matidx <= ntotnonz );
18373
18374 /* add artificial variable */
18375 if ( ! SCIPsetIsZero(set, col->lb) )
18376 {
18377 matinds[matidx] = lp->ncols;
18378 matvals[matidx++] = -col->lb;
18379 assert( matidx <= ntotnonz );
18380 }
18381
18382 /* add slack variable */
18383 matvals[matidx] = -MAX(1.0, abscollb);
18384 matinds[matidx++] = lp->ncols + 1 + cnt;
18385 assert( matidx <= ntotnonz );
18386 ++cnt;
18387
18388 matlhs[matrowidx] = 0.0;
18389 matrhs[matrowidx++] = SCIPsetInfinity(set);
18390 assert( matrowidx <= ntotrows );
18391 }
18392
18393 /* upper bound */
18394 if ( ! SCIPsetIsInfinity(set, abscolub) )
18395 {
18396 /* set up index of column */
18397 matbeg[matrowidx] = matidx;
18398
18399 matinds[matidx] = j;
18400 matvals[matidx++] = 1.0;
18401 assert( matidx <= ntotnonz );
18402
18403 /* add artificial variable */
18404 if ( ! SCIPsetIsZero(set, col->ub) )
18405 {
18406 matinds[matidx] = lp->ncols;
18407 matvals[matidx++] = -col->ub;
18408 assert( matidx <= ntotnonz );
18409 }
18410
18411 /* add slack variable */
18412 matvals[matidx] = MAX(1.0, abscolub);
18413 matinds[matidx++] = lp->ncols + 1 + cnt;
18414 assert( matidx <= ntotnonz );
18415 ++cnt;
18416
18417 matlhs[matrowidx] = -SCIPsetInfinity(set);
18418 matrhs[matrowidx++] = 0.0;
18419 assert( matrowidx <= ntotrows );
18420 }
18421 }
18422 assert( cnt == nslacks );
18423 assert( matrowidx == ntotrows );
18424
18425 /* add rows */
18426 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18427
18428 SCIPsetFreeBufferArray(set, &matrhs);
18429 SCIPsetFreeBufferArray(set, &matlhs);
18430 SCIPsetFreeBufferArray(set, &matbeg);
18431 SCIPsetFreeBufferArray(set, &matvals);
18432 SCIPsetFreeBufferArray(set, &matinds);
18433
18434#ifdef SCIP_OUTPUT
18435 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18436#endif
18437
18438#ifndef NDEBUG
18439 {
18440 int ncols;
18441 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18442 assert( ncols == nnewcols );
18443 }
18444#endif
18445
18446 /* set time limit */
18447 if( SCIPsetIsInfinity(set, timelimit) )
18448 timelimit = SCIPlpiInfinity(lpi);
18449 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18450
18451 /* check, if parameter is unknown */
18452 if( retcode == SCIP_PARAMETERUNKNOWN )
18453 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18454 else if ( retcode != SCIP_OKAY )
18455 return retcode;
18456
18457 /* set iteration limit */
18458 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18459
18460 /* check, if parameter is unknown */
18461 if( retcode == SCIP_PARAMETERUNKNOWN )
18462 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18463 else if ( retcode != SCIP_OKAY )
18464 return retcode;
18465
18466 /* solve and store point */
18467 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18468 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */
18469
18470#ifndef NDEBUG
18471 if ( SCIPlpiIsIterlimExc(lpi) )
18472 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18473 if ( SCIPlpiIsTimelimExc(lpi) )
18474 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18475#endif
18476
18477 if( SCIPlpiIsOptimal(lpi) )
18478 {
18479 /* get primal solution */
18480 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18481 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18482 alpha = primal[lp->ncols];
18483 assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18484
18485 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18486
18487 /* construct relative interior point */
18488 for( j = 0; j < lp->ncols; ++j )
18489 point[j] = primal[j]/alpha;
18490
18491#ifdef SCIP_DEBUG
18492 /* check whether the point is a relative interior point */
18493 cnt = 0;
18494 if( relaxrows )
18495 {
18496 for( i = 0; i < lp->nrows; ++i )
18497 {
18498 SCIP_ROW* row;
18499 SCIP_COL** rowcols;
18500 SCIP_Real* rowvals;
18501 SCIP_Real lhs;
18502 SCIP_Real rhs;
18503 SCIP_Real sum;
18504 int nnonz;
18505
18506 row = lp->rows[i];
18507 assert( row != NULL );
18508
18509 /* get row data */
18510 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18511 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18512 nnonz = row->nlpcols;
18513 assert( nnonz <= lp->ncols );
18514 rowcols = row->cols;
18515 rowvals = row->vals;
18516
18517 sum = 0.0;
18518 for( j = 0; j < nnonz; ++j )
18519 sum += rowvals[j] * primal[rowcols[j]->lppos];
18520 sum /= alpha;
18521
18522 /* if we have an equation */
18523 if( SCIPsetIsEQ(set, lhs, rhs) )
18524 {
18525 assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18526 }
18527 else
18528 {
18529 /* treat lhs */
18530 if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18531 {
18532 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18533 ++cnt;
18534 }
18535 /* treat rhs */
18536 if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18537 {
18538 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18539 ++cnt;
18540 }
18541 }
18542 }
18543 if( inclobjcutoff )
18544 {
18545 SCIP_Real sum;
18546#ifndef NDEBUG
18547 SCIP_Real rhs;
18548
18549 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18550#endif
18551 sum = 0.0;
18552 for( j = 0; j < lp->ncols; ++j )
18553 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18554 sum /= alpha;
18555
18556 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18557 ++cnt;
18558 }
18559 }
18560 /* check bounds */
18561 for( j = 0; j < lp->ncols; ++j )
18562 {
18563 SCIP_COL* col;
18564#ifndef NDEBUG
18565 SCIP_Real val;
18566#endif
18567
18568 col = lp->cols[j];
18569 assert( col != NULL );
18570#ifndef NDEBUG
18571 val = primal[col->lppos] / alpha;
18572#endif
18573 /* if the variable is not fixed */
18574 if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18575 {
18576 /* treat lb */
18577 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18578 {
18579 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18580 ++cnt;
18581 }
18582 /* treat rhs */
18583 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18584 {
18585 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18586 ++cnt;
18587 }
18588 }
18589 }
18590#endif
18591
18592 /* free */
18593 SCIPsetFreeBufferArray(set, &primal);
18594
18595 *success = TRUE;
18596 }
18597
18598 return SCIP_OKAY;
18599}
18600
18601/** compute relative interior point
18602 *
18603 * We use the approach of@par
18604 * R. Freund, R. Roundy, M. J. Todd@par
18605 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18606 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18607 *
18608 * to compute a relative interior point for the current LP.
18609 *
18610 * Assume the original LP looks as follows:
18611 * \f[
18612 * \begin{array}{rrl}
18613 * \min & c^T x &\\
18614 * & A x & \geq a\\
18615 * & B x & \leq b\\
18616 * & D x & = d.
18617 * \end{array}
18618 * \f]
18619 * Note that bounds should be included in the system.
18620 *
18621 * To find an interior point the following LP does the job:
18622 * \f[
18623 * \begin{array}{rrl}
18624 * \max & 1^T y &\\
18625 * & A x - y - \alpha a & \geq 0\\
18626 * & B x + y - \alpha b & \leq 0\\
18627 * & D x - \alpha d & = 0\\
18628 * & 0 \leq y & \leq 1\\
18629 * & \alpha & \geq 1.
18630 * \end{array}
18631 * \f]
18632 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18633 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18634 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18635 */
18637 SCIP_SET* set, /**< global SCIP settings */
18638 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18639 SCIP_LP* lp, /**< LP data */
18640 SCIP_PROB* prob, /**< problem data */
18641 SCIP_Bool relaxrows, /**< should the rows be relaxed */
18642 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
18643 SCIP_Real timelimit, /**< time limit for LP solver */
18644 int iterlimit, /**< iteration limit for LP solver */
18645 SCIP_Real* point, /**< array to store relative interior point on exit */
18646 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
18647 )
18648{
18649 SCIP_LPI* lpi;
18650 SCIP_RETCODE retcode;
18651
18652 assert(set != NULL);
18653 assert(lp != NULL);
18654 assert(point != NULL);
18655 assert(success != NULL);
18656
18657 *success = FALSE;
18658
18659 /* check time and iteration limits */
18660 if ( timelimit <= 0.0 || iterlimit <= 0 )
18661 return SCIP_OKAY;
18662
18663 /* exit if there are no columns */
18664 assert(lp->nrows >= 0);
18665 assert(lp->ncols >= 0);
18666 if( lp->ncols == 0 )
18667 return SCIP_OKAY;
18668
18669 /* disable objective cutoff if we have none */
18670 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18671 inclobjcutoff = FALSE;
18672
18673 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18674
18675 /* if there are no rows, we return the zero point */
18676 if( lp->nrows == 0 && !inclobjcutoff )
18677 {
18678 /* create zero point */
18679 BMSclearMemoryArray(point, lp->ncols);
18680 *success = TRUE;
18681
18682 return SCIP_OKAY;
18683 }
18684
18685 /* create auxiliary LP */
18686 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18687
18688 /* catch return code and ensure that lpi is freed, anyway */
18689 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18690
18691 SCIP_CALL( SCIPlpiFree(&lpi) );
18692
18693 /* return error, unless we obtained an LP error */
18694 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18695 {
18696 SCIP_CALL( retcode );
18697 }
18698
18699 return SCIP_OKAY;
18700}
18701
18702/** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18703 * based on the changes applied when reducing the problem to the optimal face
18704 *
18705 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18706 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18707 */
18709 SCIP_LP* lp, /**< LP data */
18710 SCIP_SET* set, /**< global SCIP settings */
18711 SCIP_STAT* stat, /**< problem statistics */
18712 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */
18713 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */
18714 )
18715{
18716 assert(lp != NULL);
18717 assert(lp->solved);
18718 assert(lp->flushed);
18719
18720 if( lp->validdegeneracylp != stat->nlps )
18721 {
18722 lp->validdegeneracylp = stat->nlps;
18723
18724 /* if the LP was solved to optimality, we determine the dual degeneracy */
18726 {
18727 SCIP_COL** cols;
18728 SCIP_ROW** rows;
18729 SCIP_COL* col;
18730 int ncols;
18731 int nrows;
18732 int nfixedcols = 0;
18733 int nalreadyfixedcols = 0;
18734 int nfixedrows = 0;
18735#ifndef NDEBUG
18736 int nimplicitfixedrows = 0;
18737#endif
18738 int nineq = 0;
18739 int c;
18740 int r;
18741 int nbasicequalities = 0;
18742
18743 cols = lp->cols;
18744 rows = lp->rows;
18745 ncols = lp->ncols;
18746 nrows = lp->nrows;
18747
18748 /* count number of columns that will be fixed when reducing the LP to the optimal face */
18749 for( c = ncols - 1 ; c >= 0; --c )
18750 {
18751 col = cols[c];
18752 assert(SCIPcolIsInLP(col));
18753
18754 /* column is not basic and not fixed already */
18756 {
18757 /* variable with nonzero reduced costs are fixed */
18758 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18759 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18760 ++nfixedcols;
18761 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18762 ++nalreadyfixedcols;
18763 }
18764 }
18765
18766 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18767 for( r = nrows - 1; r >= 0; --r )
18768 {
18769 SCIP_ROW* row = rows[r];
18770
18771 assert(SCIProwIsInLP(row));
18772
18773 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18774 {
18775 SCIP_Real dualsol = SCIProwGetDualsol(row);
18776
18777 ++nineq;
18778
18780 {
18781 /* rows with nonzero dual solution are turned into equations */
18782 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18783 if( !SCIPsetIsZero(set, dualsol) )
18784 {
18785 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18786 {
18787 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol));
18788 ++nfixedrows;
18789 }
18790 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18791 {
18792 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol));
18793 ++nfixedrows;
18794 }
18795 }
18796#ifndef NDEBUG
18797 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18798 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18799 {
18800 ++nimplicitfixedrows;
18801 }
18802#endif
18803 }
18804 }
18806 ++nbasicequalities;
18807 }
18808 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18809
18810 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18811 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18812 else
18813 lp->degeneracy = 0.0;
18814
18815 if( nrows > 0 )
18816 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18817 else
18818 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18819 assert(lp->degeneracy >= 0);
18820 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18821 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18822 }
18823 else
18824 {
18825 lp->degeneracy = 0.0;
18826 lp->varconsratio = 0.0;
18827 }
18828 }
18829
18830 *degeneracy = lp->degeneracy;
18831 *varconsratio = lp->varconsratio;
18832
18833 return SCIP_OKAY;
18834}
18835
18836/** checks, if absolute difference of values is in range of LP primal feastol */
18838 SCIP_SET* set, /**< global SCIP settings */
18839 SCIP_LP* lp, /**< current LP data */
18840 SCIP_Real val1, /**< first value to be compared */
18841 SCIP_Real val2 /**< second value to be compared */
18842 )
18843{
18844 assert(set != NULL);
18845 assert(lp != NULL);
18846
18847 /* avoid to compare two different infinities; the reason for that is
18848 * that such a comparison can lead to unexpected results */
18849 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18850 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18851 || val1 == val2 ); /*lint !e777*/
18852
18853 return EPSEQ(val1, val2, lp->feastol);
18854}
18855
18856/** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18858 SCIP_SET* set, /**< global SCIP settings */
18859 SCIP_LP* lp, /**< current LP data */
18860 SCIP_Real val1, /**< first value to be compared */
18861 SCIP_Real val2 /**< second value to be compared */
18862 )
18863{
18864 assert(set != NULL);
18865 assert(lp != NULL);
18866
18867 /* avoid to compare two different infinities; the reason for that is
18868 * that such a comparison can lead to unexpected results */
18869 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18870 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18871 || val1 == val2 ); /*lint !e777*/
18872
18873 return EPSLT(val1, val2, lp->feastol);
18874}
18875
18876/** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18878 SCIP_SET* set, /**< global SCIP settings */
18879 SCIP_LP* lp, /**< current LP data */
18880 SCIP_Real val1, /**< first value to be compared */
18881 SCIP_Real val2 /**< second value to be compared */
18882 )
18883{
18884 assert(set != NULL);
18885 assert(lp != NULL);
18886
18887 /* avoid to compare two different infinities; the reason for that is
18888 * that such a comparison can lead to unexpected results */
18889 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18890 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18891 || val1 == val2 ); /*lint !e777*/
18892
18893 return EPSLE(val1, val2, lp->feastol);
18894}
18895
18896/** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18898 SCIP_SET* set, /**< global SCIP settings */
18899 SCIP_LP* lp, /**< current LP data */
18900 SCIP_Real val1, /**< first value to be compared */
18901 SCIP_Real val2 /**< second value to be compared */
18902 )
18903{
18904 assert(set != NULL);
18905 assert(lp != NULL);
18906
18907 /* avoid to compare two different infinities; the reason for that is
18908 * that such a comparison can lead to unexpected results */
18909 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18910 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18911 || val1 == val2 ); /*lint !e777*/
18912
18913 return EPSGT(val1, val2, lp->feastol);
18914}
18915
18916/** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18918 SCIP_SET* set, /**< global SCIP settings */
18919 SCIP_LP* lp, /**< current LP data */
18920 SCIP_Real val1, /**< first value to be compared */
18921 SCIP_Real val2 /**< second value to be compared */
18922 )
18923{
18924 assert(set != NULL);
18925 assert(lp != NULL);
18926
18927 /* avoid to compare two different infinities; the reason for that is
18928 * that such a comparison can lead to unexpected results */
18929 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18930 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18931 || val1 == val2 ); /*lint !e777*/
18932
18933 return EPSGE(val1, val2, lp->feastol);
18934}
18935
18936/** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18938 SCIP_LP* lp, /**< current LP data */
18939 SCIP_Real val /**< value to process */
18940 )
18941{
18942 assert(lp != NULL);
18943
18944 return EPSZ(val, lp->feastol);
18945}
18946
18947/** checks, if value is greater than LP primal feasibility tolerance */
18949 SCIP_LP* lp, /**< current LP data */
18950 SCIP_Real val /**< value to process */
18951 )
18952{
18953 assert(lp != NULL);
18954
18955 return EPSP(val, lp->feastol);
18956}
18957
18958/** checks, if value is lower than -LP primal feasibility tolerance */
18960 SCIP_LP* lp, /**< current LP data */
18961 SCIP_Real val /**< value to process */
18962 )
18963{
18964 assert(lp != NULL);
18965
18966 return EPSN(val, lp->feastol);
18967}
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:6262
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6274
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:1179
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3457
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3377
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_clp.cpp:3824
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3947
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2718
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2478
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_clp.cpp:2995
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:920
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_clp.cpp:2860
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_clp.cpp:3676
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_clp.cpp:4029
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:3861
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:2311
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_clp.cpp:3638
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:2357
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_clp.cpp:1733
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_clp.cpp:2885
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_clp.cpp:2794
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2780
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2034
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_clp.cpp:2433
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3651
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2748
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_clp.cpp:1096
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2516
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_clp.cpp:1669
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:2332
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2549
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2637
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3620
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2764
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3550
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_clp.cpp:3720
const char * SCIPlpiGetSolverName(void)
Definition: lpi_clp.cpp:454
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2496
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3269
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_clp.cpp:992
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3304
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3342
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_clp.cpp:1985
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2651
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2046
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_clp.cpp:1766
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:2378
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:2816
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2584
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:874
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_clp.cpp:1708
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3531
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2530
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1908
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:1833
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_clp.cpp:2949
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_clp.cpp:3217
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:1252
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2675
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_clp.cpp:1447
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_clp.cpp:3923
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:1030
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_clp.cpp:1429
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3417
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 *numerator, 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:17042
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:17126
int SCIPcolGetVarProbindex(SCIP_COL *col)
Definition: lp.c:17095
SCIP_Bool SCIPcolIsRemovable(SCIP_COL *col)
Definition: lp.c:17116
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17075
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:17105
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16986
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17159
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17194
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17184
void SCIPcolSort(SCIP_COL *col)
Definition: lp.c:3433
int SCIPcolGetIndex(SCIP_COL *col)
Definition: lp.c:17085
SCIP_Real SCIPcolGetBestBound(SCIP_COL *col)
Definition: lp.c:17016
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16996
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:17029
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:17006
SCIP_Longint SCIPcolGetStrongbranchNode(SCIP_COL *col)
Definition: lp.c:17206
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:17173
int SCIPcolGetNStrongbranchs(SCIP_COL *col)
Definition: lp.c:17216
int SCIPcolGetAge(SCIP_COL *col)
Definition: lp.c:17226
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17148
int SCIPcolGetLPDepth(SCIP_COL *col)
Definition: lp.c:17137
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17064
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17236
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition: lp.c:17052
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8242
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:17424
void SCIProwSort(SCIP_ROW *row)
Definition: lp.c:6014
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17325
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17444
SCIP_Longint SCIProwGetActiveLPCount(SCIP_ROW *row)
Definition: lp.c:17578
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7786
SCIP_Real SCIProwGetScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7006
int SCIProwGetLPDepth(SCIP_ROW *row)
Definition: lp.c:17545
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7722
SCIP_CONS * SCIProwGetOriginCons(SCIP_ROW *row)
Definition: lp.c:17474
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17246
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17271
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:17524
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17335
int SCIProwGetAge(SCIP_ROW *row)
Definition: lp.c:17404
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:17260
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition: lp.c:17301
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17534
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17434
SCIP_CONSHDLR * SCIProwGetOriginConshdlr(SCIP_ROW *row)
Definition: lp.c:17489
SCIP_Longint SCIProwGetNLPsAfterCreation(SCIP_ROW *row)
Definition: lp.c:17588
void SCIProwLock(SCIP_ROW *row)
Definition: lp.c:5376
SCIP_Bool SCIProwIsRemovable(SCIP_ROW *row)
Definition: lp.c:17454
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17384
SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
Definition: lp.c:17509
void SCIProwUnlock(SCIP_ROW *row)
Definition: lp.c:5391
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition: lp.c:17313
SCIP_DECL_SORTPTRCOMP(SCIProwComp)
Definition: lp.c:951
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:17414
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17358
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17394
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:17567
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17291
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17556
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17345
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17281
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17464
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:17373
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17797
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18198
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17607
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17546
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18152
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3416
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17934
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18096
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17776
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17427
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17618
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18234
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18142
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18086
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3429
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18473
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17944
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18224
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:8177
static void rowCalcIdxsAndVals(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4828
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:15884
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17870
#define debugColPrint(x, y)
Definition: lp.c:160
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:13443
static SCIP_RETCODE lpSetObjlim(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real objlim, SCIP_Bool *success)
Definition: lp.c:2654
static SCIP_RETCODE insertColChgcols(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:3617
SCIP_Real SCIProwGetMaxval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6669
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6922
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3800
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6252
SCIP_Real SCIPcolCalcRedcost(SCIP_COL *col, SCIP_Real *dualsol)
Definition: lp.c:3845
SCIP_RETCODE SCIPlpGetBInvRow(SCIP_LP *lp, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9849
static SCIP_RETCODE lpSetRefactorInterval(SCIP_LP *lp, int refactor, SCIP_Bool *success)
Definition: lp.c:3250
SCIP_Real SCIProwGetNLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6334
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3375
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:11589
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:13385
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5337
SCIP_RETCODE SCIPlpFreeState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10099
SCIP_Real SCIProwGetPseudoFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6448
SCIP_RETCODE SCIPlpUpdateAges(SCIP_LP *lp, SCIP_STAT *stat)
Definition: lp.c:15275
SCIP_RETCODE SCIPlpGetBInvCol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9871
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3755
#define DIVESTACKGROWFACT
Definition: lp.c:16321
static SCIP_RETCODE lpSetTiming(SCIP_LP *lp, SCIP_CLOCKTYPE timing, SCIP_Bool enabled, SCIP_Bool *success)
Definition: lp.c:3163
SCIP_RETCODE SCIPlpInterrupt(SCIP_LP *lp, SCIP_Bool interrupt)
Definition: lp.c:10116
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:10669
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:1986
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:5474
static SCIP_RETCODE lpSetFromscratch(SCIP_LP *lp, SCIP_Bool fromscratch, SCIP_Bool *success)
Definition: lp.c:2833
static void colSortNonLP(SCIP_COL *col)
Definition: lp.c:1003
static SCIP_RETCODE ensureLpicolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:215
SCIP_Real SCIPcolCalcFarkasCoef(SCIP_COL *col, SCIP_Real *dualfarkas)
Definition: lp.c:4028
static void rowMoveCoef(SCIP_ROW *row, int oldpos, int newpos)
Definition: lp.c:1365
static SCIP_RETCODE lpSetFastmip(SCIP_LP *lp, int fastmip, SCIP_Bool *success)
Definition: lp.c:2858
SCIP_RETCODE SCIPlpGetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:10132
static SCIP_RETCODE lpSetRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value, SCIP_Bool *success)
Definition: lp.c:2554
static SCIP_RETCODE lpCopyIntegrality(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8621
static SCIP_RETCODE lpStoreSolVals(SCIP_LP *lp, SCIP_STAT *stat, BMS_BLKMEM *blkmem)
Definition: lp.c:377
void SCIPlpMarkSize(SCIP_LP *lp)
Definition: lp.c:9789
int SCIProwGetNumIntCols(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6733
static SCIP_RETCODE lpSetLPInfo(SCIP_LP *lp, SCIP_Bool lpinfo)
Definition: lp.c:3090
SCIP_RETCODE SCIPlpGetState(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lp.c:10032
void SCIPlpRecalculateObjSqrNorm(SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:17709
static void lpUpdateObjNorms(SCIP_LP *lp, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:3660
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:15608
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition: lp.c:17676
SCIP_Real SCIProwGetSolFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6506
void SCIProwRecalcPseudoActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6393
SCIP_RETCODE SCIProwEnsureSize(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:630
SCIP_Bool SCIPlpIsFeasPositive(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18948
SCIP_Bool SCIPlpIsFeasGT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18897
SCIP_RETCODE SCIPlpIsInfeasibilityProved(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool *proved)
Definition: lp.c:16538
SCIP_Real SCIProwGetRelaxFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6272
SCIP_RETCODE SCIPlpAddCol(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, int depth)
Definition: lp.c:9449
#define MAXNUMTROUBLELPMSGS
Definition: lp.c:11498
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13171
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:10056
static SCIP_RETCODE colDelCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos)
Definition: lp.c:1820
static void colSwapCoefs(SCIP_COL *col, int pos1, int pos2)
Definition: lp.c:1305
static void rowCalcActivityBounds(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6524
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:13732
SCIP_Real SCIPlpGetObjNorm(SCIP_LP *lp)
Definition: lp.c:17740
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6617
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:5979
static SCIP_RETCODE lpSetPresolving(SCIP_LP *lp, SCIP_Bool presolving, SCIP_Bool *success)
Definition: lp.c:2939
SCIP_RETCODE SCIPlpRemoveNewObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15684
SCIP_Bool SCIProwIsLPEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool root)
Definition: lp.c:6847
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6863
static int colSearchCoefPart(SCIP_COL *col, const SCIP_ROW *row, int minpos, int maxpos)
Definition: lp.c:1102
SCIP_RETCODE SCIPlpStartStrongbranch(SCIP_LP *lp)
Definition: lp.c:4178
static int rowSearchCoefPart(SCIP_ROW *row, const SCIP_COL *col, int minpos, int maxpos)
Definition: lp.c:1177
SCIP_Bool SCIPlpDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17890
#define checkRowSumnorm(row)
Definition: lp.c:770
static int colSearchCoef(SCIP_COL *col, const SCIP_ROW *row)
Definition: lp.c:1138
SCIP_RETCODE SCIPlpFlush(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8669
static SCIP_RETCODE rowDelCoefPos(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, int pos)
Definition: lp.c:2185
SCIP_RETCODE SCIPlpUpdateVarLb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:13926
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14337
static void rowSwapCoefs(SCIP_ROW *row, int pos1, int pos2)
Definition: lp.c:1402
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:5638
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:2245
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:1467
static void recomputePseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:822
void SCIPlpSetFeastol(SCIP_LP *lp, SCIP_SET *set, SCIP_Real newfeastol)
Definition: lp.c:10255
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:3511
SCIP_RETCODE rowUnlink(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:2476
#define lpCutoffDisabled(set, prob, lp)
Definition: lp.c:2647
SCIP_RETCODE SCIPlpWrite(SCIP_LP *lp, const char *fname)
Definition: lp.c:16560
int SCIProwGetMaxidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6701
static void colSortLP(SCIP_COL *col)
Definition: lp.c:970
static void adjustLPobjval(SCIP_LP *lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr)
Definition: lp.c:12005
static SCIP_RETCODE lpFlushAddRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8226
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:13345
static int rowSearchCoef(SCIP_ROW *row, const SCIP_COL *col)
Definition: lp.c:1216
SCIP_Real SCIProwGetLPActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6222
void SCIProwMarkNotRemovableLocal(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:7876
static SCIP_RETCODE lpSetPricing(SCIP_LP *lp, SCIP_PRICING pricing)
Definition: lp.c:3025
SCIP_RETCODE SCIPlpUpdateVarLbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb)
Definition: lp.c:13899
static SCIP_RETCODE colRestoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer)
Definition: lp.c:498
SCIP_LPSOLSTAT SCIPlpGetSolstat(SCIP_LP *lp)
Definition: lp.c:13116
SCIP_RETCODE SCIPlpShrinkCols(SCIP_LP *lp, SCIP_SET *set, int newncols)
Definition: lp.c:9632
void SCIPlpStoreRootObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13191
static SCIP_RETCODE lpSetPricingChar(SCIP_LP *lp, char pricingchar)
Definition: lp.c:3048
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:5108
static SCIP_RETCODE colStoreSolVals(SCIP_COL *col, BMS_BLKMEM *blkmem)
Definition: lp.c:471
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:2044
SCIP_ROW ** SCIPlpGetNewrows(SCIP_LP *lp)
Definition: lp.c:17687
static SCIP_RETCODE ensureSoldirectionSize(SCIP_LP *lp, int num)
Definition: lp.c:284
void SCIPlpRecomputeLocalAndGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13215
static SCIP_RETCODE lpSetMarkowitz(SCIP_LP *lp, SCIP_Real threshhold, SCIP_Bool *success)
Definition: lp.c:3138
static void rowUpdateAddLP(SCIP_ROW *row)
Definition: lp.c:8901
static SCIP_RETCODE lpCheckIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value)
Definition: lp.c:2582
SCIP_Real SCIPlpGetColumnObjval(SCIP_LP *lp)
Definition: lp.c:13160
SCIP_RETCODE SCIPlpUpdateAddVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14035
SCIP_RETCODE SCIPlpClear(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9770
SCIP_Bool SCIPlpIsPrimalReliable(SCIP_LP *lp)
Definition: lp.c:17850
static SCIP_RETCODE colEnsureSize(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: lp.c:350
static void rowSortNonLP(SCIP_ROW *row)
Definition: lp.c:1067
void SCIPlpSetIsRelax(SCIP_LP *lp, SCIP_Bool relax)
Definition: lp.c:17817
static SCIP_RETCODE ensureChgcolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:169
SCIP_RETCODE SCIProwDelCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col)
Definition: lp.c:5428
SCIP_RETCODE SCIPlpGetBase(SCIP_LP *lp, int *cstat, int *rstat)
Definition: lp.c:9832
SCIP_Bool SCIPlpIsRelax(SCIP_LP *lp)
Definition: lp.c:17830
#define FEASTOLTIGHTFAC
Definition: lp.c:11586
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:1497
void SCIPcolInvalidateStrongbranchData(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4262
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:12036
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition: lp.c:12404
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 forcedlpsolve, SCIP_Bool *lperror)
Definition: lp.c:12424
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:4297
static SCIP_RETCODE lpCheckRealpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Real value)
Definition: lp.c:2618
SCIP_RETCODE SCIPcolDelCoef(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_ROW *row)
Definition: lp.c:3466
static void rowMerge(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6047
static void colMoveCoef(SCIP_COL *col, int oldpos, int newpos)
Definition: lp.c:1269
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Real *intval)
Definition: lp.c:4898
SCIP_Real SCIPlpGetObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13132
static void computeLPBounds(SCIP_LP *lp, SCIP_SET *set, SCIP_COL *col, SCIP_Real lpiinf, SCIP_Real *lb, SCIP_Real *ub)
Definition: lp.c:7968
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:15923
void SCIProwRecalcLPActivity(SCIP_ROW *row, SCIP_STAT *stat)
Definition: lp.c:6170
static SCIP_Bool isNewValueUnreliable(SCIP_SET *set, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: lp.c:3642
static SCIP_RETCODE provedBound(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool usefarkas, SCIP_Real *bound)
Definition: lp.c:16414
SCIP_Real SCIProwGetMinval(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6685
SCIP_RETCODE SCIPlpEndStrongbranch(SCIP_LP *lp)
Definition: lp.c:4193
SCIP_Longint SCIPcolGetStrongbranchLPAge(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4737
static SCIP_RETCODE lpDelColset(SCIP_LP *lp, SCIP_SET *set, int *coldstat)
Definition: lp.c:15335
static SCIP_RETCODE lpRemoveObsoleteCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15532
SCIP_Real SCIPlpGetRootObjval(SCIP_LP *lp)
Definition: lp.c:17773
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:4938
static SCIP_RETCODE ensureLazycolsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:304
SCIP_Bool SCIPlpIsFeasGE(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18917
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:11560
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:16524
static void checkLazyColArray(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:9579
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3696
static void colUpdateAddLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8861
SCIP_Real SCIProwGetLPSolCutoffDistance(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_LP *lp)
Definition: lp.c:6749
static SCIP_RETCODE lpSetRandomseed(SCIP_LP *lp, int randomseed, SCIP_Bool *success)
Definition: lp.c:3197
static SCIP_RETCODE rowRestoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Longint validlp, SCIP_Bool freebuffer, SCIP_Bool infeasible)
Definition: lp.c:582
static SCIP_RETCODE ensureChgrowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:192
SCIP_Real SCIProwGetSolActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:6464
static SCIP_RETCODE lpSetScaling(SCIP_LP *lp, int scaling, SCIP_Bool *success)
Definition: lp.c:2889
static SCIP_RETCODE colChgCoefPos(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, int pos, SCIP_Real val)
Definition: lp.c:1865
SCIP_RETCODE SCIPlpFree(SCIP_LP **lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:9369
static SCIP_RETCODE lpSetIntpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, int value, SCIP_Bool *success)
Definition: lp.c:2515
void SCIPlpMarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17900
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition: lp.c:17665
SCIP_RETCODE SCIPlpFreeNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lp.c:10176
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:11278
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:5407
static void freeDiveChgSideArrays(SCIP_LP *lp)
Definition: lp.c:9057
SCIP_RETCODE SCIPlpGetBInvARow(SCIP_LP *lp, int r, SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9897
SCIP_LPI * SCIPlpGetLPI(SCIP_LP *lp)
Definition: lp.c:17807
SCIP_Bool SCIPlpIsFeasLT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18857
static SCIP_RETCODE rowStoreSolVals(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_Bool infeasible)
Definition: lp.c:545
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:5526
static SCIP_RETCODE lpUpdateVarColumnProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14127
#define debugRowPrint(x, y)
Definition: lp.c:127
SCIP_RETCODE SCIPlpRemoveRedundantRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15962
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17880
static void rowUpdateDelLP(SCIP_ROW *row)
Definition: lp.c:8975
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17911
SCIP_RETCODE SCIPlpGetBasisInd(SCIP_LP *lp, int *basisind)
Definition: lp.c:9815
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6962
SCIP_RETCODE SCIPlpSetNorms(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_LPINORMS *lpinorms)
Definition: lp.c:10156
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5728
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:18636
#define DIVESTACKINITSIZE
Definition: lp.c:9074
SCIP_RETCODE SCIPlpGetDualDegeneracy(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *degeneracy, SCIP_Real *varconsratio)
Definition: lp.c:18708
static SCIP_RETCODE lpSetBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value, SCIP_Bool *success)
Definition: lp.c:2542
static SCIP_RETCODE ensureColsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:261
static void rowCalcNorms(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:4769
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6806
SCIP_RETCODE SCIPlpGetSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lp.c:14355
static void markRowDeleted(SCIP_ROW *row)
Definition: lp.c:8161
static void rowAddNorms(SCIP_ROW *row, SCIP_SET *set, SCIP_COL *col, SCIP_Real val, SCIP_Bool updateidxvals)
Definition: lp.c:1909
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:13650
static const int nscalars
Definition: lp.c:5742
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:4705
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:3445
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:17934
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:3562
SCIP_Real SCIPlpGetRootLooseObjval(SCIP_LP *lp)
Definition: lp.c:17797
SCIP_RETCODE SCIPlpGetDualfarkas(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool forcedlpsolve, SCIP_Bool *valid)
Definition: lp.c:15059
void SCIProwPrint(SCIP_ROW *row, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:5297
SCIP_RETCODE SCIPlpSetCutoffbound(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob, SCIP_Real cutoffbound)
Definition: lp.c:10200
SCIP_RETCODE SCIPlpRecordOldRowSideDive(SCIP_LP *lp, SCIP_ROW *row, SCIP_SIDETYPE sidetype)
Definition: lp.c:16324
static SCIP_RETCODE lpCleanupCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15746
SCIP_RETCODE SCIPlpMarkFlushed(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8733
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:11415
SCIP_Real SCIPcolGetFeasibility(SCIP_COL *col, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3974
#define checkRowSqrnorm(row)
Definition: lp.c:769
SCIP_RETCODE SCIPlpShrinkRows(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int newnrows)
Definition: lp.c:9704
SCIP_Bool SCIProwIsRedundant(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6638
void SCIPlpStartStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16378
static SCIP_RETCODE lpFlushDelCols(SCIP_LP *lp)
Definition: lp.c:7917
static SCIP_RETCODE lpSetRowrepswitch(SCIP_LP *lp, SCIP_Real rowrepswitch, SCIP_Bool *success)
Definition: lp.c:2964
SCIP_RETCODE SCIPlpGetIterations(SCIP_LP *lp, int *iterations)
Definition: lp.c:15260
static void recomputeLooseObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:780
static void colUpdateDelLP(SCIP_COL *col, SCIP_SET *set)
Definition: lp.c:8936
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:5583
SCIP_RETCODE SCIPlpStartProbing(SCIP_LP *lp)
Definition: lp.c:16348
SCIP_Real SCIPlpGetFeastol(SCIP_LP *lp)
Definition: lp.c:10245
static SCIP_RETCODE lpSetFeastol(SCIP_LP *lp, SCIP_Real feastol, SCIP_Bool *success)
Definition: lp.c:2703
SCIP_Bool SCIProwIsSolEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Bool root)
Definition: lp.c:6906
static SCIP_RETCODE lpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14080
SCIP_RETCODE SCIPlpUpdateDelVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14056
void SCIPlpEndStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16391
SCIP_RETCODE SCIPlpGetBInvACol(SCIP_LP *lp, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lp.c:9922
SCIP_Bool SCIPlpIsFeasZero(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18937
static SCIP_RETCODE lpSetThreads(SCIP_LP *lp, int threads, SCIP_Bool *success)
Definition: lp.c:2914
SCIP_RETCODE SCIPlpRemoveAllObsoletes(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c:15715
static SCIP_RETCODE lpFlushChgCols(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8374
static SCIP_RETCODE lpUpdateVarLooseProved(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14259
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:7831
SCIP_RETCODE colLink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2353
SCIP_RETCODE SCIProwFree(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5257
static SCIP_Real getFiniteLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:906
SCIP_Real SCIPcolGetFarkasValue(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4159
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:10478
static const char * lpalgoName(SCIP_LPALGO lpalgo)
Definition: lp.c:10297
static void coefChanged(SCIP_ROW *row, SCIP_COL *col, SCIP_LP *lp)
Definition: lp.c:1634
static SCIP_RETCODE lpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14214
static void getObjvalDeltaUb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldub, SCIP_Real newub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13612
static SCIP_RETCODE lpRestoreSolVals(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_Longint validlp)
Definition: lp.c:411
static SCIP_RETCODE rowSideChanged(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp, SCIP_SIDETYPE sidetype)
Definition: lp.c:2301
static void rowSortLP(SCIP_ROW *row)
Definition: lp.c:1034
static SCIP_Real colCalcInternalFarkasCoef(SCIP_COL *col)
Definition: lp.c:4080
SCIP_RETCODE colUnlink(SCIP_COL *col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2396
SCIP_RETCODE SCIPlpCreate(SCIP_LP **lp, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *name)
Definition: lp.c:9077
SCIP_Bool SCIPlpDivingRowsChanged(SCIP_LP *lp)
Definition: lp.c:17922
SCIP_RETCODE SCIPlpUpdateVarUbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13967
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:12225
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:9414
static SCIP_RETCODE lpCheckBoolpar(SCIP_LP *lp, SCIP_LPPARAM lpparam, SCIP_Bool value)
Definition: lp.c:2607
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3950
SCIP_RETCODE SCIPlpEndProbing(SCIP_LP *lp)
Definition: lp.c:16363
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:7855
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:1699
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:3277
SCIP_Bool SCIPlpIsRootLPRelax(SCIP_LP *lp)
Definition: lp.c:17763
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:17840
SCIP_RETCODE SCIPlpUpdateVarUb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13994
static SCIP_RETCODE lpSetConditionLimit(SCIP_LP *lp, SCIP_Real condlimit, SCIP_Bool *success)
Definition: lp.c:3113
SCIP_RETCODE SCIPlpUpdateVarObj(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: lp.c:13845
static void lpNumericalTroubleMessage(SCIP_MESSAGEHDLR *messagehdlr, SCIP_SET *set, SCIP_STAT *stat, SCIP_VERBLEVEL verblevel, const char *formatstr,...)
Definition: lp.c:11507
SCIP_Real SCIPcolGetFarkasCoef(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:4133
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14316
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13283
static SCIP_RETCODE reallocDiveChgSideArrays(SCIP_LP *lp, int minsize, SCIP_Real growfact)
Definition: lp.c:9031
SCIP_Bool SCIPlpIsDualReliable(SCIP_LP *lp)
Definition: lp.c:17860
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:9508
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:16575
static void getObjvalDeltaLb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13574
int SCIProwGetMinidx(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6717
static SCIP_Real colCalcInternalRedcost(SCIP_COL *col)
Definition: lp.c:3897
SCIP_RETCODE SCIPlpStartDive(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:16036
SCIP_Bool SCIPlpIsFeasNegative(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18959
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:16142
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:17598
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17608
static SCIP_RETCODE lpSetBarrierconvtol(SCIP_LP *lp, SCIP_Real barrierconvtol, SCIP_Bool *success)
Definition: lp.c:2789
SCIP_RETCODE SCIProwChgRhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real rhs)
Definition: lp.c:5696
SCIP_Real SCIPlpGetRootColumnObjval(SCIP_LP *lp)
Definition: lp.c:17785
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:1525
SCIP_RETCODE SCIPlpGetUnboundedSol(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool *primalfeasible, SCIP_Bool *rayfeasible)
Definition: lp.c:14672
static SCIP_RETCODE lpSetDualfeastol(SCIP_LP *lp, SCIP_Real dualfeastol, SCIP_Bool *success)
Definition: lp.c:2746
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:5745
SCIP_Real SCIPlpGetCutoffbound(SCIP_LP *lp)
Definition: lp.c:10190
SCIP_Bool SCIPlpIsFeasEQ(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18837
static void markColDeleted(SCIP_COL *col)
Definition: lp.c:7895
SCIP_Real SCIProwGetPseudoActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6420
static void checkLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12315
static SCIP_RETCODE lpSetIterationLimit(SCIP_LP *lp, int itlim)
Definition: lp.c:2989
static SCIP_RETCODE ensureRowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:327
static SCIP_Real getFinitePseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:928
static SCIP_RETCODE allocDiveChgSideArrays(SCIP_LP *lp, int initsize)
Definition: lp.c:9009
SCIP_ROW ** SCIPlpGetRows(SCIP_LP *lp)
Definition: lp.c:17645
void SCIPlpSetRootLPIsRelax(SCIP_LP *lp, SCIP_Bool isrelax)
Definition: lp.c:17752
static SCIP_RETCODE ensureLpirowsSize(SCIP_LP *lp, SCIP_SET *set, int num)
Definition: lp.c:238
SCIP_RETCODE SCIProwChgLhs(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real lhs)
Definition: lp.c:5664
void SCIProwForceSort(SCIP_ROW *row, SCIP_SET *set)
Definition: lp.c:6157
void SCIPcolMarkNotRemovableLocal(SCIP_COL *col, SCIP_STAT *stat)
Definition: lp.c:4749
static SCIP_RETCODE updateLazyBounds(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:12342
SCIP_RETCODE rowLink(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:2434
int SCIPlpGetNUnfixedCols(SCIP_LP *lp, SCIP_Real eps)
Definition: lp.c:17618
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6596
#define checkRowObjprod(row)
Definition: lp.c:771
static const SCIP_Real scalars[]
Definition: lp.c:5741
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:4208
SCIP_Bool SCIPlpIsFeasLE(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18877
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition: lp.c:17698
void SCIPlpResetFeastol(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:10280
SCIP_RETCODE SCIPlpGetPrimalRay(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *ray)
Definition: lp.c:14998
#define checkRow(row)
Definition: lp.c:696
void SCIProwDelaySort(SCIP_ROW *row)
Definition: lp.c:6146
static SCIP_RETCODE lpSetSolutionPolishing(SCIP_LP *lp, SCIP_Bool polishing, SCIP_Bool *success)
Definition: lp.c:3227
void SCIPlpInvalidateRootObjval(SCIP_LP *lp)
Definition: lp.c:13204
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17655
static SCIP_RETCODE lpFlushChgRows(SCIP_LP *lp, SCIP_SET *set)
Definition: lp.c:8522
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:10320
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7798
static void recomputeGlbPseudoObjectiveValue(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:864
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:9946
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:4482
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:15813
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13315
static SCIP_RETCODE lpDelRowset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int *rowdstat)
Definition: lp.c:15434
void SCIPlpSetSizeMark(SCIP_LP *lp, int nrows, int ncols)
Definition: lp.c:9801
static int SCIProwGetDiscreteScalarProduct(SCIP_ROW *row1, SCIP_ROW *row2)
Definition: lp.c:7363
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14192
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5350
#define checkLinks(lp)
Definition: lp.c:1625
static SCIP_RETCODE lpFlushAddCols(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: lp.c:8003
void SCIPcolPrint(SCIP_COL *col, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: lp.c:3405
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
SCIP main data structure.
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:13931
internal methods for problem variables