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 nominator;
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, &nominator, &denominator);
5927 if( rational && nominator != 0 )
5928 {
5929 assert(denominator > 0);
5930 gcd = ABS(nominator);
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, nominator, 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, &nominator, &denominator);
5947 if( rational && nominator != 0 )
5948 {
5949 assert(denominator > 0);
5950 gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
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, nominator, 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_Bool chooseBasic;
10787 SCIP_Real* primsol;
10788 SCIP_Real* dualsol;
10789 SCIP_Real* redcost;
10790 int* cstat;
10791 int* rstat;
10792 SCIP_Real* newobj;
10793 SCIP_Real* newlb;
10794 SCIP_Real* newub;
10795 SCIP_Real* newlhs;
10796 SCIP_Real* newrhs;
10797 SCIP_Real* oldlb;
10798 SCIP_Real* oldub;
10799 SCIP_Real* oldlhs;
10800 SCIP_Real* oldrhs;
10801 SCIP_Real* oldobj;
10802 SCIP_Bool* fixedc;
10803 SCIP_Bool* fixedr;
10804 int* indcol;
10805 int* indrow;
10806 int* indallcol;
10807 int* indallrow;
10808 int nDualDeg;
10809 int r, c;
10810 int cntcol;
10811 int cntrow;
10812 int nruns;
10813 int pos;
10814
10815 chooseBasic = set->lp_lexdualbasic;
10816
10817 /* start timing */
10819
10820 /* get all solution information */
10821 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, lp->nlpirows) );
10822 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, lp->nlpicols) );
10823 if( chooseBasic )
10824 {
10825 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10826 }
10827 else
10828 primsol = NULL;
10829
10830 /* get basic and nonbasic information */
10833
10834 /* save bounds, lhs/rhs, and objective */
10840 SCIP_CALL( SCIPlpiGetBounds(lp->lpi, 0, lp->nlpicols-1, oldlb, oldub) );
10841 SCIP_CALL( SCIPlpiGetSides(lp->lpi, 0, lp->nlpirows-1, oldlhs, oldrhs) );
10842 SCIP_CALL( SCIPlpiGetObj(lp->lpi, 0, lp->nlpicols-1, oldobj) );
10843
10844 /* get storage for several arrays */
10848
10852
10853 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallcol, lp->nlpicols) );
10854 SCIP_CALL( SCIPsetAllocBufferArray(set, &indallrow, lp->nlpirows) );
10855
10858
10859 /* initialize: set objective to 0, get fixed variables */
10861 for( c = 0; c < lp->nlpicols; ++c )
10862 {
10863 newobj[c] = 0.0;
10864 indallcol[c] = c;
10865 if( SCIPsetIsFeasEQ(set, oldlb[c], oldub[c]) )
10866 fixedc[c] = TRUE;
10867 else
10868 fixedc[c] = FALSE;
10869 }
10870
10871 /* initialize: get fixed slack variables */
10872 for( r = 0; r < lp->nlpirows; ++r )
10873 {
10874 indallrow[r] = r;
10875 if( SCIPsetIsFeasEQ(set, oldlhs[r], oldrhs[r]) )
10876 fixedr[r] = TRUE;
10877 else
10878 fixedr[r] = FALSE;
10879 }
10880
10881#ifdef DEBUG_LEXDUAL
10882 {
10883 int j;
10884
10885 if( !chooseBasic )
10886 {
10887 assert(primsol == NULL);
10888 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
10889 }
10890 assert(primsol != NULL);
10891 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
10892 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10893
10894 for( j = 0; j < lp->nlpicols; ++j )
10895 {
10896 if( fixedc[j] )
10897 {
10898 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
10899 }
10900 else
10901 {
10902 char type;
10903 switch( (SCIP_BASESTAT) cstat[j] )
10904 {
10906 type = 'l';
10907 break;
10909 type = 'u';
10910 break;
10911 case SCIP_BASESTAT_ZERO:
10912 type = 'z';
10913 break;
10915 type = 'b';
10916 break;
10917 default:
10918 type = '?';
10919 SCIPerrorMessage("unknown base stat %d\n", cstat[j]);
10920 SCIPABORT();
10921 }
10922 SCIPsetDebugMsg(set, "%f (%d) [%c] ", primsol[j], j, type);
10923 }
10924 }
10925 SCIPsetDebugMsg(set, "\n\n");
10926
10927 if( !chooseBasic )
10928 {
10929 SCIPsetFreeBufferArray(set, &primsol);
10930 assert(primsol == NULL);
10931 }
10932 }
10933#endif
10934
10935 /* perform lexicographic rounds */
10936 pos = -1;
10937 nruns = 0;
10938 rounds = 0;
10939 /* SCIP_CALL( lpSetLPInfo(lp, TRUE) ); */
10940 do
10941 {
10942 int oldpos;
10943
10944 /* get current solution */
10945 if( chooseBasic )
10946 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, NULL, redcost) );
10947 else
10948 {
10949 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, NULL, dualsol, NULL, redcost) );
10950 assert(primsol == NULL);
10951 }
10952
10953 /* get current basis */
10954 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
10955
10956 /* check columns: find first candidate (either basic or nonbasic and zero reduced cost) and fix variables */
10957 nDualDeg = 0;
10958 cntcol = 0;
10959 oldpos = pos;
10960 pos = -1;
10961 for( c = 0; c < lp->nlpicols; ++c )
10962 {
10963 if( !fixedc[c] )
10964 {
10965 /* check whether variable is in basis */
10966 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_BASIC )
10967 {
10968 /* store first candidate */
10969 if( pos == -1 && c > oldpos )
10970 {
10971 if( !chooseBasic || !SCIPsetIsIntegral(set, primsol[c]) ) /*lint !e613*/
10972 pos = c;
10973 }
10974 }
10975 else
10976 {
10977 /* reduced cost == 0 -> possible candidate */
10978 if( SCIPsetIsDualfeasZero(set, redcost[c]) )
10979 {
10980 ++nDualDeg;
10981 /* only if we have not yet found a candidate */
10982 if( pos == -1 && c > oldpos )
10983 {
10984 /* if the variable is at its lower bound - fix it, because its value cannot be reduced */
10985 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
10986 {
10987 newlb[cntcol] = oldlb[c];
10988 newub[cntcol] = oldlb[c];
10989 indcol[cntcol++] = c;
10990 fixedc[c] = TRUE;
10991 }
10992 else /* found a non-fixed candidate */
10993 {
10994 if( !chooseBasic )
10995 pos = c;
10996 }
10997 }
10998 }
10999 else
11000 {
11001 /* nonzero reduced cost -> variable can be fixed */
11002 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_LOWER )
11003 {
11004 newlb[cntcol] = oldlb[c];
11005 newub[cntcol] = oldlb[c];
11006 }
11007 else
11008 {
11009 if( (SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_UPPER )
11010 {
11011 newlb[cntcol] = oldub[c];
11012 newub[cntcol] = oldub[c];
11013 }
11014 else
11015 {
11016 assert((SCIP_BASESTAT) cstat[c] == SCIP_BASESTAT_ZERO);
11017 newlb[cntcol] = 0.0;
11018 newub[cntcol] = 0.0;
11019 }
11020 }
11021 indcol[cntcol++] = c;
11022 fixedc[c] = TRUE;
11023 }
11024 }
11025 }
11026 }
11027
11028 /* check rows */
11029 cntrow = 0;
11030 for( r = 0; r < lp->nlpirows; ++r )
11031 {
11032 if( !fixedr[r] )
11033 {
11034 /* consider only nonbasic rows */
11035 if( (SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_BASIC )
11036 {
11037 assert((SCIP_BASESTAT) rstat[r] != SCIP_BASESTAT_ZERO);
11038 if( SCIPsetIsFeasZero(set, dualsol[r]) )
11039 ++nDualDeg;
11040 else
11041 {
11042 if( SCIPsetIsFeasPositive(set, dualsol[r]) )
11043 {
11044 assert(!SCIPsetIsInfinity(set, -oldlhs[r]));
11045 newlhs[cntrow] = oldlhs[r];
11046 newrhs[cntrow] = oldlhs[r];
11047 }
11048 else
11049 {
11050 assert(!SCIPsetIsInfinity(set, oldrhs[r]));
11051 newlhs[cntrow] = oldrhs[r];
11052 newrhs[cntrow] = oldrhs[r];
11053 }
11054 indrow[cntrow++] = r;
11055 fixedr[r] = TRUE;
11056 }
11057 }
11058 }
11059 }
11060
11061 if( nDualDeg > 0 && pos >= 0 )
11062 {
11063 assert(0 <= pos && pos < lp->nlpicols && pos > oldpos);
11064
11065 /* change objective */
11066 if( nruns == 0 )
11067 {
11068 /* set objective to appropriate unit vector for first run */
11069 newobj[pos] = 1.0;
11070 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, newobj) );
11071 }
11072 else
11073 {
11074 /* set obj. coef. to 1 for other runs (ones remain in previous positions) */
11075 SCIP_Real obj = 1.0;
11076 SCIP_CALL( SCIPlpiChgObj(lp->lpi, 1, &pos, &obj) );
11077 }
11078
11079 /* fix variables */
11080 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, cntcol, indcol, newlb, newub) );
11081 SCIP_CALL( SCIPlpiChgSides(lp->lpi, cntrow, indrow, newlhs, newrhs) );
11082
11083 /* solve with primal simplex, because we are primal feasible, but not necessarily dual feasible */
11084 retcode = SCIPlpiSolvePrimal(lp->lpi);
11085 if( retcode == SCIP_LPERROR )
11086 {
11087 *lperror = TRUE;
11088 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") in lex-dual: primal simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11089 }
11090 else
11091 {
11092 SCIP_CALL( retcode );
11093 }
11094 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11095 lexIterations += iterations;
11096
11097#ifdef DEBUG_LEXDUAL
11098 if( iterations > 0 )
11099 {
11100 int j;
11101
11102 if( !chooseBasic )
11103 {
11104 assert(primsol == NULL);
11105 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
11106 }
11107 assert(primsol != NULL);
11108 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
11109
11110 for( j = 0; j < lp->nlpicols; ++j )
11111 {
11112 if( fixedc[j] )
11113 {
11114 SCIPsetDebugMsg(set, "%f (%d) [f] ", primsol[j], j);
11115 }
11116 else
11117 {
11118 char cstart = '[';
11119 char cend = ']';
11120 char type;
11121
11122 if(j == pos)
11123 {
11124 cstart = '*';
11125 cend = '*';
11126 }
11127
11128 switch( (SCIP_BASESTAT) cstat[j] )
11129 {
11131 type = 'l';
11132 break;
11134 type = 'u';
11135 break;
11136 case SCIP_BASESTAT_ZERO:
11137 type = 'z';
11138 break;
11140 type = 'b';
11141 break;
11142 default:
11143 type = '?';
11144 SCIPerrorMessage("unknown base state %d\n", cstat[j]);
11145 SCIPABORT();
11146 }
11147 SCIPsetDebugMsg(set, "%f (%d) %c%c%c ", primsol[j], j, cstart, type, cend);
11148 }
11149 }
11150 SCIPsetDebugMsg(set, "\n\n");
11151
11152 if( !chooseBasic )
11153 {
11154 SCIPsetFreeBufferArray(set, &primsol);
11155 assert(primsol == NULL);
11156 }
11157 }
11158#endif
11159
11160 /* count only as round if iterations have been performed */
11161 if( iterations > 0 )
11162 ++rounds;
11163 ++nruns;
11164 }
11165 }
11166 while( pos >= 0 && nDualDeg > 0 && (set->lp_lexdualmaxrounds == -1 || rounds < set->lp_lexdualmaxrounds) );
11167
11168 /* reset bounds, lhs/rhs, and obj */
11169 SCIP_CALL( SCIPlpiChgBounds(lp->lpi, lp->nlpicols, indallcol, oldlb, oldub) );
11170 SCIP_CALL( SCIPlpiChgSides(lp->lpi, lp->nlpirows, indallrow, oldlhs, oldrhs) );
11171 SCIP_CALL( SCIPlpiChgObj(lp->lpi, lp->nlpicols, indallcol, oldobj) );
11172
11173 /* resolve to update solvers internal data structures - should only produce few pivots - is this needed? */
11174 retcode = SCIPlpiSolveDual(lp->lpi);
11175 if( retcode == SCIP_LPERROR )
11176 {
11177 *lperror = TRUE;
11178 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") dual simplex solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11179 }
11180 else
11181 {
11182 SCIP_CALL( retcode );
11183 }
11184 assert(SCIPlpiIsOptimal(lp->lpi));
11185 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11186 lexIterations += iterations;
11187
11188 /* SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) ); */
11189
11190 /* count number of iterations */
11191 if( totalIterations == 0 && lexIterations > 0 && !lp->strongbranchprobing )
11192 SCIPstatIncrement(stat, set, nlps);
11193
11194 if( lexIterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11195 {
11196 SCIPstatAdd(stat, set, nlpiterations, lexIterations);
11197 if( resolve && !lp->lpifromscratch && stat->nlps > 1 )
11198 {
11199 SCIPstatIncrement(stat, set, nlexdualresolvelps);
11200 SCIPstatAdd(stat, set, nlexdualresolvelpiterations, lexIterations);
11201 }
11202 SCIPstatIncrement(stat, set, nlexduallps);
11203 SCIPstatAdd(stat, set, nlexduallpiterations, lexIterations);
11204
11205 totalIterations += lexIterations;
11206 }
11207
11208 /* free space */
11209 SCIPsetFreeBufferArray(set, &newobj);
11210
11211 SCIPsetFreeBufferArray(set, &fixedr);
11212 SCIPsetFreeBufferArray(set, &fixedc);
11213
11214 SCIPsetFreeBufferArray(set, &indallrow);
11215 SCIPsetFreeBufferArray(set, &indallcol);
11216
11217 SCIPsetFreeBufferArray(set, &indrow);
11218 SCIPsetFreeBufferArray(set, &newrhs);
11219 SCIPsetFreeBufferArray(set, &newlhs);
11220
11221 SCIPsetFreeBufferArray(set, &indcol);
11222 SCIPsetFreeBufferArray(set, &newub);
11223 SCIPsetFreeBufferArray(set, &newlb);
11224
11225 SCIPsetFreeBufferArray(set, &oldobj);
11226 SCIPsetFreeBufferArray(set, &oldrhs);
11227 SCIPsetFreeBufferArray(set, &oldlhs);
11228 SCIPsetFreeBufferArray(set, &oldub);
11229 SCIPsetFreeBufferArray(set, &oldlb);
11230
11231 SCIPsetFreeBufferArray(set, &rstat);
11232 SCIPsetFreeBufferArray(set, &cstat);
11233
11234 SCIPsetFreeBufferArray(set, &redcost);
11235 SCIPsetFreeBufferArray(set, &dualsol);
11236 if( chooseBasic )
11237 SCIPsetFreeBufferArray(set, &primsol);
11238
11239 /* stop timing */
11241
11242 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with lex dual simplex (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", ndivinglps=%" SCIP_LONGINT_FORMAT ")\n",
11243 stat->lpcount, lp->diving || lp->probing, stat->nduallps, stat->ndivinglps);
11244 }
11246 lp->solisbasic = TRUE;
11247
11248 if( totalIterations > 0 && !lp->strongbranchprobing )
11249 SCIPstatIncrement(stat, set, nlps);
11250 else
11251 {
11252 if( keepsol && !(*lperror) )
11253 {
11254 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11255 if( lp->validsollp == stat->lpcount-1 )
11256 lp->validsollp = stat->lpcount;
11257 if( lp->validfarkaslp == stat->lpcount-1 )
11258 lp->validfarkaslp = stat->lpcount;
11259 }
11260 }
11261
11262 return SCIP_OKAY;
11263}
11264
11265/** calls LPI to perform barrier, measures time and counts iterations, gets basis feasibility status */
11266static
11268 SCIP_LP* lp, /**< current LP data */
11269 SCIP_SET* set, /**< global SCIP settings */
11270 SCIP_STAT* stat, /**< problem statistics */
11271 SCIP_Bool crossover, /**< should crossover be performed? */
11272 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11273 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11274 )
11275{
11276 SCIP_Real timedelta;
11277 SCIP_RETCODE retcode;
11278 int iterations;
11279
11280 assert(lp != NULL);
11281 assert(lp->flushed);
11282 assert(set != NULL);
11283 assert(stat != NULL);
11284 assert(lperror != NULL);
11285
11286 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",
11287 stat->lpcount+1, lp->ncols, lp->nrows, crossover ? "/crossover" : "", lp->diving || lp->probing,
11288 stat->nbarrierlps, stat->ndivinglps);
11289
11290 *lperror = FALSE;
11291
11292#ifdef SCIP_MORE_DEBUG /* for debugging: write all root node LP's */
11293 if( stat->nnodes == 1 && !lp->diving && !lp->probing )
11294 {
11295 char fname[SCIP_MAXSTRLEN];
11296 (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "lp%" SCIP_LONGINT_FORMAT "_%" SCIP_LONGINT_FORMAT ".lp", stat->nnodes, stat->lpcount);
11297 SCIP_CALL( SCIPlpWrite(lp, fname) );
11298 SCIPsetDebugMsg(set, "wrote LP to file <%s> (barrier, objlim=%.15g, feastol=%.15g/%.15g, convtol=%.15g, fromscratch=%d, fastmip=%d, scaling=%d, presolving=%d)\n",
11299 fname, lp->lpiobjlim, lp->lpifeastol, lp->lpidualfeastol, lp->lpibarrierconvtol,
11301 }
11302#endif
11303
11304 /* start timing */
11305 if( lp->diving || lp->probing )
11306 {
11307 if( lp->strongbranchprobing )
11309 else
11311
11312 timedelta = 0.0; /* unused for diving or probing */
11313 }
11314 else
11315 {
11317 timedelta = -SCIPclockGetTime(stat->barrierlptime);
11318 }
11319
11320 /* call barrier algorithm */
11321 retcode = SCIPlpiSolveBarrier(lp->lpi, crossover);
11322 if( retcode == SCIP_LPERROR )
11323 {
11324 *lperror = TRUE;
11325 SCIPsetDebugMsg(set, "(node %" SCIP_LONGINT_FORMAT ") barrier solving error in LP %" SCIP_LONGINT_FORMAT "\n", stat->nnodes, stat->nlps);
11326 }
11327 else
11328 {
11329 SCIP_CALL( retcode );
11330 }
11332 lp->solisbasic = crossover;
11333
11334 /* stop timing */
11335 if( lp->diving || lp->probing )
11336 {
11337 if( lp->strongbranchprobing )
11339 else
11341 }
11342 else
11343 {
11345 timedelta += SCIPclockGetTime(stat->barrierlptime);
11346 }
11347
11348 /* count number of iterations */
11349 SCIPstatIncrement(stat, set, lpcount);
11350 SCIP_CALL( SCIPlpGetIterations(lp, &iterations) );
11351 if( iterations > 0 ) /* don't count the resolves after removing unused columns/rows */
11352 {
11353 if( !lp->strongbranchprobing )
11354 {
11355 SCIPstatIncrement(stat, set, nlps);
11356 SCIPstatAdd(stat, set, nlpiterations, iterations);
11357 }
11358 if( lp->diving || lp->probing )
11359 {
11360 if( lp->strongbranchprobing )
11361 {
11362 SCIPstatIncrement(stat, set, nsbdivinglps);
11363 SCIPstatAdd(stat, set, nsbdivinglpiterations, iterations);
11364 }
11365 else
11366 {
11367 SCIPstatUpdate(stat, set, lastdivenode, stat->nnodes);
11368 SCIPstatIncrement(stat, set, ndivinglps);
11369 SCIPstatAdd(stat, set, ndivinglpiterations, iterations);
11370 }
11371 }
11372 else
11373 {
11374 SCIPstatIncrement(stat, set, nbarrierlps);
11375 SCIPstatAdd(stat, set, nbarrierlpiterations, iterations);
11376 }
11377 }
11378 else
11379 {
11380 if ( ! lp->diving && ! lp->probing )
11381 {
11382 SCIPstatIncrement(stat, set, nbarrierzeroitlps);
11383 SCIPstatAdd(stat, set, barrierzeroittime, timedelta);
11384 }
11385
11386 if( keepsol && !(*lperror) )
11387 {
11388 /* the solution didn't change: if the solution was valid before resolve, it is still valid */
11389 if( lp->validsollp == stat->lpcount-1 )
11390 lp->validsollp = stat->lpcount;
11391 if( lp->validfarkaslp == stat->lpcount-1 )
11392 lp->validfarkaslp = stat->lpcount;
11393 }
11394 }
11395
11396 SCIPsetDebugMsg(set, "solved LP %" SCIP_LONGINT_FORMAT " with barrier%s (diving=%d, nduallps=%" SCIP_LONGINT_FORMAT ", nbarrierlps=%" SCIP_LONGINT_FORMAT ")\n",
11397 stat->lpcount, crossover ? "/crossover" : "", lp->diving || lp->probing, stat->nbarrierlps, stat->ndivinglps);
11398
11399 return SCIP_OKAY;
11400}
11401
11402/** solves the LP with the given algorithm */
11403static
11405 SCIP_LP* lp, /**< current LP data */
11406 SCIP_SET* set, /**< global SCIP settings */
11407 SCIP_STAT* stat, /**< problem statistics */
11408 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11409 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11410 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11411 SCIP_Bool instable, /**< is this a resolving call to avoid instable LPs? */
11412 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11413 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11414 )
11415{
11416 SCIP_Real lptimelimit;
11417 SCIP_Bool success;
11418
11419 assert(lp != NULL);
11420 assert(lp->flushed);
11421 assert(lperror != NULL);
11422
11423 /* check if a time limit is set, and set time limit for LP solver accordingly */
11424 lptimelimit = SCIPlpiInfinity(lp->lpi);
11425 if( set->istimelimitfinite )
11426 lptimelimit = set->limit_time - SCIPclockGetTime(stat->solvingtime);
11427
11428 success = FALSE;
11429 if( lptimelimit > 0.0 )
11430 SCIP_CALL( lpSetRealpar(lp, SCIP_LPPAR_LPTILIM, lptimelimit, &success) );
11431
11432 if( lptimelimit <= 0.0 || !success )
11433 {
11434 SCIPsetDebugMsg(set, "time limit of %f seconds could not be set\n", lptimelimit);
11435 *lperror = ((lptimelimit > 0.0) ? TRUE : FALSE);
11436 *timelimit = TRUE;
11437 return SCIP_OKAY;
11438 }
11439 SCIPsetDebugMsg(set, "calling LP algorithm <%s> with a time limit of %g seconds\n", lpalgoName(lpalgo), lptimelimit);
11440
11441 /* call appropriate LP algorithm */
11442 switch( lpalgo )
11443 {
11445 SCIP_CALL( lpPrimalSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11446 break;
11447
11449 /* run dual lexicographic simplex if required */
11450 if( set->lp_lexdualalgo && (!set->lp_lexdualrootonly || stat->maxdepth == 0) && (!set->lp_lexdualstalling || lp->installing) )
11451 {
11452 SCIP_CALL( lpLexDualSimplex(lp, set, stat, resolve, keepsol, lperror) );
11453 }
11454 else
11455 {
11456 SCIP_CALL( lpDualSimplex(lp, set, stat, resolve, keepsol, instable, lperror) );
11457 }
11458 break;
11459
11461 SCIP_CALL( lpBarrier(lp, set, stat, FALSE, keepsol, lperror) );
11462 break;
11463
11465 SCIP_CALL( lpBarrier(lp, set, stat, TRUE, keepsol, lperror) );
11466 break;
11467
11468 default:
11469 SCIPerrorMessage("invalid LP algorithm\n");
11470 return SCIP_INVALIDDATA;
11471 }
11472
11473 if( !(*lperror) )
11474 {
11475 /* check for primal and dual feasibility */
11477
11478 SCIPsetDebugMsg(set, "LP feasibility: primalfeasible=%u, dualfeasible=%u\n", lp->primalfeasible, lp->dualfeasible);
11479 }
11480
11481 return SCIP_OKAY;
11482}
11483
11484/** maximal number of verblevel-high messages about numerical trouble in LP that will be printed
11485 * when this number is reached and display/verblevel is not full, then further messages are suppressed in this run
11486 */
11487#define MAXNUMTROUBLELPMSGS 10
11488
11489/** prints message about numerical trouble
11490 *
11491 * If message has verblevel at most high and display/verblevel is not full,
11492 * then the message is not printed if already MAXNUMTROUBLELPMSGS messages
11493 * were printed before in the current run.
11494 */
11495static
11497 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11498 SCIP_SET* set, /**< global SCIP settings */
11499 SCIP_STAT* stat, /**< problem statistics */
11500 SCIP_VERBLEVEL verblevel, /**< verbosity level of message */
11501 const char* formatstr, /**< message format string */
11502 ... /**< arguments to format string */
11503 )
11504{
11505 va_list ap;
11506
11507 assert(verblevel > SCIP_VERBLEVEL_NONE);
11508 assert(verblevel <= SCIP_VERBLEVEL_FULL);
11509 assert(set->disp_verblevel <= SCIP_VERBLEVEL_FULL);
11510
11511 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL )
11512 {
11513 if( verblevel <= SCIP_VERBLEVEL_HIGH )
11514 {
11515 /* if already max number of messages about numerical trouble in LP on verblevel at most high, then skip message */
11517 return;
11518
11519 /* increase count on messages with verblevel high */
11520 ++stat->nnumtroublelpmsgs ;
11521 }
11522
11523 /* if messages wouldn't be printed, then return already */
11524 if( verblevel > set->disp_verblevel )
11525 return;
11526 }
11527
11528 /* print common begin of message */
11529 SCIPmessagePrintInfo(messagehdlr,
11530 "(node %" SCIP_LONGINT_FORMAT ") numerical troubles in LP %" SCIP_LONGINT_FORMAT " -- ",
11531 stat->nnodes, stat->nlps);
11532
11533 /* print individual part of message */
11534 va_start(ap, formatstr); /*lint !e838*/
11535 SCIPmessageVFPrintInfo(messagehdlr, NULL, formatstr, ap);
11536 va_end(ap);
11537
11538 /* warn that further messages will be suppressed */
11539 if( set->disp_verblevel < SCIP_VERBLEVEL_FULL && verblevel <= SCIP_VERBLEVEL_HIGH && stat->nnumtroublelpmsgs > MAXNUMTROUBLELPMSGS )
11540 {
11541 SCIPmessagePrintInfo(messagehdlr, " -- further messages will be suppressed (use display/verblevel=5 to see all)");
11542 }
11543
11544 /* print closing new-line */
11545 SCIPmessagePrintInfo(messagehdlr, "\n");
11546}
11547
11548static
11550 SCIP_LP* lp, /**< current LP data */
11551 SCIP_SET* set, /**< global SCIP settings */
11552 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11553 SCIP_STAT* stat, /**< problem statistics */
11554 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11555 SCIP_Bool* success /**< was instability successfully ignored */
11556 )
11557{
11558 assert(lp != NULL);
11559 assert(set != NULL);
11560
11561 SCIP_CALL( SCIPlpiIgnoreInstability(lp->lpi, success) );
11562
11563 if( *success )
11564 {
11565 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "ignoring instability of %s", lpalgoName(lpalgo));
11566 if( !set->lp_checkdualfeas )
11567 lp->dualfeasible = TRUE;
11568 if( !set->lp_checkprimfeas )
11569 lp->primalchecked = TRUE;
11570 }
11571
11572 return SCIP_OKAY;
11573}
11574
11575#define FEASTOLTIGHTFAC 0.001
11576/** solves the LP with the given LP algorithm, and tries to resolve numerical problems */
11577static
11579 SCIP_LP* lp, /**< current LP data */
11580 SCIP_SET* set, /**< global SCIP settings */
11581 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
11582 SCIP_STAT* stat, /**< problem statistics */
11583 SCIP_PROB* prob, /**< problem data */
11584 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
11585 int itlim, /**< maximal number of LP iterations to perform in first LP calls (before solving from scratch), or -1 for no limit */
11586 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
11587 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
11588 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
11589 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
11590 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
11591 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
11592 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
11593 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
11594 SCIP_Bool* timelimit, /**< pointer to store whether the time limit was hit */
11595 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
11596 )
11597{
11598 SCIP_Bool success;
11599 SCIP_Bool success2;
11600 SCIP_Bool success3;
11601 SCIP_Bool simplex;
11602 SCIP_Bool itlimishard;
11603 SCIP_Bool usepolishing;
11604
11605 assert(lp != NULL);
11606 assert(lp->flushed);
11607 assert(set != NULL);
11608 assert(stat != NULL);
11609 assert(lperror != NULL);
11610 assert(timelimit != NULL);
11611
11612 *lperror = FALSE;
11613
11614 /**@todo implement solving the LP when loose variables with infinite best bound are present; for this, we need to
11615 * solve with deactivated objective limit in order to determine whether we are (a) infeasible or (b) feasible
11616 * and hence unbounded; to handle case (b) we need to store an array of loose variables with best bound in
11617 * SCIP_LP such that we can return a primal ray
11618 */
11619 if( lp->looseobjvalinf > 0 )
11620 {
11621 SCIPerrorMessage("cannot solve LP when loose variable with infinite best bound is present\n");
11622 return SCIP_ERROR;
11623 }
11624
11625 /* check, whether we solve with a simplex algorithm */
11626 simplex = (lpalgo == SCIP_LPALGO_PRIMALSIMPLEX || lpalgo == SCIP_LPALGO_DUALSIMPLEX);
11627
11628 /* check whether the iteration limit is a hard one */
11629 itlimishard = (itlim == harditlim);
11630
11631 /* check whether solution polishing should be used */
11632 if( lp->lpihaspolishing && (set->lp_solutionpolishing == 2 || (set->lp_solutionpolishing == 1 && stat->nnodes == 1 && !lp->probing)
11633 || (set->lp_solutionpolishing == 3 && ((lp->probing && !lp->strongbranchprobing) || lp->diving))) )
11634 {
11635 usepolishing = TRUE;
11636 if( lp->updateintegrality )
11637 {
11639 }
11640 }
11641 else
11642 usepolishing = FALSE;
11643
11644 /* solve with given settings (usually fast but imprecise) */
11646 {
11647 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound, &success) );
11648 }
11649 else
11650 {
11651 SCIP_CALL( lpSetObjlim(lp, set, prob, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob), &success) );
11652 }
11653 SCIP_CALL( lpSetIterationLimit(lp, itlim) );
11654 SCIP_CALL( lpSetFeastol(lp, tightprimfeastol ? FEASTOLTIGHTFAC * lp->feastol : lp->feastol, &success) );
11656 &success) );
11657 SCIP_CALL( lpSetBarrierconvtol(lp, (tightprimfeastol || tightdualfeastol) ? FEASTOLTIGHTFAC * SCIPsetBarrierconvtol(set)
11658 : SCIPsetBarrierconvtol(set), &success) );
11659 SCIP_CALL( lpSetFromscratch(lp, fromscratch, &success) );
11660 SCIP_CALL( lpSetFastmip(lp, fastmip, &success) );
11661 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11662 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11663 SCIP_CALL( lpSetRowrepswitch(lp, set->lp_rowrepswitch, &success) );
11664 SCIP_CALL( lpSetPricingChar(lp, set->lp_pricing) );
11665 SCIP_CALL( lpSetThreads(lp, set->lp_threads, &success) );
11666 SCIP_CALL( lpSetLPInfo(lp, set->disp_lpinfo) );
11667 SCIP_CALL( lpSetConditionLimit(lp, set->lp_conditionlimit, &success) );
11668 SCIP_CALL( lpSetMarkowitz(lp, set->lp_markowitz, &success) );
11669 SCIP_CALL( lpSetTiming(lp, set->time_clocktype, set->time_enabled, &success) );
11670 SCIP_CALL( lpSetRandomseed(lp, (int) (SCIPsetInitializeRandomSeed(set, (unsigned) set->random_randomseed) % INT_MAX), &success) );
11671 SCIP_CALL( lpSetSolutionPolishing(lp, usepolishing, &success) );
11672 SCIP_CALL( lpSetRefactorInterval(lp, set->lp_refactorinterval, &success) );
11673
11674 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, FALSE, timelimit, lperror) );
11675
11676 /* after the first solve, do not use starting basis, since otherwise the solver will probably think the basis is
11677 * optimal without preforming scaling/change tolerances/presolving */
11678 resolve = FALSE;
11679
11680 /* check for stability; iteration limit exceeded is also treated like instability if the iteration limit is soft */
11681 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11682 return SCIP_OKAY;
11683
11684 if( !set->lp_checkstability )
11685 {
11686 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11687
11688 if( success )
11689 return SCIP_OKAY;
11690 }
11691
11692 /* In the following, whenever the LP iteration limit is exceeded in an LP solving call, we leave out the
11693 * remaining resolving calls with changed settings and go directly to solving the LP from scratch.
11694 */
11695
11696 /* if FASTMIP is turned on, solve again without FASTMIP (starts from the solution of the last LP solving call);
11697 * do this only if the iteration limit was not exceeded in the last LP solving call
11698 */
11699 if( fastmip > 0 && simplex && ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11700 {
11701 SCIP_CALL( lpSetFastmip(lp, 0, &success) );
11702 if( success )
11703 {
11704 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s without FASTMIP", lpalgoName(lpalgo));
11705 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11706
11707 /* check for stability */
11708 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11709 return SCIP_OKAY;
11710
11711 if( !set->lp_checkstability )
11712 {
11713 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11714
11715 if( success )
11716 return SCIP_OKAY;
11717 }
11718 }
11719 }
11720
11721 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11722 * and go directly to solving the LP from scratch
11723 */
11724 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11725 {
11726 /* solve again with opposite scaling setting (starts from the solution of the last LP solving call) */
11727 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11728 if( success )
11729 {
11730 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s scaling",
11731 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11732 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11733
11734 /* check for stability */
11735 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11736 return SCIP_OKAY;
11737
11738 if( !set->lp_checkstability )
11739 {
11740 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11741
11742 if( success )
11743 return SCIP_OKAY;
11744 }
11745
11746 /* reset scaling */
11747 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11748 assert(success);
11749 }
11750 }
11751
11752 /* if the iteration limit was exceeded in the last LP solving call, we leave out the remaining resolving calls with changed settings
11753 * and go directly to solving the LP from scratch */
11754 if( (*lperror) || !SCIPlpiIsIterlimExc(lp->lpi) )
11755 {
11756 /* solve again with opposite presolving setting (starts from the solution of the last LP solving call) */
11757 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11758 if( success )
11759 {
11760 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s %s presolving",
11761 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11762 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11763
11764 /* check for stability */
11765 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11766 return SCIP_OKAY;
11767
11768 if( !set->lp_checkstability )
11769 {
11770 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11771
11772 if( success )
11773 return SCIP_OKAY;
11774 }
11775
11776 /* reset presolving */
11777 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11778 assert(success);
11779 }
11780 }
11781
11782 /* solve again with a tighter feasibility tolerance (starts from the solution of the last LP solving call);
11783 * do this only if the iteration limit was not exceeded in the last LP solving call
11784 */
11785 if( ((simplex && (!tightprimfeastol || !tightdualfeastol)) || (!tightprimfeastol && !tightdualfeastol)) &&
11786 ((*lperror) || !SCIPlpiIsIterlimExc(lp->lpi)) )
11787 {
11788 success = FALSE;
11789 if( !tightprimfeastol )
11790 {
11791 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11792 }
11793
11794 success2 = FALSE;
11795 if( !tightdualfeastol )
11796 {
11798 }
11799
11800 success3 = FALSE;
11801 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11802 {
11804 }
11805
11806 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11807 if( success || success2 || success3 )
11808 {
11809 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again with %s with tighter primal and dual feasibility tolerance",
11810 lpalgoName(lpalgo));
11811 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11812
11813 /* check for stability */
11814 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi) && (itlimishard || !SCIPlpiIsIterlimExc(lp->lpi))) )
11815 return SCIP_OKAY;
11816
11817 if( !set->lp_checkstability )
11818 {
11819 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11820
11821 if( success )
11822 return SCIP_OKAY;
11823 }
11824
11825 /* reset feasibility tolerance */
11826 if( !tightprimfeastol )
11827 {
11828 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11829 }
11830 if( !tightdualfeastol )
11831 {
11833 }
11834 if( !simplex && !tightprimfeastol && !tightdualfeastol )
11835 {
11837 }
11838 }
11839 }
11840
11841 /* all LPs solved after this point are solved from scratch, so set the LP iteration limit to the hard limit;
11842 * the given iteration limit might be a soft one to restrict resolving calls only */
11843 SCIP_CALL( lpSetIterationLimit(lp, harditlim) );
11844
11845 /* if not already done, solve again from scratch */
11846 if( !fromscratch && simplex )
11847 {
11848 SCIP_CALL( lpSetFromscratch(lp, TRUE, &success) );
11849 if( success )
11850 {
11851 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11852 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11853
11854 /* check for stability */
11855 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11856 return SCIP_OKAY;
11857
11858 if( !set->lp_checkstability )
11859 {
11860 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11861
11862 if( success )
11863 return SCIP_OKAY;
11864 }
11865 }
11866 }
11867
11868 /* solve again, use other simplex this time */
11869 if( simplex )
11870 {
11872 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s", lpalgoName(lpalgo));
11873 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11874
11875 /* check for stability */
11876 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11877 return SCIP_OKAY;
11878
11879 if( !set->lp_checkstability )
11880 {
11881 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11882
11883 if( success )
11884 return SCIP_OKAY;
11885 }
11886
11887 /* solve again with opposite scaling and other simplex */
11888 SCIP_CALL( lpSetScaling(lp, (scaling > 0) ? 0 : 1, &success) );
11889 if( success )
11890 {
11891 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s scaling",
11892 lpalgoName(lpalgo), (scaling == 0) ? "with" : "without");
11893 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11894
11895 /* check for stability */
11896 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11897 return SCIP_OKAY;
11898
11899 if( !set->lp_checkstability )
11900 {
11901 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11902
11903 if( success )
11904 return SCIP_OKAY;
11905 }
11906
11907 /* reset scaling */
11908 SCIP_CALL( lpSetScaling(lp, scaling, &success) );
11909 assert(success);
11910 }
11911
11912 /* solve again with opposite presolving and other simplex */
11913 SCIP_CALL( lpSetPresolving(lp, !set->lp_presolving, &success) );
11914 if( success )
11915 {
11916 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s %s presolving",
11917 lpalgoName(lpalgo), !set->lp_presolving ? "with" : "without");
11918 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11919
11920 /* check for stability */
11921 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11922 return SCIP_OKAY;
11923
11924 if( !set->lp_checkstability )
11925 {
11926 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11927
11928 if( success )
11929 return SCIP_OKAY;
11930 }
11931
11932 /* reset presolving */
11933 SCIP_CALL( lpSetPresolving(lp, set->lp_presolving, &success) );
11934 assert(success);
11935 }
11936
11937 /* solve again with tighter feasibility tolerance, use other simplex this time */
11938 if( !tightprimfeastol || !tightdualfeastol )
11939 {
11940 success = FALSE;
11941 if( !tightprimfeastol )
11942 {
11943 SCIP_CALL( lpSetFeastol(lp, FEASTOLTIGHTFAC * lp->feastol, &success) );
11944 }
11945
11946 success2 = FALSE;
11947 if( !tightdualfeastol )
11948 {
11950 }
11951
11952 /* only resolve if at least one of the parameters was actually changed in the LP solver */
11953 if( success || success2 )
11954 {
11955 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "solve again from scratch with %s with tighter feasibility tolerance",
11956 lpalgoName(lpalgo));
11957 SCIP_CALL( lpAlgorithm(lp, set, stat, lpalgo, resolve, keepsol, TRUE, timelimit, lperror) );
11958
11959 /* check for stability */
11960 if( *timelimit || (!(*lperror) && SCIPlpiIsStable(lp->lpi)) )
11961 return SCIP_OKAY;
11962
11963 if( !set->lp_checkstability )
11964 {
11965 SCIP_CALL( ignoreInstability(lp, set, messagehdlr, stat, lpalgo, &success) );
11966
11967 if( success )
11968 return SCIP_OKAY;
11969 }
11970
11971 /* reset feasibility tolerance */
11972 if( !tightprimfeastol )
11973 {
11974 SCIP_CALL( lpSetFeastol(lp, lp->feastol, &success) );
11975 }
11976 if( !tightdualfeastol )
11977 {
11979 }
11980 SCIP_UNUSED(success);
11981 }
11982 }
11983 }
11984
11985 /* nothing worked -- exit with an LPERROR */
11986 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
11987 *lperror = TRUE;
11988
11989 return SCIP_OKAY;
11990}
11991
11992/** adjust the LP objective value if it is greater/less than +/- SCIPsetInfinity() */
11993static
11995 SCIP_LP* lp, /**< current LP data */
11996 SCIP_SET* set, /**< global SCIP settings */
11997 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
11998 )
11999{
12000 assert(lp != NULL);
12001 assert(set != NULL);
12002
12003 if( SCIPsetIsInfinity(set, lp->lpobjval) && lp->lpobjval != SCIPsetInfinity(set) ) /*lint !e777*/
12004 {
12005 if( !lp->adjustlpval && messagehdlr != NULL )
12006 {
12007 SCIPmessagePrintWarning(messagehdlr, "LP solution value is above SCIP's infinity value\n");
12008 lp->adjustlpval = TRUE;
12009 }
12011 }
12012 else if( SCIPsetIsInfinity(set, -lp->lpobjval) && lp->lpobjval != -SCIPsetInfinity(set) ) /*lint !e777*/
12013 {
12014 if( !lp->adjustlpval && messagehdlr != NULL )
12015 {
12016 SCIPmessagePrintWarning(messagehdlr, "LP solution value is below SCIP's -infinity value\n");
12017 lp->adjustlpval = TRUE;
12018 }
12020 }
12021}
12022
12023/** solves the LP with the given algorithm and evaluates return status */
12024static
12026 SCIP_LP* lp, /**< current LP data */
12027 SCIP_SET* set, /**< global SCIP settings */
12028 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12029 SCIP_STAT* stat, /**< problem statistics */
12030 SCIP_PROB* prob, /**< problem data */
12031 SCIP_LPALGO lpalgo, /**< LP algorithm that should be applied */
12032 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12033 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12034 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12035 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12036 SCIP_Bool resolve, /**< is this a resolving call (starting with feasible basis)? */
12037 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12038 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12039 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12040 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12041 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12042 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12043 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12044 )
12045{
12046 SCIP_Bool solvedprimal;
12047 SCIP_Bool solveddual;
12048 SCIP_Bool timelimit;
12049 int itlim;
12050
12051 assert(lp != NULL);
12052 assert(lp->flushed);
12053 assert(set != NULL);
12054 assert(stat != NULL);
12055 assert(lperror != NULL);
12056
12057 checkLinks(lp);
12058
12059 solvedprimal = FALSE;
12060 solveddual = FALSE;
12061 timelimit = FALSE;
12062
12063 /* select the basic iteration limit depending on whether this is a resolving call or not */
12064 itlim = ( resolve ? resolveitlim : harditlim );
12065
12066 SOLVEAGAIN:
12067 /* call simplex */
12068 SCIP_CALL( lpSolveStable(lp, set, messagehdlr, stat, prob, lpalgo, itlim, harditlim, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch,
12069 scaling, keepsol, &timelimit, lperror) );
12070 resolve = FALSE; /* only the first solve should be counted as resolving call */
12071 solvedprimal = solvedprimal || (lp->lastlpalgo == SCIP_LPALGO_PRIMALSIMPLEX);
12072 solveddual = solveddual || (lp->lastlpalgo == SCIP_LPALGO_DUALSIMPLEX);
12073
12074 /* check, if an error occurred */
12075 if( *lperror )
12076 {
12077 SCIPsetDebugMsg(set, "unresolved error while solving LP with %s\n", lpalgoName(lp->lastlpalgo));
12078 lp->solved = FALSE;
12080 return SCIP_OKAY;
12081 }
12082
12083 /* check, if a time limit was exceeded */
12084 if( timelimit )
12085 {
12086 SCIPsetDebugMsg(set, "time limit exceeded before solving LP\n");
12087 lp->solved = TRUE;
12090 return SCIP_OKAY;
12091 }
12092
12093 /* only one should return true */
12096
12097 /* evaluate solution status */
12098 if( SCIPlpiIsOptimal(lp->lpi) )
12099 {
12100 assert(lp->primalfeasible);
12101 assert(lp->dualfeasible);
12103 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12104 adjustLPobjval(lp, set, messagehdlr);
12105
12107 {
12108 /* the solver may return the optimal value, even if this is greater or equal than the upper bound */
12109 SCIPsetDebugMsg(set, "optimal solution %.15g exceeds objective limit %.15g\n", lp->lpobjval, lp->lpiobjlim);
12112 }
12113 /* if we did not disable the cutoff bound in the LP solver, the LP solution status should be objective limit
12114 * reached if the LP objective value is greater than the cutoff bound
12115 */
12116 assert(lpCutoffDisabled(set, prob, lp) || lp->lpsolstat == SCIP_LPSOLSTAT_OBJLIMIT
12118 || SCIPsetIsLE(set, lp->lpobjval + getFiniteLooseObjval(lp, set, prob), lp->cutoffbound));
12119 }
12120 else if( SCIPlpiIsObjlimExc(lp->lpi) )
12121 {
12122 assert(!lpCutoffDisabled(set, prob, lp));
12123
12124#ifndef NDEBUG
12125 /* the LP solution objective should exceed the limit in this case; if this assert is triggered, it typically means
12126 * that the LP interface method SCIPlpiIsStable() lacks a check for this event and incorrectly returned TRUE */
12127 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12128 assert(!set->lp_checkstability || SCIPsetIsRelGE(set, lp->lpobjval, lp->lpiobjlim));
12129#endif
12130
12133 }
12134 else if( SCIPlpiIsPrimalInfeasible(lp->lpi) )
12135 {
12136 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12137 if( needdualray && !SCIPlpiHasDualRay(lp->lpi) && !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX )
12138 {
12139 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12140 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12141 goto SOLVEAGAIN;
12142 }
12145 }
12146 else if( SCIPlpiExistsPrimalRay(lp->lpi) )
12147 {
12148 /* because of numerical instability lpalgo != lp->lastlpalgo might happen - hence, we have to check both */
12149 if( needprimalray && !SCIPlpiIsPrimalUnbounded(lp->lpi) && !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX )
12150 {
12151 /* unboundedness includes that the primal is feasible: ensure a primal solution here */
12154 goto SOLVEAGAIN;
12155 }
12158 }
12159 else if( SCIPlpiIsIterlimExc(lp->lpi) )
12160 {
12161 SCIP_CALL( SCIPlpiGetObjval(lp->lpi, &lp->lpobjval) );
12162
12163 /* The lpobjval might be infinite, e.g. if the LP solver was not able to produce a valid bound while reaching the
12164 iteration limit. In this case, we avoid the warning in adjustLPobjval() by setting the messagehdlr to NULL. */
12165 if ( REALABS(lp->lpobjval) == SCIPlpiInfinity(lp->lpi) ) /*lint !e777*/
12166 adjustLPobjval(lp, set, NULL);
12167 else
12168 adjustLPobjval(lp, set, messagehdlr);
12169
12171 }
12172 else if( SCIPlpiIsTimelimExc(lp->lpi) )
12173 {
12176 }
12177 else if( !solveddual && lpalgo != SCIP_LPALGO_DUALSIMPLEX)
12178 {
12179 assert(lp->lastlpalgo != SCIP_LPALGO_DUALSIMPLEX);
12180 lpalgo = SCIP_LPALGO_DUALSIMPLEX;
12181 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12182 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12183 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12184 goto SOLVEAGAIN;
12185 }
12186 else if( !solvedprimal && lpalgo != SCIP_LPALGO_PRIMALSIMPLEX)
12187 {
12190 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12191 "(node %" SCIP_LONGINT_FORMAT ") solution status of LP %" SCIP_LONGINT_FORMAT " could not be proven (internal status:%d) -- solve again with %s\n",
12192 stat->nnodes, stat->nlps, SCIPlpiGetInternalStatus(lp->lpi), lpalgoName(lpalgo));
12193 goto SOLVEAGAIN;
12194 }
12195 else
12196 {
12197 SCIPerrorMessage("(node %" SCIP_LONGINT_FORMAT ") error or unknown return status of %s in LP %" SCIP_LONGINT_FORMAT " (internal status: %d)\n",
12198 stat->nnodes, lpalgoName(lp->lastlpalgo), stat->nlps, SCIPlpiGetInternalStatus(lp->lpi));
12200 return SCIP_LPERROR;
12201 }
12202
12203 lp->solved = TRUE;
12204
12205 SCIPsetDebugMsg(set, "solving LP with %s returned solstat=%d (internal status: %d, primalfeasible=%u, dualfeasible=%u)\n",
12208
12209 return SCIP_OKAY;
12210}
12211
12212/** flushes the LP and solves it with the primal or dual simplex algorithm, depending on the current basis feasibility */
12213static
12215 SCIP_LP* lp, /**< current LP data */
12216 BMS_BLKMEM* blkmem, /**< block memory */
12217 SCIP_SET* set, /**< global SCIP settings */
12218 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12219 SCIP_STAT* stat, /**< problem statistics */
12220 SCIP_PROB* prob, /**< problem data */
12221 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12222 int resolveitlim, /**< maximal number of LP iterations to perform in resolving calls, or -1 for no limit */
12223 int harditlim, /**< maximal number of LP iterations to perform (hard limit for all LP calls), or -1 for no limit */
12224 SCIP_Bool needprimalray, /**< if the LP is unbounded, do we need a primal ray? */
12225 SCIP_Bool needdualray, /**< if the LP is infeasible, do we need a dual ray? */
12226 int fastmip, /**< which FASTMIP setting of LP solver should be used? */
12227 SCIP_Bool tightprimfeastol, /**< should a tighter primal feasibility tolerance be used? */
12228 SCIP_Bool tightdualfeastol, /**< should a tighter dual feasibility tolerance be used? */
12229 SCIP_Bool fromscratch, /**< should the LP be solved from scratch without using current basis? */
12230 int scaling, /**< LP scaling (0: none, 1: normal, 2: aggressive) */
12231 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12232 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12233 )
12234{
12235 SCIP_Bool resolve;
12236 char algo;
12237
12238 assert(lp != NULL);
12239 assert(set != NULL);
12240 assert(lperror != NULL);
12241
12242 /* flush changes to the LP solver */
12243 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12244 fastmip = ((!lp->flushaddedcols && !lp->flushdeletedcols) ? fastmip : 0); /* turn off FASTMIP if columns were changed */
12245
12246 /* select LP algorithm to apply */
12247 resolve = lp->solisbasic && (lp->dualfeasible || lp->primalfeasible) && !fromscratch;
12248 algo = resolve ? set->lp_resolvealgorithm : set->lp_initalgorithm;
12249
12250 switch( algo )
12251 {
12252 case 's':
12253 /* select simplex method */
12254 if( lp->dualfeasible || !lp->primalfeasible )
12255 {
12256 SCIPsetDebugMsg(set, "solving dual LP\n");
12257 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12258 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12259 }
12260 else
12261 {
12262 SCIPsetDebugMsg(set, "solving primal LP\n");
12263 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12264 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12265 }
12266 break;
12267
12268 case 'p':
12269 SCIPsetDebugMsg(set, "solving primal LP\n");
12270 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_PRIMALSIMPLEX, resolveitlim, harditlim, needprimalray,
12271 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12272 break;
12273
12274 case 'd':
12275 SCIPsetDebugMsg(set, "solving dual LP\n");
12276 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, resolveitlim, harditlim, needprimalray,
12277 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12278 break;
12279
12280 case 'b':
12281 SCIPsetDebugMsg(set, "solving barrier LP\n");
12282 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIER, resolveitlim, harditlim, needprimalray,
12283 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12284 break;
12285
12286 case 'c':
12287 SCIPsetDebugMsg(set, "solving barrier LP with crossover\n");
12288 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_BARRIERCROSSOVER, resolveitlim, harditlim, needprimalray,
12289 needdualray, resolve, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12290 break;
12291
12292 default:
12293 SCIPerrorMessage("invalid parameter setting <%c> for LP algorithm\n", algo);
12295 }
12296 assert(!(*lperror) || !lp->solved);
12297
12298 return SCIP_OKAY;
12299}
12300
12301#ifndef NDEBUG
12302/** checks if the lazy bounds are valid */
12303static
12305 SCIP_LP* lp, /**< LP data */
12306 SCIP_SET* set /**< global SCIP settings */
12307 )
12308{
12309 SCIP_COL* col;
12310 int c;
12311
12312 assert(lp->flushed);
12313
12314 for( c = 0; c < lp->nlazycols; ++c )
12315 {
12316 col = lp->lazycols[c];
12317
12318 /* in case lazy bounds are given, check that the primal solution satisfies them */
12319 assert(SCIPsetIsInfinity(set, -col->lazylb) || SCIPsetIsFeasGE(set, col->primsol, col->lazylb));
12320 assert(SCIPsetIsInfinity(set, col->lazyub) || SCIPsetIsFeasLE(set, col->primsol, col->lazyub));
12321 }
12322}
12323#else
12324#define checkLazyBounds(lp, set) /**/
12325#endif
12326
12327/** marks all lazy columns to be changed; this is needed for reloading/removing bounds of these columns before and after
12328 * diving
12329 */
12330static
12332 SCIP_LP* lp, /**< LP data */
12333 SCIP_SET* set /**< global SCIP settings */
12334 )
12335{
12336 SCIP_COL* col;
12337 int c;
12338
12339 assert(lp->nlazycols > 0);
12340
12341 /* return, if we are in diving, and bounds were already applied
12342 * or if we are not in diving and bounds were not applied
12343 */
12344 if( lp->diving == lp->divinglazyapplied )
12345 return SCIP_OKAY;
12346
12347 SCIPsetDebugMsg(set, "mark all lazy columns as changed in order to reload bounds (diving=%u, applied=%u)\n",
12348 lp->diving, lp->divinglazyapplied);
12349
12350 for( c = 0; c < lp->nlazycols; ++c )
12351 {
12352 col = lp->lazycols[c];
12353
12354 /* if the column has a lazy lower bound, mark its lower bounds as changed */
12355 if( !SCIPsetIsInfinity(set, -col->lazylb) )
12356 {
12357 assert((!(lp->divinglazyapplied)) || (col->flushedlb == col->lb) || col->lbchanged); /*lint !e777*/
12358 assert(lp->divinglazyapplied || SCIPsetIsGT(set, col->lb, col->lazylb)
12359 || (col->flushedlb == -SCIPlpiInfinity(lp->lpi)) || col->lbchanged); /*lint !e777*/
12360
12361 /* insert column in the chgcols list (if not already there) */
12362 SCIP_CALL( insertColChgcols(col, set, lp) );
12363
12364 /* mark bound change in the column */
12365 col->lbchanged = TRUE;
12366 }
12367
12368 /* if the column has a lazy upper bound, mark its upper bounds as changed */
12369 if( !SCIPsetIsInfinity(set, col->lazyub) )
12370 {
12371 assert((!(lp->divinglazyapplied)) || (col->flushedub == col->ub) || col->ubchanged); /*lint !e777*/
12372 assert(lp->divinglazyapplied || SCIPsetIsLT(set, col->ub, col->lazyub)
12373 || (col->flushedub == SCIPlpiInfinity(lp->lpi)) || col->ubchanged); /*lint !e777*/
12374
12375 /* insert column in the chgcols list (if not already there) */
12376 SCIP_CALL( insertColChgcols(col, set, lp) );
12377
12378 /* mark bound change in the column */
12379 col->ubchanged = TRUE;
12380 }
12381 }
12382
12383 /* update lp->divinglazyapplied flag: if we are in diving mode, we just applied the lazy bounds,
12384 * if not, we just removed them
12385 */
12386 lp->divinglazyapplied = lp->diving;
12387
12388 return SCIP_OKAY;
12389}
12390
12391/** returns the iteration limit for an LP resolving call */
12392static
12394 SCIP_SET* set, /**< global SCIP settings */
12395 SCIP_STAT* stat, /**< dynamic problem statistics */
12396 int itlim /**< hard iteration limit */
12397 )
12398{
12399 /* no limit set or average not yet reliable */
12400 if( (set->lp_resolveiterfac == -1) || stat->nlps - stat->nrootlps < 5 )
12401 return itlim;
12402 /* set itlim to INT_MAX if it is -1 to reduce the number of cases to be regarded in the following */
12403 if( itlim == -1 )
12404 itlim = INT_MAX;
12405 /* return resolveiterfac * average iteration number per call after root, but at least resolveitermin and at most the hard iteration limit */
12406 return (int) MIN(itlim, MAX(set->lp_resolveitermin, \
12407 (set->lp_resolveiterfac * (stat->nlpiterations - stat->nrootlpiterations) / (SCIP_Real)(stat->nlps - stat->nrootlps))));
12408}
12409
12410
12411
12412/** solves the LP with simplex algorithm, and copy the solution into the column's data */
12414 SCIP_LP* lp, /**< LP data */
12415 SCIP_SET* set, /**< global SCIP settings */
12416 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
12417 BMS_BLKMEM* blkmem, /**< block memory buffers */
12418 SCIP_STAT* stat, /**< problem statistics */
12419 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
12420 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
12421 SCIP_PROB* prob, /**< problem data */
12422 SCIP_Longint itlim, /**< maximal number of LP iterations to perform, or -1 for no limit */
12423 SCIP_Bool limitresolveiters, /**< should LP iterations for resolving calls be limited?
12424 * (limit is computed within the method w.r.t. the average LP iterations) */
12425 SCIP_Bool aging, /**< should aging and removal of obsolete cols/rows be applied? */
12426 SCIP_Bool keepsol, /**< should the old LP solution be kept if no iterations were performed? */
12427 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
12428 SCIP_Bool* lperror /**< pointer to store whether an unresolved LP error occurred */
12429 )
12430{
12431 SCIP_RETCODE retcode;
12432 SCIP_Bool needprimalray;
12433 SCIP_Bool needdualray;
12434 int harditlim;
12435 int resolveitlim;
12436
12437 assert(lp != NULL);
12438 assert(prob != NULL);
12439 assert(prob->nvars >= lp->ncols);
12440 assert(lperror != NULL);
12441
12442 retcode = SCIP_OKAY;
12443 *lperror = FALSE;
12444
12445 if( lp->flushed && lp->solved )
12446 {
12447 SCIPsetDebugMsg(set, "skipping LP solve: already flushed and solved)\n");
12448 return SCIP_OKAY;
12449 }
12450
12451 SCIPsetDebugMsg(set, "solving LP: %d rows, %d cols, primalfeasible=%u, dualfeasible=%u, solved=%u, diving=%u, probing=%u, cutoffbnd=%g\n",
12452 lp->nrows, lp->ncols, lp->primalfeasible, lp->dualfeasible, lp->solved, lp->diving, lp->probing, lp->cutoffbound);
12453
12454 /* check whether we need a proof of unboundedness or infeasibility by a primal or dual ray */
12455 needprimalray = TRUE;
12456 needdualray = (!SCIPprobAllColsInLP(prob, set, lp) || set->misc_exactsolve
12457 || (set->conf_enable && set->conf_useinflp != 'o'));
12458
12459 /* compute the limit for the number of LP resolving iterations, if needed (i.e. if limitresolveiters == TRUE) */
12460 harditlim = (int) MIN(itlim, INT_MAX);
12461 resolveitlim = ( limitresolveiters ? lpGetResolveItlim(set, stat, harditlim) : harditlim );
12462 assert(harditlim == -1 || (resolveitlim <= harditlim));
12463
12464 /* if there are lazy bounds, check whether the bounds should explicitly be put into the LP (diving was started)
12465 * or removed from the LP (diving was ended)
12466 */
12467 if( lp->nlazycols > 0 )
12468 {
12469 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
12470 * first resolve LP?
12471 */
12473 assert(lp->diving == lp->divinglazyapplied);
12474 }
12475
12476 /* flush changes to the LP solver */
12477 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
12478 assert(lp->flushed);
12479
12480 /* 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
12481 * to run again anyway, since there seems to be some time left / the time limit was increased
12482 */
12483 if( !lp->solved || (lp->lpsolstat == SCIP_LPSOLSTAT_TIMELIMIT && stat->status != SCIP_STATUS_TIMELIMIT) )
12484 {
12485 SCIP_Bool* primalfeaspointer;
12486 SCIP_Bool* dualfeaspointer;
12487 SCIP_Bool primalfeasible;
12488 SCIP_Bool dualfeasible;
12489 SCIP_Bool farkasvalid;
12490 SCIP_Bool rayfeasible;
12491 SCIP_Bool tightprimfeastol;
12492 SCIP_Bool tightdualfeastol;
12493 SCIP_Bool fromscratch;
12494 SCIP_Bool wasfromscratch;
12495 int scaling;
12496 SCIP_Longint oldnlps;
12497 int fastmip;
12498
12499 /* set initial LP solver settings */
12500 fastmip = ((lp->lpihasfastmip && !lp->flushaddedcols && !lp->flushdeletedcols && stat->nnodes > 1) ? set->lp_fastmip : 0);
12501 tightprimfeastol = FALSE;
12502 tightdualfeastol = FALSE;
12503 fromscratch = FALSE;
12504 primalfeasible = FALSE;
12505 dualfeasible = FALSE;
12506 wasfromscratch = (stat->nlps == 0);
12507 scaling = set->lp_scaling;
12508
12509 SOLVEAGAIN:
12510 /* solve the LP */
12511 oldnlps = stat->nlps;
12512 SCIP_CALL( lpFlushAndSolve(lp, blkmem, set, messagehdlr, stat, prob, eventqueue, resolveitlim, harditlim, needprimalray,
12513 needdualray, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12514 SCIPsetDebugMsg(set, "lpFlushAndSolve() returned solstat %d (error=%u)\n", SCIPlpGetSolstat(lp), *lperror);
12515 assert(!(*lperror) || !lp->solved);
12516
12517 /* check for error */
12518 if( *lperror )
12519 {
12520 retcode = SCIP_OKAY;
12521 goto TERMINATE;
12522 }
12523
12524 /* evaluate solution status */
12525 switch( SCIPlpGetSolstat(lp) )
12526 {
12528 /* get LP solution and possibly check the solution's feasibility again */
12529 if( set->lp_checkprimfeas )
12530 {
12531 primalfeaspointer = &primalfeasible;
12532 lp->primalchecked = TRUE;
12533 }
12534 else
12535 {
12536 /* believe in the primal feasibility of the LP solution */
12537 primalfeasible = TRUE;
12538 primalfeaspointer = NULL;
12539 lp->primalchecked = FALSE;
12540 }
12541 if( set->lp_checkdualfeas )
12542 {
12543 dualfeaspointer = &dualfeasible;
12544 lp->dualchecked = TRUE;
12545 }
12546 else
12547 {
12548 /* believe in the dual feasibility of the LP solution */
12549 dualfeasible = TRUE;
12550 dualfeaspointer = NULL;
12551 lp->dualchecked = FALSE;
12552 }
12553
12554 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12555
12556 /* in debug mode, check that lazy bounds (if present) are not violated */
12557 checkLazyBounds(lp, set);
12558
12559 if( primalfeasible && dualfeasible && aging && !lp->diving && stat->nlps > oldnlps )
12560 {
12561 /* update ages and remove obsolete columns and rows from LP */
12562 SCIP_CALL( SCIPlpUpdateAges(lp, stat) );
12563 if( stat->nlps % ((set->lp_rowagelimit+1)/2 + 1) == 0 ) /*lint !e776*/
12564 {
12565 SCIP_CALL( SCIPlpRemoveNewObsoletes(lp, blkmem, set, stat, eventqueue, eventfilter) );
12566 }
12567
12568 if( !lp->solved )
12569 {
12570 /* resolve LP after removing obsolete columns and rows */
12571 SCIPsetDebugMsg(set, "removed obsoletes - resolve LP again: %d rows, %d cols\n", lp->nrows, lp->ncols);
12572 aging = FALSE; /* to prevent infinite loops */
12573 goto SOLVEAGAIN;
12574 }
12575 }
12576 if( !primalfeasible || !dualfeasible )
12577 {
12579
12580 if( (fastmip > 0) && simplex )
12581 {
12582 /* solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12583 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12584 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again without FASTMIP\n",
12585 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12586 fastmip = 0;
12587 goto SOLVEAGAIN;
12588 }
12589 else if( (!primalfeasible && !tightprimfeastol) || (!dualfeasible && !tightdualfeastol) )
12590 {
12591 /* solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12592 * tolerance
12593 */
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 with tighter feasibility tolerance\n",
12596 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12597 tightprimfeastol = tightprimfeastol || !primalfeasible;
12598 tightdualfeastol = tightdualfeastol || !dualfeasible;
12599 goto SOLVEAGAIN;
12600 }
12601 else if( !fromscratch && !wasfromscratch && simplex )
12602 {
12603 /* solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12604 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12605 "(node %" SCIP_LONGINT_FORMAT ") solution of LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, dfeas=%u) -- solving again from scratch\n",
12606 stat->nnodes, stat->nlps, primalfeasible, dualfeasible);
12607 fromscratch = TRUE;
12608 goto SOLVEAGAIN;
12609 }
12610 else
12611 {
12612 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved");
12613 lp->solved = FALSE;
12615 *lperror = TRUE;
12616 }
12617 }
12618 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12619 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12620 lp->lpsolstat, lp->cutoffbound);
12621 break;
12622
12624 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12625 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas || set->lp_alwaysgetduals || set->misc_exactsolve )
12626 {
12627 if( SCIPlpiHasDualRay(lp->lpi) )
12628 {
12629 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12630 }
12631 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12632 * with the primal simplex due to numerical problems) - treat this case like an LP error
12633 */
12634 else
12635 {
12636 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12637 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12638 lp->solved = FALSE;
12640 farkasvalid = FALSE;
12641 *lperror = TRUE;
12642 }
12643 }
12644 else
12645 farkasvalid = TRUE;
12646
12647 /* if the LP solver does not provide a Farkas proof we don't want to resolve the LP */
12648 if( !farkasvalid && !(*lperror) )
12649 {
12651
12652 if( (fastmip > 0) && simplex )
12653 {
12654 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12655 * without FASTMIP
12656 */
12657 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12658 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again without FASTMIP\n",
12659 stat->nnodes, stat->nlps);
12660 fastmip = 0;
12661 goto SOLVEAGAIN;
12662 }
12663 else if( !tightdualfeastol )
12664 {
12665 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12666 * solve again with tighter feasibility tolerance
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 with tighter dual feasibility tolerance\n",
12670 stat->nnodes, stat->nlps);
12671 tightdualfeastol = TRUE;
12672 goto SOLVEAGAIN;
12673 }
12674 else if( !fromscratch && simplex )
12675 {
12676 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12677 * from scratch
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 from scratch\n",
12681 stat->nnodes, stat->nlps);
12682 fromscratch = TRUE;
12683 goto SOLVEAGAIN;
12684 }
12685 else
12686 {
12687 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12688 * helped forget about the LP at this node and mark it to be unsolved
12689 */
12690 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
12691 lp->solved = FALSE;
12693 *lperror = TRUE;
12694 }
12695 }
12696
12697 break;
12698
12700 if( set->lp_checkprimfeas )
12701 {
12702 /* get unbounded LP solution and check the solution's feasibility again */
12703 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
12704
12705 lp->primalchecked = TRUE;
12706 }
12707 else
12708 {
12709 /* get unbounded LP solution believing in the feasibility of the LP solution */
12711
12712 primalfeasible = TRUE;
12713 rayfeasible = TRUE;
12714 lp->primalchecked = FALSE;
12715 }
12716
12717 /* in debug mode, check that lazy bounds (if present) are not violated */
12718 checkLazyBounds(lp, set);
12719
12720 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray (primalfeas=%u, rayfeas=%u)\n",
12721 primalfeasible, rayfeasible);
12722
12723 if( !primalfeasible || !rayfeasible )
12724 {
12726
12727 if( (fastmip > 0) && simplex )
12728 {
12729 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without FASTMIP */
12730 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12731 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again without FASTMIP\n",
12732 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12733 fastmip = 0;
12734 goto SOLVEAGAIN;
12735 }
12736 else if( !tightprimfeastol )
12737 {
12738 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again with tighter feasibility
12739 * tolerance
12740 */
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 with tighter primal feasibility tolerance\n",
12743 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12744 tightprimfeastol = TRUE;
12745 goto SOLVEAGAIN;
12746 }
12747 else if( !fromscratch && simplex )
12748 {
12749 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again from scratch */
12750 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12751 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving again from scratch\n",
12752 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12753 fromscratch = TRUE;
12754 goto SOLVEAGAIN;
12755 }
12756 else if( scaling > 0 )
12757 {
12758 /* unbounded solution is infeasible (this can happen due to numerical problems): solve again without scaling */
12759 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12760 "(node %" SCIP_LONGINT_FORMAT ") solution of unbounded LP %" SCIP_LONGINT_FORMAT " not optimal (pfeas=%u, rfeas=%u) -- solving without scaling\n",
12761 stat->nnodes, stat->nlps, primalfeasible, rayfeasible);
12762 scaling = 0;
12763 goto SOLVEAGAIN;
12764 }
12765 else
12766 {
12767 /* unbounded solution is infeasible (this can happen due to numerical problems) and nothing helped:
12768 * forget about the LP at this node and mark it to be unsolved
12769 */
12770 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP unbounded");
12771 lp->solved = FALSE;
12773 *lperror = TRUE;
12774 }
12775 }
12776
12777 break;
12778
12780 assert(!lpCutoffDisabled(set, prob, lp));
12781 /* Some LP solvers, e.g. CPLEX With FASTMIP setting, do not apply the final pivot to reach the dual solution
12782 * exceeding the objective limit. In some cases like branch-and-price, however, we must make sure that a dual
12783 * feasible solution exists that exceeds the objective limit. Therefore, we have to continue solving it without
12784 * objective limit for at least one iteration. We first try to continue with FASTMIP for one additional simplex
12785 * iteration using the steepest edge pricing rule. If this does not fix the problem, we temporarily disable
12786 * FASTMIP and solve again.
12787 */
12788 if( !SCIPprobAllColsInLP(prob, set, lp) )
12789 {
12790 SCIP_LPI* lpi;
12791 SCIP_Real objval;
12792
12793 lpi = SCIPlpGetLPI(lp);
12794
12795 assert(lpi != NULL);
12796 /* actually, SCIPsetIsGE(set, lp->lpobjval, lp->lpiuobjlim) should hold, but we are a bit less strict in
12797 * the assert by using !SCIPsetIsFeasNegative()
12798 */
12799 assert(SCIPlpiIsObjlimExc(lpi) || !SCIPsetIsFeasNegative(set, lp->lpobjval - lp->lpiobjlim));
12800
12801 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12802
12803 /* do one additional simplex step if the computed dual solution doesn't exceed the objective limit */
12804 if( SCIPsetIsLT(set, objval, lp->lpiobjlim) )
12805 {
12806 SCIP_Real tmpcutoff;
12807 char tmppricingchar;
12808 SCIP_LPSOLSTAT solstat;
12809
12810 SCIPsetDebugMsg(set, "objval = %f < %f = lp->lpiobjlim, but status objlimit\n", objval, lp->lpiobjlim);
12811
12812 /* we want to resolve from the current basis (also if the LP had to be solved from scratch) */
12813 fromscratch = FALSE;
12814
12815 /* temporarily disable cutoffbound, which also disables the objective limit */
12816 tmpcutoff = lp->cutoffbound;
12817 lp->cutoffbound = SCIPlpiInfinity(lpi);
12818
12819 /* set lp pricing strategy to steepest edge */
12820 SCIP_CALL( SCIPsetGetCharParam(set, "lp/pricing", &tmppricingchar) );
12821 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", 's') );
12822
12823 /* resolve LP with an iteration limit of 1 */
12824 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, 1, 1,
12825 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12826
12827 /* reinstall old cutoff bound and lp pricing strategy */
12828 lp->cutoffbound = tmpcutoff;
12829 SCIP_CALL( SCIPsetSetCharParam(set, messagehdlr, "lp/pricing", tmppricingchar) );
12830
12831 /* get objective value */
12832 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12833
12834 /* get solution status for the lp */
12835 solstat = SCIPlpGetSolstat(lp);
12836 assert(solstat != SCIP_LPSOLSTAT_OBJLIMIT);
12837
12838 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, 1 add. step)\n", objval, solstat);
12839
12840 /* the solution is still not exceeding the objective limit and the solving process
12841 * was stopped due to time or iteration limit, solve again with fastmip turned off
12842 */
12843 if( solstat == SCIP_LPSOLSTAT_ITERLIMIT &&
12844 SCIPsetIsLT(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12845 {
12847 if( !(*lperror) && (fastmip > 0) && simplex )
12848 {
12849 fastmip = 0;
12850 SCIP_CALL( lpSolve(lp, set, messagehdlr, stat, prob, SCIP_LPALGO_DUALSIMPLEX, -1, -1,
12851 FALSE, FALSE, TRUE, fastmip, tightprimfeastol, tightdualfeastol, fromscratch, scaling, keepsol, lperror) );
12852
12853 /* get objective value */
12854 SCIP_CALL( SCIPlpiGetObjval(lpi, &objval) );
12855
12856 /* get solution status for the lp */
12857 solstat = SCIPlpGetSolstat(lp);
12858
12859 SCIPsetDebugMsg(set, " ---> new objval = %f (solstat: %d, without fastmip)\n", objval, solstat);
12860 }
12861 }/*lint !e438*/
12862
12863 /* check for lp errors */
12864 if( *lperror || solstat == SCIP_LPSOLSTAT_ERROR || solstat == SCIP_LPSOLSTAT_NOTSOLVED )
12865 {
12866 SCIPsetDebugMsg(set, "unresolved error while resolving LP in order to exceed the objlimit\n");
12867 lp->solved = FALSE;
12869
12870 retcode = *lperror ? SCIP_OKAY : SCIP_LPERROR;
12871 goto TERMINATE;
12872 }
12873
12874 lp->solved = TRUE;
12875
12876 /* optimal solution / objlimit / itlimit or timelimit, but objlimit exceeded */
12877 if( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_OBJLIMIT
12878 || ( (solstat == SCIP_LPSOLSTAT_ITERLIMIT || solstat == SCIP_LPSOLSTAT_TIMELIMIT)
12879 && SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) ) )
12880 {
12881 /* get LP solution and possibly check the solution's feasibility again */
12882 if( set->lp_checkprimfeas )
12883 {
12884 primalfeaspointer = &primalfeasible;
12885 lp->primalchecked = TRUE;
12886 }
12887 else
12888 {
12889 /* believe in the primal feasibility of the LP solution */
12890 primalfeasible = TRUE;
12891 primalfeaspointer = NULL;
12892 lp->primalchecked = FALSE;
12893 }
12894 if( set->lp_checkdualfeas )
12895 {
12896 dualfeaspointer = &dualfeasible;
12897 lp->dualchecked = TRUE;
12898 }
12899 else
12900 {
12901 /* believe in the dual feasibility of the LP solution */
12902 dualfeasible = TRUE;
12903 dualfeaspointer = NULL;
12904 lp->dualchecked = FALSE;
12905 }
12906
12907 SCIP_CALL( SCIPlpGetSol(lp, set, stat, primalfeaspointer, dualfeaspointer) );
12908
12909 /* in debug mode, check that lazy bounds (if present) are not violated by an optimal LP solution */
12910 if( solstat == SCIP_LPSOLSTAT_OPTIMAL )
12911 {
12912 checkLazyBounds(lp, set);
12913 }
12914
12915 /* if objective value is larger than the cutoff bound, set solution status to objective
12916 * limit reached and objective value to infinity, in case solstat = SCIP_LPSOLSTAT_OBJLIMIT,
12917 * this was already done in the lpSolve() method
12918 */
12919 if( SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob)) )
12920 {
12923 }
12924
12925 /* LP solution is not feasible or objective limit was reached without the LP value really exceeding
12926 * the cutoffbound; mark the LP to be unsolved
12927 */
12928 if( !primalfeasible || !dualfeasible
12929 || (solstat == SCIP_LPSOLSTAT_OBJLIMIT &&
12930 !SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))) )
12931 {
12932 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_HIGH, "unresolved");
12933 lp->solved = FALSE;
12935 *lperror = TRUE;
12936 }
12937
12938 SCIPsetDebugMsg(set, " -> LP objective value: %g + %g = %g (solstat=%d, cutoff=%g)\n",
12939 lp->lpobjval, getFiniteLooseObjval(lp, set, prob), lp->lpobjval + getFiniteLooseObjval(lp, set, prob),
12940 lp->lpsolstat, lp->cutoffbound);
12941 }
12942 /* infeasible solution */
12943 else if( solstat == SCIP_LPSOLSTAT_INFEASIBLE )
12944 {
12945 SCIPsetDebugMsg(set, " -> LP infeasible\n");
12946
12947 if( !SCIPprobAllColsInLP(prob, set, lp) || set->lp_checkfarkas )
12948 {
12949 if( SCIPlpiHasDualRay(lp->lpi) )
12950 {
12951 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, forcedlpsolve, &farkasvalid) );
12952 }
12953 /* it might happen that we have no infeasibility proof for the current LP (e.g. if the LP was always solved
12954 * with the primal simplex due to numerical problems) - treat this case like an LP error
12955 */
12956 else
12957 {
12958 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12959 "(node %" SCIP_LONGINT_FORMAT ") infeasibility of LP %" SCIP_LONGINT_FORMAT " could not be proven by dual ray\n", stat->nnodes, stat->nlps);
12960 lp->solved = FALSE;
12962 farkasvalid = FALSE;
12963 *lperror = TRUE;
12964 }
12965 }
12966 else
12967 farkasvalid = TRUE;
12968
12969 if( !farkasvalid )
12970 {
12972
12973 if( !tightprimfeastol )
12974 {
12975 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems):
12976 * solve again with tighter feasibility tolerance
12977 */
12978 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
12979 "(node %" SCIP_LONGINT_FORMAT ") proof of infeasible LP %" SCIP_LONGINT_FORMAT " not valid -- solving again with tighter primal feasibility tolerance\n",
12980 stat->nnodes, stat->nlps);
12981 tightprimfeastol = TRUE;
12982 goto SOLVEAGAIN;
12983 }
12984 else if( simplex )
12985 {
12986 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems): solve again
12987 * from scratch
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 from scratch\n",
12991 stat->nnodes, stat->nlps);
12992 fromscratch = TRUE;
12993 goto SOLVEAGAIN;
12994 }
12995 else
12996 {
12997 /* the Farkas proof does not prove infeasibility (this can happen due to numerical problems) and nothing
12998 * helped forget about the LP at this node and mark it to be unsolved
12999 */
13000 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, LP infeasible");
13001 lp->solved = FALSE;
13003 *lperror = TRUE;
13004 }
13005 }
13006 }
13007 /* unbounded solution */
13008 else if( solstat == SCIP_LPSOLSTAT_UNBOUNDEDRAY )
13009 {
13010 if( set->lp_checkprimfeas )
13011 {
13012 /* get unbounded LP solution and check the solution's feasibility again */
13013 SCIP_CALL( SCIPlpGetUnboundedSol(lp, set, stat, &primalfeasible, &rayfeasible) );
13014
13015 lp->primalchecked = TRUE;
13016 }
13017 else
13018 {
13019 /* get unbounded LP solution believing in its feasibility */
13021
13022 primalfeasible = TRUE;
13023 rayfeasible = TRUE;
13024 lp->primalchecked = FALSE;
13025 }
13026
13027 SCIPsetDebugMsg(set, " -> LP has unbounded primal ray\n");
13028
13029 /* in debug mode, check that lazy bounds (if present) are not violated */
13030 checkLazyBounds(lp, set);
13031
13032 if( !primalfeasible || !rayfeasible )
13033 {
13034 /* unbounded solution is infeasible (this can happen due to numerical problems):
13035 * forget about the LP at this node and mark it to be unsolved
13036 *
13037 * @todo: like in the default LP solving evaluation, solve without fastmip,
13038 * with tighter feasibility tolerance and from scratch
13039 */
13040 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved, unbounded LP");
13041 lp->solved = FALSE;
13043 *lperror = TRUE;
13044 }
13045 }
13046
13047 assert(lp->lpsolstat != SCIP_LPSOLSTAT_ITERLIMIT);
13048 assert(SCIPsetIsGE(set, objval, lp->cutoffbound - getFiniteLooseObjval(lp, set, prob))
13050 }
13051 else
13052 {
13053 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
13054 }
13055 }
13056 SCIPsetDebugMsg(set, " -> LP objective limit reached\n");
13057 break;
13058
13060 SCIPsetDebugMsg(set, " -> LP iteration limit exceeded\n");
13061 break;
13062
13064 SCIPsetDebugMsg(set, " -> LP time limit exceeded\n");
13065
13066 /* make sure that we evaluate the time limit exactly in order to avoid erroneous warning */
13067 stat->nclockskipsleft = 0;
13068 if( !stat->userinterrupt && !SCIPsolveIsStopped(set, stat, FALSE) )
13069 {
13070 SCIPmessagePrintWarning(messagehdlr, "LP solver reached time limit, but SCIP time limit is not exceeded yet; "
13071 "you might consider switching the clock type of SCIP\n");
13073 }
13074 break;
13075
13078 SCIPerrorMessage("error in LP solver\n");
13079 retcode = SCIP_LPERROR;
13080 goto TERMINATE;
13081
13082 default:
13083 SCIPerrorMessage("unknown LP solution status\n");
13084 retcode = SCIP_ERROR;
13085 goto TERMINATE;
13086 }
13087 }
13088 assert(!(*lperror) || !lp->solved);
13089
13090 TERMINATE:
13091 /* if the LP had to be solved from scratch, we have to reset this flag since it is stored in the LPI; otherwise it
13092 * may happen that we continue to solve from scratch during strong branching */
13093 if( lp->lpifromscratch )
13094 {
13095 SCIP_Bool success;
13096 (void) lpSetFromscratch(lp, FALSE, &success);
13097 SCIPsetDebugMsg(set, "resetting parameter SCIP_LPPARAM_FROMSCRATCH to FALSE %s\n", success ? "" : "failed");
13098 SCIP_UNUSED(success);
13099 }
13100
13101 return retcode;
13102}
13103
13104/** gets solution status of current LP */
13106 SCIP_LP* lp /**< current LP data */
13107 )
13108{
13109 assert(lp != NULL);
13110 assert(lp->solved || lp->lpsolstat == SCIP_LPSOLSTAT_NOTSOLVED);
13111
13112 return (lp->flushed ? lp->lpsolstat : SCIP_LPSOLSTAT_NOTSOLVED);
13113}
13114
13115/** gets objective value of current LP
13116 *
13117 * @note This method returns the objective value of the current LP solution, which might be primal or dual infeasible
13118 * if a limit was hit during solving. It must not be used as a dual bound if the LP solution status is
13119 * SCIP_LPSOLSTAT_ITERLIMIT or SCIP_LPSOLSTAT_TIMELIMIT.
13120 */
13122 SCIP_LP* lp, /**< current LP data */
13123 SCIP_SET* set, /**< global SCIP settings */
13124 SCIP_PROB* prob /**< problem data */
13125 )
13126{
13127 assert(lp != NULL);
13128 assert(lp->solved);
13129 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13130 assert(set != NULL);
13131
13132 if( !lp->flushed )
13133 return SCIP_INVALID;
13135 return lp->lpobjval;
13136 else if( lp->looseobjvalinf > 0 )
13137 return -SCIPsetInfinity(set);
13138 else
13139 {
13140 /* recalculate the loose objective value, if needed */
13141 if( !lp->looseobjvalid )
13143
13144 return lp->lpobjval + lp->looseobjval;
13145 }
13146}
13147
13148/** gets part of objective value of current LP that results from COLUMN variables only */
13150 SCIP_LP* lp /**< current LP data */
13151 )
13152{
13153 assert(lp != NULL);
13154 assert(lp->solved);
13155
13156 return (lp->flushed ? lp->lpobjval : SCIP_INVALID);
13157}
13158
13159/** gets part of objective value of current LP that results from LOOSE variables only */
13161 SCIP_LP* lp, /**< current LP data */
13162 SCIP_SET* set, /**< global SCIP settings */
13163 SCIP_PROB* prob /**< problem data */
13164 )
13165{
13166 assert(lp != NULL);
13167 assert(lp->solved);
13168 assert((lp->nloosevars > 0) || (lp->looseobjvalinf == 0 && lp->looseobjval == 0.0));
13169 assert(set != NULL);
13170
13171 if( !lp->flushed )
13172 return SCIP_INVALID;
13173 else if( lp->looseobjvalinf > 0 )
13174 return -SCIPsetInfinity(set);
13175 else
13176 return getFiniteLooseObjval(lp, set, prob);
13177}
13178
13179/** remembers the current LP objective value as root solution value */
13181 SCIP_LP* lp, /**< current LP data */
13182 SCIP_SET* set, /**< global SCIP settings */
13183 SCIP_PROB* prob /**< problem data */
13184 )
13185{
13186 assert(lp != NULL);
13187
13189 lp->rootlooseobjval = SCIPlpGetLooseObjval(lp, set, prob);
13190}
13191
13192/** invalidates the root LP solution value */
13194 SCIP_LP* lp /**< current LP data */
13195 )
13196{
13197 assert(lp != NULL);
13198
13201}
13202
13203/** recomputes local and global pseudo objective values */
13205 SCIP_LP* lp, /**< current LP data */
13206 SCIP_SET* set, /**< global SCIP settings */
13207 SCIP_PROB* prob /**< problem data */
13208 )
13209{
13210 SCIP_VAR** vars;
13211 int nvars;
13212 int v;
13213
13214 assert(lp != NULL);
13215 assert(set != NULL);
13216 assert(prob != NULL);
13217
13218 vars = prob->vars;
13219 nvars = prob->nvars;
13220
13221 lp->glbpseudoobjvalinf = 0;
13222 lp->glbpseudoobjval = 0.0;
13223
13224 lp->pseudoobjvalinf = 0;
13225 lp->pseudoobjval = 0.0;
13226
13227 for( v = 0; v < nvars; ++v )
13228 {
13229 SCIP_Real obj = SCIPvarGetObj(vars[v]);
13230
13231 if( SCIPsetIsPositive(set, obj) )
13232 {
13233 /* update the global pseudo objective value */
13234 if( SCIPsetIsInfinity(set, -SCIPvarGetLbGlobal(vars[v])) )
13235 ++(lp->glbpseudoobjvalinf);
13236 else
13237 lp->glbpseudoobjval += obj * SCIPvarGetLbGlobal(vars[v]);
13238
13239 /* update the local pseudo objective value */
13240 if( SCIPsetIsInfinity(set, -SCIPvarGetLbLocal(vars[v])) )
13241 ++(lp->pseudoobjvalinf);
13242 else
13243 lp->pseudoobjval += obj * SCIPvarGetLbLocal(vars[v]);
13244 }
13245
13246 if( SCIPsetIsNegative(set, obj) )
13247 {
13248 /* update the global pseudo objective value */
13250 ++(lp->glbpseudoobjvalinf);
13251 else
13252 lp->glbpseudoobjval += obj * SCIPvarGetUbGlobal(vars[v]);
13253
13254 /* update the local pseudo objective value */
13255 if( SCIPsetIsInfinity(set, SCIPvarGetUbLocal(vars[v])) )
13256 ++(lp->pseudoobjvalinf);
13257 else
13258 lp->pseudoobjval += obj * SCIPvarGetUbLocal(vars[v]);
13259 }
13260 }
13261
13262 /* the recomputed values are reliable */
13264 lp->glbpseudoobjvalid = TRUE;
13265 lp->relpseudoobjval = lp->pseudoobjval;
13266 lp->pseudoobjvalid = TRUE;
13267}
13268
13269/** gets the global pseudo objective value; that is all variables set to their best (w.r.t. the objective function)
13270 * global bound
13271 */
13273 SCIP_LP* lp, /**< current LP data */
13274 SCIP_SET* set, /**< global SCIP settings */
13275 SCIP_PROB* prob /**< problem data */
13276 )
13277{
13278 assert(lp != NULL);
13279 assert(lp->glbpseudoobjvalinf >= 0);
13280 assert(set != NULL);
13281
13282 if( lp->glbpseudoobjvalinf > 0 || set->nactivepricers > 0 )
13283 return -SCIPsetInfinity(set);
13284 else
13285 {
13286 /* recalculate the global pseudo solution value, if needed */
13287 if( !lp->glbpseudoobjvalid )
13289
13290 /* if the global pseudo objective value is smaller than -infinity, we just return -infinity */
13292 return -SCIPsetInfinity(set);
13293
13295 return SCIPsetInfinity(set);
13296
13297 return lp->glbpseudoobjval;
13298 }
13299}
13300
13301/** gets the pseudo objective value for the current search node; that is all variables set to their best (w.r.t. the
13302 * objective function) local bound
13303 */
13305 SCIP_LP* lp, /**< current LP data */
13306 SCIP_SET* set, /**< global SCIP settings */
13307 SCIP_PROB* prob /**< problem data */
13308 )
13309{
13310 assert(lp != NULL);
13311 assert(lp->pseudoobjvalinf >= 0);
13312 assert(set != NULL);
13313
13314 if( lp->pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13315 return -SCIPsetInfinity(set);
13316 else
13317 {
13318 /* recalculate the pseudo solution value, if needed */
13319 if( !lp->pseudoobjvalid )
13321
13322 /* if the pseudo objective value is smaller than -infinity, we just return -infinity */
13324 return -SCIPsetInfinity(set);
13325
13327 return SCIPsetInfinity(set);
13328
13329 return lp->pseudoobjval;
13330 }
13331}
13332
13333/** gets pseudo objective value, if a bound of the given variable would be modified in the given way */
13335 SCIP_LP* lp, /**< current LP data */
13336 SCIP_SET* set, /**< global SCIP settings */
13337 SCIP_PROB* prob, /**< problem data */
13338 SCIP_VAR* var, /**< problem variable */
13339 SCIP_Real oldbound, /**< old value for bound */
13340 SCIP_Real newbound, /**< new value for bound */
13341 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13342 )
13343{
13344 SCIP_Real pseudoobjval;
13345 int pseudoobjvalinf;
13346 SCIP_Real obj;
13347
13348 pseudoobjval = getFinitePseudoObjval(lp, set, prob);
13349 pseudoobjvalinf = lp->pseudoobjvalinf;
13350 obj = SCIPvarGetObj(var);
13351 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13352 {
13353 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13354 pseudoobjvalinf--;
13355 else
13356 pseudoobjval -= oldbound * obj;
13357 assert(pseudoobjvalinf >= 0);
13358 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13359 pseudoobjvalinf++;
13360 else
13361 pseudoobjval += newbound * obj;
13362 }
13363 assert(pseudoobjvalinf >= 0);
13364
13365 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13366 return -SCIPsetInfinity(set);
13367 else
13368 return pseudoobjval;
13369}
13370
13371/** gets pseudo objective value, if a bound of the given variable would be modified in the given way;
13372 * perform calculations with interval arithmetic to get an exact lower bound
13373 */
13375 SCIP_LP* lp, /**< current LP data */
13376 SCIP_SET* set, /**< global SCIP settings */
13377 SCIP_VAR* var, /**< problem variable */
13378 SCIP_Real oldbound, /**< old value for bound */
13379 SCIP_Real newbound, /**< new value for bound */
13380 SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
13381 )
13382{
13383 SCIP_Real pseudoobjval;
13384 int pseudoobjvalinf;
13385 SCIP_Real obj;
13386
13387 assert(lp->pseudoobjvalid);
13388
13389 pseudoobjval = lp->pseudoobjval;
13390 pseudoobjvalinf = lp->pseudoobjvalinf;
13391 obj = SCIPvarGetObj(var);
13392 if( !SCIPsetIsZero(set, obj) && boundtype == SCIPvarGetBestBoundType(var) )
13393 {
13394 SCIP_INTERVAL objint;
13395 SCIP_INTERVAL bd;
13396 SCIP_INTERVAL prod;
13397 SCIP_INTERVAL psval;
13398
13399 SCIPintervalSet(&psval, pseudoobjval);
13400 SCIPintervalSet(&objint, SCIPvarGetObj(var));
13401
13402 if( SCIPsetIsInfinity(set, REALABS(oldbound)) )
13403 pseudoobjvalinf--;
13404 else
13405 {
13406 SCIPintervalSet(&bd, oldbound);
13407 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13408 SCIPintervalSub(SCIPsetInfinity(set), &psval, psval, prod);
13409 }
13410 assert(pseudoobjvalinf >= 0);
13411 if( SCIPsetIsInfinity(set, REALABS(newbound)) )
13412 pseudoobjvalinf++;
13413 else
13414 {
13415 SCIPintervalSet(&bd, newbound);
13416 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, objint);
13417 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, prod);
13418 }
13419
13420 pseudoobjval = SCIPintervalGetInf(psval);
13421 }
13422 assert(pseudoobjvalinf >= 0);
13423
13424 if( pseudoobjvalinf > 0 || set->nactivepricers > 0 )
13425 return -SCIPsetInfinity(set);
13426 else
13427 return pseudoobjval;
13428}
13429
13430/** compute the objective delta due the new objective coefficient */
13431static
13433 SCIP_SET* set, /**< global SCIP settings */
13434 SCIP_Real oldobj, /**< old objective value of variable */
13435 SCIP_Real newobj, /**< new objective value of variable */
13436 SCIP_Real lb, /**< lower bound of variable */
13437 SCIP_Real ub, /**< upper bound of variable */
13438 SCIP_Real* deltaval, /**< pointer to store the delta value */
13439 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13440 )
13441{
13442 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13443 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13444 assert(!SCIPsetIsInfinity(set, lb));
13445 assert(!SCIPsetIsInfinity(set, -ub));
13446 assert(!SCIPsetIsEQ(set, oldobj, newobj));
13447
13448 (*deltaval) = 0.0;
13449 (*deltainf) = 0;
13450
13451 if( SCIPsetIsPositive(set, oldobj) )
13452 {
13453 /* sign of objective did not change */
13454 if( SCIPsetIsPositive(set, newobj) )
13455 {
13456 /* if the bound is finite, calculate the deltaval */
13457 if( !SCIPsetIsInfinity(set, -lb) )
13458 (*deltaval) = lb * (newobj - oldobj);
13459 }
13460 /* sign of objective did change, so the best bound does change */
13461 else if( SCIPsetIsNegative(set, newobj) )
13462 {
13463 if( SCIPsetIsInfinity(set, -lb) )
13464 {
13465 /* old best bound was infinite while new one is not */
13466 if( !SCIPsetIsInfinity(set, ub) )
13467 {
13468 (*deltainf) = -1;
13469 (*deltaval) = ub * newobj;
13470 }
13471 }
13472 else
13473 {
13474 /* new best bound is infinite while old one was not */
13475 if( SCIPsetIsInfinity(set, ub) )
13476 {
13477 (*deltainf) = 1;
13478 (*deltaval) = -lb * oldobj;
13479 }
13480 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13481 else
13482 {
13483 (*deltaval) = (ub * newobj) - (lb * oldobj);
13484 }
13485 }
13486 }
13487 /* new objective is 0.0 */
13488 else
13489 {
13490 if( SCIPsetIsInfinity(set, -lb) )
13491 (*deltainf) = -1;
13492 else
13493 (*deltaval) = -lb * oldobj;
13494 }
13495 }
13496 else if( SCIPsetIsNegative(set, oldobj) )
13497 {
13498 /* sign of objective did not change */
13499 if( SCIPsetIsNegative(set, newobj) )
13500 {
13501 /* if the bound is finite, calculate the deltaval */
13502 if( !SCIPsetIsInfinity(set, ub) )
13503 (*deltaval) = ub * (newobj - oldobj);
13504 }
13505 /* sign of objective did change, so the best bound does change */
13506 else if( SCIPsetIsPositive(set, newobj) )
13507 {
13508 if( SCIPsetIsInfinity(set, ub) )
13509 {
13510 /* old best bound was infinite while new one is not */
13511 if( !SCIPsetIsInfinity(set, -lb) )
13512 {
13513 (*deltainf) = -1;
13514 (*deltaval) = lb * newobj;
13515 }
13516 }
13517 else
13518 {
13519 /* new best bound is infinite while old one was not */
13520 if( SCIPsetIsInfinity(set, -lb) )
13521 {
13522 (*deltainf) = 1;
13523 (*deltaval) = -ub * oldobj;
13524 }
13525 /* neither old nor new best bound is infinite, so just calculate the deltaval */
13526 else
13527 {
13528 (*deltaval) = (lb * newobj) - (ub * oldobj);
13529 }
13530 }
13531 }
13532 /* new objective is 0.0 */
13533 else
13534 {
13535 if( SCIPsetIsInfinity(set, ub) )
13536 (*deltainf) = -1;
13537 else
13538 (*deltaval) = -ub * oldobj;
13539 }
13540 }
13541 /* old objective was 0.0 */
13542 else
13543 {
13544 if( SCIPsetIsNegative(set, newobj) )
13545 {
13546 if( SCIPsetIsInfinity(set, ub) )
13547 (*deltainf) = 1;
13548 else
13549 (*deltaval) = ub * newobj;
13550 }
13551 else if( SCIPsetIsPositive(set, newobj) )
13552 {
13553 if( SCIPsetIsInfinity(set, -lb) )
13554 (*deltainf) = 1;
13555 else
13556 (*deltaval) = lb * newobj;
13557 }
13558 }
13559}
13560
13561/** compute the objective delta due the new lower bound */
13562static
13564 SCIP_SET* set, /**< global SCIP settings */
13565 SCIP_Real obj, /**< objective value of variable */
13566 SCIP_Real oldlb, /**< old lower bound of variable */
13567 SCIP_Real newlb, /**< new lower bound of variable */
13568 SCIP_Real* deltaval, /**< pointer to store the delta value */
13569 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13570 )
13571{
13572 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13573 assert(!SCIPsetIsInfinity(set, oldlb));
13574 assert(!SCIPsetIsInfinity(set, -oldlb) || !SCIPsetIsInfinity(set, -newlb));
13575 assert(SCIPsetIsPositive(set, obj)); /* we only need to update if the objective is positive */
13576
13577 if( SCIPsetIsInfinity(set, -oldlb) )
13578 {
13579 if( !SCIPsetIsInfinity(set, newlb) )
13580 {
13581 (*deltainf) = -1;
13582 (*deltaval) = newlb * obj;
13583 }
13584 else
13585 {
13586 (*deltainf) = 0;
13587 (*deltaval) = 0.0;
13588 }
13589 }
13590 else if( SCIPsetIsInfinity(set, REALABS(newlb)) )
13591 {
13592 (*deltainf) = 1;
13593 (*deltaval) = -oldlb * obj;
13594 }
13595 else
13596 {
13597 (*deltainf) = 0;
13598 (*deltaval) = obj * (newlb - oldlb);
13599 }
13600}
13601
13602/** compute the objective delta due the new upper bound */
13603static
13605 SCIP_SET* set, /**< global SCIP settings */
13606 SCIP_Real obj, /**< objective value of variable */
13607 SCIP_Real oldub, /**< old upper bound of variable */
13608 SCIP_Real newub, /**< new upper bound of variable */
13609 SCIP_Real* deltaval, /**< pointer to store the delta value */
13610 int* deltainf /**< pointer to store the number of variables with infinite best bound */
13611 )
13612{
13613 assert(!SCIPsetIsInfinity(set, REALABS(obj)));
13614 assert(!SCIPsetIsInfinity(set, -oldub));
13615 assert(!SCIPsetIsInfinity(set, oldub) || !SCIPsetIsInfinity(set, newub));
13616 assert(SCIPsetIsNegative(set, obj)); /* we only need to update if the objective is negative */
13617
13618 if( SCIPsetIsInfinity(set, oldub) )
13619 {
13620 if( !SCIPsetIsInfinity(set, -newub) )
13621 {
13622 (*deltainf) = -1;
13623 (*deltaval) = newub * obj;
13624 }
13625 else
13626 {
13627 (*deltainf) = 0;
13628 (*deltaval) = 0.0;
13629 }
13630 }
13631 else if( SCIPsetIsInfinity(set, REALABS(newub)) )
13632 {
13633 (*deltainf) = 1;
13634 (*deltaval) = -oldub * obj;
13635 }
13636 else
13637 {
13638 (*deltainf) = 0;
13639 (*deltaval) = obj * (newub - oldub);
13640 }
13641}
13642
13643/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds */
13644static
13646 SCIP_LP* lp, /**< current LP data */
13647 SCIP_SET* set, /**< global SCIP settings */
13648 SCIP_VAR* var, /**< problem variable that changed */
13649 SCIP_Real deltaval, /**< delta value in the objective function */
13650 int deltainf, /**< delta value for the number of variables with infinite best bound */
13651 SCIP_Bool local, /**< should the local pseudo objective value be updated? */
13652 SCIP_Bool loose, /**< should the loose objective value be updated? */
13653 SCIP_Bool global /**< should the global pseudo objective value be updated? */
13654 )
13655{
13656 assert(lp != NULL);
13657 assert(lp->looseobjvalinf >= 0);
13658 assert(lp->pseudoobjvalinf >= 0);
13659 assert(lp->glbpseudoobjvalinf >= 0);
13660
13661 /* update the pseudo objective value */
13662 if( local )
13663 {
13664 lp->pseudoobjvalinf += deltainf;
13665 if( lp->pseudoobjvalid )
13666 {
13667 lp->pseudoobjval += deltaval;
13668
13669 /* if the absolute value was increased, this is regarded as reliable,
13670 * otherwise, we check whether we can still trust the updated value
13671 */
13673 lp->relpseudoobjval = lp->pseudoobjval;
13675 lp->pseudoobjvalid = FALSE;
13676 }
13677
13678 /* after changing a local bound on a LOOSE variable, we have to update the loose objective value, too */
13680 loose = TRUE;
13681 }
13682 /* update the loose objective value */
13683 if( loose )
13684 {
13685 lp->looseobjvalinf += deltainf;
13686
13687 if( deltaval != 0.0 && lp->looseobjvalid )
13688 {
13689 lp->looseobjval += deltaval;
13690
13691 /* if the absolute value was increased, this is regarded as reliable,
13692 * otherwise, we check whether we can still trust the updated value
13693 */
13694 if( REALABS(lp->rellooseobjval) < REALABS(lp->looseobjval) )
13695 lp->rellooseobjval = lp->looseobjval;
13697 lp->looseobjvalid = FALSE;
13698 }
13699 }
13700 /* update the root pseudo objective values */
13701 if( global )
13702 {
13703 lp->glbpseudoobjvalinf += deltainf;
13704 if( lp->glbpseudoobjvalid )
13705 {
13706 lp->glbpseudoobjval += deltaval;
13707
13708 /* if the absolute value was increased, this is regarded as reliable,
13709 * otherwise, we check whether we can still trust the updated value
13710 */
13715 }
13716 }
13717
13718 assert(lp->looseobjvalinf >= 0);
13719 assert(lp->pseudoobjvalinf >= 0);
13720 assert(lp->glbpseudoobjvalinf >= 0);
13721}
13722
13723/** updates current pseudo and loose objective values for a change in a variable's objective value or bounds;
13724 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
13725 */
13726static
13728 SCIP_LP* lp, /**< current LP data */
13729 SCIP_SET* set, /**< global SCIP settings */
13730 SCIP_VAR* var, /**< problem variable that changed */
13731 SCIP_Real oldobj, /**< old objective value of variable */
13732 SCIP_Real oldlb, /**< old objective value of variable */
13733 SCIP_Real oldub, /**< old objective value of variable */
13734 SCIP_Real newobj, /**< new objective value of variable */
13735 SCIP_Real newlb, /**< new objective value of variable */
13736 SCIP_Real newub /**< new objective value of variable */
13737 )
13738{
13739 SCIP_INTERVAL deltaval;
13740 SCIP_INTERVAL bd;
13741 SCIP_INTERVAL obj;
13742 SCIP_INTERVAL prod;
13743 SCIP_INTERVAL psval;
13744 int deltainf;
13745
13746 assert(lp != NULL);
13747 assert(lp->pseudoobjvalinf >= 0);
13748 assert(lp->looseobjvalinf >= 0);
13749 assert(!SCIPsetIsInfinity(set, REALABS(oldobj)));
13750 assert(!SCIPsetIsInfinity(set, oldlb));
13751 assert(!SCIPsetIsInfinity(set, -oldub));
13752 assert(!SCIPsetIsInfinity(set, REALABS(newobj)));
13753 assert(!SCIPsetIsInfinity(set, newlb));
13754 assert(!SCIPsetIsInfinity(set, -newub));
13755 assert(var != NULL);
13756
13758 {
13759 SCIPerrorMessage("LP was informed of an objective change of a non-active variable\n");
13760 return SCIP_INVALIDDATA;
13761 }
13762
13763 assert(SCIPvarGetProbindex(var) >= 0);
13764
13765 SCIPintervalSet(&deltaval, 0.0);
13766 deltainf = 0;
13767
13768 /* subtract old pseudo objective value */
13769 if( oldobj > 0.0 )
13770 {
13771 if( SCIPsetIsInfinity(set, -oldlb) )
13772 deltainf--;
13773 else
13774 {
13775 SCIPintervalSet(&bd, oldlb);
13776 SCIPintervalSet(&obj, oldobj);
13777 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13778 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldlb * oldobj; */
13779 }
13780 }
13781 else if( oldobj < 0.0 )
13782 {
13783 if( SCIPsetIsInfinity(set, oldub) )
13784 deltainf--;
13785 else
13786 {
13787 SCIPintervalSet(&bd, oldub);
13788 SCIPintervalSet(&obj, oldobj);
13789 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13790 SCIPintervalSub(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval -= oldub * oldobj; */
13791 }
13792 }
13793
13794 /* add new pseudo objective value */
13795 if( newobj > 0.0 )
13796 {
13797 if( SCIPsetIsInfinity(set, -newlb) )
13798 deltainf++;
13799 else
13800 {
13801 SCIPintervalSet(&bd, newlb);
13802 SCIPintervalSet(&obj, newobj);
13803 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13804 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newlb * newobj; */
13805 }
13806 }
13807 else if( newobj < 0.0 )
13808 {
13809 if( SCIPsetIsInfinity(set, newub) )
13810 deltainf++;
13811 else
13812 {
13813 SCIPintervalSet(&bd, newub);
13814 SCIPintervalSet(&obj, newobj);
13815 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, obj);
13816 SCIPintervalAdd(SCIPsetInfinity(set), &deltaval, deltaval, prod); /* deltaval += newub * newobj; */
13817 }
13818 }
13819
13820 /* update the pseudo and loose objective values */
13821 SCIPintervalSet(&psval, lp->pseudoobjval);
13822 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13823 lp->pseudoobjval = SCIPintervalGetInf(psval);
13824 lp->pseudoobjvalinf += deltainf;
13826 {
13827 SCIPintervalSet(&psval, lp->looseobjval);
13828 SCIPintervalAdd(SCIPsetInfinity(set), &psval, psval, deltaval);
13829 lp->looseobjval = SCIPintervalGetInf(psval);
13830 lp->looseobjvalinf += deltainf;
13831 }
13832
13833 assert(lp->pseudoobjvalinf >= 0);
13834 assert(lp->looseobjvalinf >= 0);
13835
13836 return SCIP_OKAY;
13837}
13838
13839/** updates current pseudo and loose objective value for a change in a variable's objective coefficient */
13841 SCIP_LP* lp, /**< current LP data */
13842 SCIP_SET* set, /**< global SCIP settings */
13843 SCIP_VAR* var, /**< problem variable that changed */
13844 SCIP_Real oldobj, /**< old objective coefficient of variable */
13845 SCIP_Real newobj /**< new objective coefficient of variable */
13846 )
13847{
13848 assert(set != NULL);
13849 assert(var != NULL);
13850
13851 if( set->misc_exactsolve )
13852 {
13853 if( oldobj != newobj ) /*lint !e777*/
13854 {
13856 newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) );
13857 }
13858 }
13859 else
13860 {
13861 if( !SCIPsetIsEQ(set, oldobj, newobj) )
13862 {
13863 SCIP_Real deltaval;
13864 int deltainf;
13865
13867 assert(SCIPvarGetProbindex(var) >= 0);
13868
13869 /* the objective coefficient can only be changed during presolving, that implies that the global and local
13870 * domain of the variable are the same
13871 */
13872 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetLbGlobal(var), SCIPvarGetLbLocal(var)));
13873 assert(lp->probing || SCIPsetIsEQ(set, SCIPvarGetUbGlobal(var), SCIPvarGetUbLocal(var)));
13874
13875 /* compute the pseudo objective delta due the new objective coefficient */
13876 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), &deltaval, &deltainf);
13877
13878 /* update the local pseudo objective value */
13879 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13880
13881 /* compute the pseudo objective delta due the new objective coefficient */
13882 getObjvalDeltaObj(set, oldobj, newobj, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), &deltaval, &deltainf);
13883
13884 /* update the global pseudo objective value */
13885 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13886 }
13887 }
13888
13889 return SCIP_OKAY;
13890}
13891
13892
13893/** updates current root pseudo objective value for a global change in a variable's lower bound */
13895 SCIP_LP* lp, /**< current LP data */
13896 SCIP_SET* set, /**< global SCIP settings */
13897 SCIP_VAR* var, /**< problem variable that changed */
13898 SCIP_Real oldlb, /**< old lower bound of variable */
13899 SCIP_Real newlb /**< new lower bound of variable */
13900 )
13901{
13902 assert(set != NULL);
13903 assert(var != NULL);
13904
13905 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13906 {
13907 SCIP_Real deltaval;
13908 int deltainf;
13909
13910 /* compute the pseudo objective delta due the new lower bound */
13911 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13912
13913 /* update the root pseudo objective values */
13914 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13915 }
13916
13917 return SCIP_OKAY;
13918}
13919
13920/** updates current pseudo and loose objective value for a change in a variable's lower bound */
13922 SCIP_LP* lp, /**< current LP data */
13923 SCIP_SET* set, /**< global SCIP settings */
13924 SCIP_VAR* var, /**< problem variable that changed */
13925 SCIP_Real oldlb, /**< old lower bound of variable */
13926 SCIP_Real newlb /**< new lower bound of variable */
13927 )
13928{
13929 assert(set != NULL);
13930 assert(var != NULL);
13931
13932 if( set->misc_exactsolve )
13933 {
13934 if( oldlb != newlb && SCIPvarGetObj(var) > 0.0 ) /*lint !e777*/
13935 {
13936 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), oldlb, SCIPvarGetUbLocal(var),
13937 SCIPvarGetObj(var), newlb, SCIPvarGetUbLocal(var)) );
13938 }
13939 }
13940 else
13941 {
13942 if( !SCIPsetIsEQ(set, oldlb, newlb) && SCIPsetIsPositive(set, SCIPvarGetObj(var)) )
13943 {
13944 SCIP_Real deltaval;
13945 int deltainf;
13946
13948 assert(SCIPvarGetProbindex(var) >= 0);
13949
13950 /* compute the pseudo objective delta due the new lower bound */
13951 getObjvalDeltaLb(set, SCIPvarGetObj(var), oldlb, newlb, &deltaval, &deltainf);
13952
13953 /* update the pseudo and loose objective values */
13954 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
13955 }
13956 }
13957
13958 return SCIP_OKAY;
13959}
13960
13961/** updates current root pseudo objective value for a global change in a variable's upper bound */
13963 SCIP_LP* lp, /**< current LP data */
13964 SCIP_SET* set, /**< global SCIP settings */
13965 SCIP_VAR* var, /**< problem variable that changed */
13966 SCIP_Real oldub, /**< old upper bound of variable */
13967 SCIP_Real newub /**< new upper bound of variable */
13968 )
13969{
13970 assert(set != NULL);
13971 assert(var != NULL);
13972
13973 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
13974 {
13975 SCIP_Real deltaval;
13976 int deltainf;
13977
13978 /* compute the pseudo objective delta due the new upper bound */
13979 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
13980
13981 /* update the root pseudo objective values */
13982 lpUpdateObjval(lp, set, var, deltaval, deltainf, FALSE, FALSE, TRUE);
13983 }
13984
13985 return SCIP_OKAY;
13986}
13987
13988/** updates current pseudo objective value for a change in a variable's upper bound */
13990 SCIP_LP* lp, /**< current LP data */
13991 SCIP_SET* set, /**< global SCIP settings */
13992 SCIP_VAR* var, /**< problem variable that changed */
13993 SCIP_Real oldub, /**< old upper bound of variable */
13994 SCIP_Real newub /**< new upper bound of variable */
13995 )
13996{
13997 assert(set != NULL);
13998 assert(var != NULL);
13999
14000 if( set->misc_exactsolve )
14001 {
14002 if( oldub != newub && SCIPvarGetObj(var) < 0.0 ) /*lint !e777*/
14003 {
14004 SCIP_CALL( lpUpdateVarProved(lp, set, var, SCIPvarGetObj(var), SCIPvarGetLbLocal(var), oldub,
14005 SCIPvarGetObj(var), SCIPvarGetLbLocal(var), newub) );
14006 }
14007 }
14008 else
14009 {
14010 if( !SCIPsetIsEQ(set, oldub, newub) && SCIPsetIsNegative(set, SCIPvarGetObj(var)) )
14011 {
14012 SCIP_Real deltaval;
14013 int deltainf;
14014
14016 assert(SCIPvarGetProbindex(var) >= 0);
14017
14018 /* compute the pseudo objective delta due the new upper bound */
14019 getObjvalDeltaUb(set, SCIPvarGetObj(var), oldub, newub, &deltaval, &deltainf);
14020
14021 /* update the pseudo and loose objective values */
14022 lpUpdateObjval(lp, set, var, deltaval, deltainf, TRUE, FALSE, FALSE);
14023 }
14024 }
14025
14026 return SCIP_OKAY;
14027}
14028
14029/** informs LP, that given variable was added to the problem */
14031 SCIP_LP* lp, /**< current LP data */
14032 SCIP_SET* set, /**< global SCIP settings */
14033 SCIP_VAR* var /**< variable that is now a LOOSE problem variable */
14034 )
14035{
14036 assert(lp != NULL);
14038 assert(SCIPvarGetProbindex(var) >= 0);
14039
14040 /* add the variable to the loose objective value sum */
14041 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, 0.0, SCIPvarGetObj(var)) );
14042
14043 /* update the loose variables counter */
14045 lp->nloosevars++;
14046
14047 return SCIP_OKAY;
14048}
14049
14050/** informs LP, that given variable is to be deleted from the problem */
14052 SCIP_LP* lp, /**< current LP data */
14053 SCIP_SET* set, /**< global SCIP settings */
14054 SCIP_VAR* var /**< variable that will be deleted from the problem */
14055 )
14056{
14057 assert(lp != NULL);
14059 assert(SCIPvarGetProbindex(var) >= 0);
14060
14061 /* subtract the variable from the loose objective value sum */
14062 SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, SCIPvarGetObj(var), 0.0) );
14063
14064 /* update the loose variables counter */
14066 {
14068 }
14069
14070 return SCIP_OKAY;
14071}
14072
14073/** informs LP, that given formerly loose problem variable is now a column variable */
14074static
14076 SCIP_LP* lp, /**< current LP data */
14077 SCIP_SET* set, /**< global SCIP settings */
14078 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14079 )
14080{
14081 SCIP_Real obj;
14082 SCIP_Real lb;
14083 SCIP_Real ub;
14084
14085 assert(lp != NULL);
14086 assert(lp->nloosevars > 0);
14088 assert(SCIPvarGetProbindex(var) >= 0);
14089 assert(lp->looseobjvalinf >= 0);
14090
14091 obj = SCIPvarGetObj(var);
14092
14093 /* update loose objective value */
14094 if( SCIPsetIsPositive(set, obj) )
14095 {
14096 lb = SCIPvarGetLbLocal(var);
14097 if( SCIPsetIsInfinity(set, -lb) )
14098 lp->looseobjvalinf--;
14099 else
14100 lpUpdateObjval(lp, set, var, -lb * obj, 0, FALSE, TRUE, FALSE);
14101 }
14102 else if( SCIPsetIsNegative(set, obj) )
14103 {
14104 ub = SCIPvarGetUbLocal(var);
14105 if( SCIPsetIsInfinity(set, ub) )
14106 lp->looseobjvalinf--;
14107 else
14108 lpUpdateObjval(lp, set, var, -ub * obj, 0, FALSE, TRUE, FALSE);
14109 }
14110
14112
14113 assert(lp->looseobjvalinf >= 0);
14114
14115 return SCIP_OKAY;
14116}
14117
14118/** informs LP, that given formerly loose problem variable is now a column variable
14119 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14120 */
14121static
14123 SCIP_LP* lp, /**< current LP data */
14124 SCIP_SET* set, /**< global SCIP settings */
14125 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14126 )
14127{
14128 SCIP_INTERVAL bd;
14129 SCIP_INTERVAL ob;
14130 SCIP_INTERVAL prod;
14131 SCIP_INTERVAL loose;
14132 SCIP_Real obj;
14133 SCIP_Real lb;
14134 SCIP_Real ub;
14135
14136 assert(lp != NULL);
14137 assert(lp->nloosevars > 0);
14139 assert(SCIPvarGetProbindex(var) >= 0);
14140
14141 obj = SCIPvarGetObj(var);
14142
14143 SCIPintervalSet(&loose, lp->looseobjval);
14144
14145 /* update loose objective value corresponding to the deletion of variable */
14146 if( obj > 0.0 )
14147 {
14148 lb = SCIPvarGetLbLocal(var);
14149 if( SCIPsetIsInfinity(set, -lb) )
14150 lp->looseobjvalinf--;
14151 else
14152 {
14153 SCIPintervalSet(&bd, lb);
14154 SCIPintervalSet(&ob, obj);
14155 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14156 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= lb * obj; */
14157 }
14158 }
14159 else if( SCIPsetIsNegative(set, obj) )
14160 {
14161 ub = SCIPvarGetUbLocal(var);
14162 if( SCIPsetIsInfinity(set, ub) )
14163 lp->looseobjvalinf--;
14164 else
14165 {
14166 SCIPintervalSet(&bd, ub);
14167 SCIPintervalSet(&ob, obj);
14168 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14169 SCIPintervalSub(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval -= ub * obj; */
14170 }
14171 }
14172 lp->nloosevars--;
14173
14174 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14175 if( lp->nloosevars == 0 )
14176 {
14177 assert(lp->looseobjvalinf == 0);
14178 lp->looseobjval = 0.0;
14179 }
14180 else
14181 lp->looseobjval = SCIPintervalGetInf(loose);
14182
14183 return SCIP_OKAY;
14184}
14185
14186/** informs LP, that given formerly loose problem variable is now a column variable */
14188 SCIP_LP* lp, /**< current LP data */
14189 SCIP_SET* set, /**< global SCIP settings */
14190 SCIP_VAR* var /**< problem variable that changed from LOOSE to COLUMN */
14191 )
14192{
14193 assert(set != NULL);
14194
14195 if( set->misc_exactsolve )
14196 {
14198 }
14199 else
14200 {
14201 SCIP_CALL( lpUpdateVarColumn(lp, set, var) );
14202 }
14203
14204 return SCIP_OKAY;
14205}
14206
14207/** informs LP, that given formerly column problem variable is now again a loose variable */
14208static
14210 SCIP_LP* lp, /**< current LP data */
14211 SCIP_SET* set, /**< global SCIP settings */
14212 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14213 )
14214{
14215 SCIP_Real obj;
14216 SCIP_Real lb;
14217 SCIP_Real ub;
14218
14219 assert(lp != NULL);
14220 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14221 assert(SCIPvarGetProbindex(var) >= 0);
14222 assert(lp->looseobjvalinf >= 0);
14223
14224 obj = SCIPvarGetObj(var);
14225
14226 /* update loose objective value corresponding to the addition of variable */
14227 if( SCIPsetIsPositive(set, obj) )
14228 {
14229 lb = SCIPvarGetLbLocal(var);
14230 if( SCIPsetIsInfinity(set, -lb) )
14231 lp->looseobjvalinf++;
14232 else
14233 lpUpdateObjval(lp, set, var, lb * obj, 0, FALSE, TRUE, FALSE);
14234 }
14235 else if( SCIPsetIsNegative(set, obj) )
14236 {
14237 ub = SCIPvarGetUbLocal(var);
14238 if( SCIPsetIsInfinity(set, ub) )
14239 lp->looseobjvalinf++;
14240 else
14241 lpUpdateObjval(lp, set, var, ub * obj, 0, FALSE, TRUE, FALSE);
14242 }
14243 lp->nloosevars++;
14244
14245 assert(lp->looseobjvalinf >= 0);
14246
14247 return SCIP_OKAY;
14248}
14249
14250/** informs LP, that given formerly column problem variable is now again a loose variable
14251 * pseudo objective value is calculated with interval arithmetics to get a proved lower bound
14252 */
14253static
14255 SCIP_LP* lp, /**< current LP data */
14256 SCIP_SET* set, /**< global SCIP settings */
14257 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14258 )
14259{
14260 SCIP_INTERVAL bd;
14261 SCIP_INTERVAL ob;
14262 SCIP_INTERVAL prod;
14263 SCIP_INTERVAL loose;
14264 SCIP_Real obj;
14265 SCIP_Real lb;
14266 SCIP_Real ub;
14267
14268 assert(lp != NULL);
14269 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
14270 assert(SCIPvarGetProbindex(var) >= 0);
14271
14272 obj = SCIPvarGetObj(var);
14273
14274 SCIPintervalSet(&loose, lp->looseobjval);
14275
14276 /* update loose objective value corresponding to the deletion of variable */
14277 if( obj > 0.0 )
14278 {
14279 lb = SCIPvarGetLbLocal(var);
14280 if( SCIPsetIsInfinity(set, -lb) )
14281 lp->looseobjvalinf++;
14282 else
14283 {
14284 SCIPintervalSet(&bd, lb);
14285 SCIPintervalSet(&ob, obj);
14286 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14287 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += lb * obj; */
14288 }
14289 }
14290 else if( SCIPsetIsNegative(set, obj) )
14291 {
14292 ub = SCIPvarGetUbLocal(var);
14293 if( SCIPsetIsInfinity(set, ub) )
14294 lp->looseobjvalinf++;
14295 else
14296 {
14297 SCIPintervalSet(&bd, ub);
14298 SCIPintervalSet(&ob, obj);
14299 SCIPintervalMul(SCIPsetInfinity(set), &prod, bd, ob);
14300 SCIPintervalAdd(SCIPsetInfinity(set), &loose, loose, prod); /* lp->looseobjval += ub * obj; */
14301 }
14302 }
14303 lp->nloosevars++;
14304
14305 lp->looseobjval = SCIPintervalGetInf(loose);
14306
14307 return SCIP_OKAY;
14308}
14309
14310/** informs LP, that given formerly column problem variable is now again a loose variable */
14312 SCIP_LP* lp, /**< current LP data */
14313 SCIP_SET* set, /**< global SCIP settings */
14314 SCIP_VAR* var /**< problem variable that changed from COLUMN to LOOSE */
14315 )
14316{
14317 assert(set != NULL);
14318
14319 if( set->misc_exactsolve )
14320 {
14322 }
14323 else
14324 {
14325 SCIP_CALL( lpUpdateVarLoose(lp, set, var) );
14326 }
14327
14328 return SCIP_OKAY;
14329}
14330
14331/** decrease the number of loose variables by one */
14333 SCIP_LP* lp /**< current LP data */
14334 )
14335{
14336 assert(lp != NULL);
14337 assert(lp->nloosevars > 0);
14338
14339 lp->nloosevars--;
14340
14341 /* get rid of numerical problems: set loose objective value explicitly to zero, if no loose variables remain */
14342 if( lp->nloosevars == 0 )
14343 {
14344 assert(lp->looseobjvalinf == 0);
14345 lp->looseobjval = 0.0;
14346 }
14347}
14348
14349/** stores the LP solution in the columns and rows */
14351 SCIP_LP* lp, /**< current LP data */
14352 SCIP_SET* set, /**< global SCIP settings */
14353 SCIP_STAT* stat, /**< problem statistics */
14354 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14355 SCIP_Bool* dualfeasible /**< pointer to store whether the solution is dual feasible, or NULL */
14356 )
14357{
14358 SCIP_COL** lpicols;
14359 SCIP_ROW** lpirows;
14360 SCIP_Real* primsol;
14361 SCIP_Real* dualsol;
14362 SCIP_Real* activity = NULL;
14363 SCIP_Real* redcost;
14364 SCIP_Real primalbound;
14365 SCIP_Real dualbound;
14366 SCIP_Bool stillprimalfeasible;
14367 SCIP_Bool stilldualfeasible;
14368 int* cstat;
14369 int* rstat;
14370 SCIP_Longint lpcount;
14371 int nlpicols;
14372 int nlpirows;
14373 int c;
14374 int r;
14375
14376 assert(lp != NULL);
14377 assert(lp->flushed);
14378 assert(lp->solved);
14379 assert(set != NULL);
14380 assert(stat != NULL);
14381 assert(lp->validsollp <= stat->lpcount);
14382
14383 assert(lp->lpsolstat == SCIP_LPSOLSTAT_OPTIMAL);
14384
14385 /* initialize return and feasibility flags; if primal oder dual feasibility shall not be checked, we set the
14386 * corresponding flag immediately to FALSE to skip all checks
14387 */
14388 if( primalfeasible == NULL )
14389 stillprimalfeasible = FALSE;
14390 else
14391 {
14392 *primalfeasible = TRUE;
14393 stillprimalfeasible = TRUE;
14394 }
14395 if( dualfeasible == NULL )
14396 stilldualfeasible = FALSE;
14397 else
14398 {
14399 *dualfeasible = TRUE;
14400 stilldualfeasible = TRUE;
14401 }
14402
14403 /* check if the values are already calculated */
14404 if( lp->validsollp == stat->lpcount )
14405 return SCIP_OKAY;
14406 lp->validsollp = stat->lpcount;
14407
14408 SCIPsetDebugMsg(set, "getting new LP solution %" SCIP_LONGINT_FORMAT " for solstat %d\n",
14409 stat->lpcount, SCIPlpGetSolstat(lp));
14410
14411 lpicols = lp->lpicols;
14412 lpirows = lp->lpirows;
14413 nlpicols = lp->nlpicols;
14414 nlpirows = lp->nlpirows;
14415 lpcount = stat->lpcount;
14416
14417 /* get temporary memory */
14418 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, nlpicols) );
14419 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualsol, nlpirows) );
14420#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14421 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, nlpirows) );
14422#endif
14423 SCIP_CALL( SCIPsetAllocBufferArray(set, &redcost, nlpicols) );
14424 SCIP_CALL( SCIPsetAllocBufferArray(set, &cstat, nlpicols) );
14425 SCIP_CALL( SCIPsetAllocBufferArray(set, &rstat, nlpirows) );
14426
14427 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, dualsol, activity, redcost) );
14428 if( lp->solisbasic )
14429 {
14430 SCIP_CALL( SCIPlpiGetBase(lp->lpi, cstat, rstat) );
14431 }
14432 else
14433 {
14434 BMSclearMemoryArray(cstat, nlpicols);
14435 BMSclearMemoryArray(rstat, nlpirows);
14436 }
14437
14438 primalbound = 0.0;
14439 dualbound = 0.0;
14440
14441 /* copy primal solution and reduced costs into columns */
14442 for( c = 0; c < nlpicols; ++c )
14443 {
14444 assert( 0 <= cstat[c] && cstat[c] < 4 );
14445 lpicols[c]->primsol = primsol[c];
14446 if( !SCIPisFinite(lpicols[c]->primsol) )
14447 {
14448 /* calculating with nan or +/-inf can have many unexpected effects
14449 * thus change the solution here to a reasonable value (0.0) and declare it as neither primal nor dual feasible
14450 * this should trigger a resolve of the LP, or a stop with an LP error
14451 */
14452 stillprimalfeasible = FALSE;
14453 stilldualfeasible = FALSE;
14454 lpicols[c]->primsol = 0.0;
14455 SCIPsetDebugMsg(set, " col <%s>: primsol=%.9f is not finite\n", SCIPvarGetName(lpicols[c]->var), primsol[c]);
14456 }
14457 lpicols[c]->minprimsol = MIN(lpicols[c]->minprimsol, primsol[c]);
14458 lpicols[c]->maxprimsol = MAX(lpicols[c]->maxprimsol, primsol[c]);
14459 lpicols[c]->redcost = redcost[c];
14460 lpicols[c]->basisstatus = (unsigned int) cstat[c];
14461 lpicols[c]->validredcostlp = lpcount;
14462 if( stillprimalfeasible )
14463 {
14464 stillprimalfeasible =
14465 (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb))
14466 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub));
14467 primalbound += (lpicols[c]->primsol * lpicols[c]->obj);
14468 }
14469 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14470 {
14471 double compslack;
14472
14473 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14474 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinty() for unbounded
14475 * variables, which would magnify even the tiniest violation in the dual multiplier
14476 */
14477 if( stilldualfeasible )
14478 {
14479 compslack = MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost;
14480 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14481 }
14482 if( stilldualfeasible )
14483 {
14484 compslack = MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost;
14485 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14486 }
14487
14488 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14489 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14490 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14491 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14492 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14493 !SCIPsetIsDualfeasPositive(set, MIN((lpicols[c]->primsol - lpicols[c]->lb), 1.0) * lpicols[c]->redcost),
14494 !SCIPsetIsDualfeasNegative(set, MIN((lpicols[c]->ub - lpicols[c]->primsol), 1.0) * lpicols[c]->redcost),
14495 dualfeasible != NULL ? stilldualfeasible : TRUE);
14496 }
14497 else
14498 {
14499 /* if dual feasibility check is disabled, set reduced costs of basic variables to 0 */
14500 if( dualfeasible == NULL && lpicols[c]->basisstatus == (unsigned int) SCIP_BASESTAT_BASIC )
14501 {
14502 lpicols[c]->redcost = 0.0;
14503 }
14504
14505 /* complementary slackness means that if a variable is not at its lower or upper bound, its reduced costs
14506 * must be non-positive or non-negative, respectively; in particular, if a variable is strictly within its
14507 * bounds, its reduced cost must be zero
14508 */
14509 if( stilldualfeasible
14510 && (SCIPsetIsInfinity(set, -lpicols[c]->lb) || SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb)) )
14511 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost);
14512 if( stilldualfeasible
14513 && (SCIPsetIsInfinity(set, lpicols[c]->ub) || SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub)) )
14514 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost);
14515
14516 SCIPsetDebugMsg(set, " col <%s> [%.9g,%.9g]: primsol=%.9f, redcost=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14517 SCIPvarGetName(lpicols[c]->var), lpicols[c]->lb, lpicols[c]->ub, lpicols[c]->primsol, lpicols[c]->redcost,
14518 SCIPlpIsFeasGE(set, lp, lpicols[c]->primsol, lpicols[c]->lb),
14519 SCIPlpIsFeasLE(set, lp, lpicols[c]->primsol, lpicols[c]->ub),
14520 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14521 !SCIPlpIsFeasGT(set, lp, lpicols[c]->primsol, lpicols[c]->lb) || !SCIPsetIsDualfeasPositive(set, lpicols[c]->redcost),
14522 !SCIPlpIsFeasLT(set, lp, lpicols[c]->primsol, lpicols[c]->ub) || !SCIPsetIsDualfeasNegative(set, lpicols[c]->redcost),
14523 dualfeasible != NULL ? stilldualfeasible : TRUE);
14524 }
14525
14526 /* we intentionally use an exact positive/negative check because ignoring small reduced cost values may lead to a
14527 * wrong bound value; if the corresponding bound is +/-infinity, we use zero reduced cost (if stilldualfeasible is
14528 * TRUE, we are in the case that the reduced cost is tiny with wrong sign)
14529 */
14530 if( stilldualfeasible )
14531 {
14532 if( lpicols[c]->redcost > 0.0 && !SCIPsetIsInfinity(set, -lpicols[c]->lb) )
14533 dualbound += (lpicols[c]->redcost * lpicols[c]->lb);
14534 else if( lpicols[c]->redcost < 0.0 && !SCIPsetIsInfinity(set, lpicols[c]->ub) )
14535 dualbound += (lpicols[c]->redcost * lpicols[c]->ub);
14536 }
14537 }
14538
14539 /* copy dual solution and activities into rows */
14540 for( r = 0; r < nlpirows; ++r )
14541 {
14542 assert( 0 <= rstat[r] && rstat[r] < 4 );
14543 lpirows[r]->dualsol = dualsol[r];
14544#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14545 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14546#else
14547 /* calculate row activity if invalid */
14548 if( lpirows[r]->validactivitylp != stat->lpcount )
14549 SCIProwRecalcLPActivity(lpirows[r], stat);
14550#endif
14551 lpirows[r]->basisstatus = (unsigned int) rstat[r]; /*lint !e732*/
14552 lpirows[r]->validactivitylp = lpcount;
14553 if( stillprimalfeasible )
14554 {
14555 stillprimalfeasible =
14556 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs))
14557 && (SCIPsetIsInfinity(set, lpirows[r]->rhs) || SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs));
14558 }
14559 if( lp->lastlpalgo == SCIP_LPALGO_BARRIER )
14560 {
14561 double compslack;
14562
14563 /* complementary slackness in barrier solutions is measured as product of primal slack and dual multiplier;
14564 * we use a slack of at most 1, because otherwise we multiply by something like SCIPinfinity() for unbounded
14565 * variables, which would magnify even the tiniest violation in the dual multiplier
14566 */
14567 if( stilldualfeasible )
14568 {
14569 compslack = MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol;
14570 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, compslack);
14571 }
14572 if( stilldualfeasible )
14573 {
14574 compslack = MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol;
14575 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, compslack);
14576 }
14577
14578 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g]: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14579 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->activity, lpirows[r]->dualsol,
14580 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14581 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14582 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14583 !SCIPsetIsDualfeasPositive(set, MIN((lpirows[r]->activity - lpirows[r]->lhs), 1.0) * lpirows[r]->dualsol),
14584 !SCIPsetIsDualfeasNegative(set, MIN((lpirows[r]->rhs - lpirows[r]->activity), 1.0) * lpirows[r]->dualsol),
14585 dualfeasible != NULL ? stilldualfeasible : TRUE);
14586 }
14587 else
14588 {
14589 /* complementary slackness means that if the activity of a row is not at its left-hand or right-hand side,
14590 * its dual multiplier must be non-positive or non-negative, respectively; in particular, if the activity is
14591 * strictly within left-hand and right-hand side, its dual multiplier must be zero
14592 */
14593 if( stilldualfeasible &&
14594 (SCIPsetIsInfinity(set, -lpirows[r]->lhs) || SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs)) )
14595 stilldualfeasible = !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol);
14596 if( stilldualfeasible &&
14597 (SCIPsetIsInfinity(set,lpirows[r]->rhs) || SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs)) )
14598 stilldualfeasible = !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol);
14599
14600 SCIPsetDebugMsg(set, " row <%s> [%.9g,%.9g] + %.9g: activity=%.9f, dualsol=%.9f, pfeas=%u/%u(%u), dfeas=%d/%d(%u)\n",
14601 lpirows[r]->name, lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, lpirows[r]->activity, lpirows[r]->dualsol,
14602 SCIPlpIsFeasGE(set, lp, lpirows[r]->activity, lpirows[r]->lhs),
14603 SCIPlpIsFeasLE(set, lp, lpirows[r]->activity, lpirows[r]->rhs),
14604 primalfeasible != NULL ? stillprimalfeasible : TRUE,
14605 !SCIPlpIsFeasGT(set, lp, lpirows[r]->activity, lpirows[r]->lhs) || !SCIPsetIsDualfeasPositive(set, lpirows[r]->dualsol),
14606 !SCIPlpIsFeasLT(set, lp, lpirows[r]->activity, lpirows[r]->rhs) || !SCIPsetIsDualfeasNegative(set, lpirows[r]->dualsol),
14607 dualfeasible != NULL ? stilldualfeasible : TRUE);
14608 }
14609
14610 /* we intentionally use an exact positive/negative check because ignoring small dual multipliers may lead to a
14611 * wrong bound value; if the corresponding side is +/-infinity, we use a zero dual multiplier (if
14612 * stilldualfeasible is TRUE, we are in the case that the dual multiplier is tiny with wrong sign)
14613 */
14614 if( stilldualfeasible )
14615 {
14616 if( lpirows[r]->dualsol > 0.0 && !SCIPsetIsInfinity(set, -lpirows[r]->lhs) )
14617 dualbound += (lpirows[r]->dualsol * (lpirows[r]->lhs - lpirows[r]->constant));
14618 else if( lpirows[r]->dualsol < 0.0 && !SCIPsetIsInfinity(set, lpirows[r]->rhs) )
14619 dualbound += (lpirows[r]->dualsol * (lpirows[r]->rhs - lpirows[r]->constant));
14620 }
14621 }
14622
14623 /* if the objective value returned by the LP solver is smaller than the internally computed primal bound, then we
14624 * declare the solution primal infeasible; we assume primalbound and lp->lpobjval to be equal if they are both +/-
14625 * infinity
14626 */
14627 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14628 if( stillprimalfeasible && !(SCIPsetIsInfinity(set, primalbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14629 && !(SCIPsetIsInfinity(set, -primalbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14630 {
14631 stillprimalfeasible = SCIPsetIsFeasLE(set, primalbound, lp->lpobjval);
14632 SCIPsetDebugMsg(set, " primalbound=%.9f, lpbound=%.9g, pfeas=%u(%u)\n", primalbound, lp->lpobjval,
14633 SCIPsetIsFeasLE(set, primalbound, lp->lpobjval), primalfeasible != NULL ? stillprimalfeasible : TRUE);
14634 }
14635
14636 /* if the objective value returned by the LP solver is smaller than the internally computed dual bound, we declare
14637 * the solution dual infeasible; we assume dualbound and lp->lpobjval to be equal if they are both +/- infinity
14638 */
14639 /**@todo alternatively, if otherwise the LP solution is feasible, we could simply update the objective value */
14640 if( stilldualfeasible && !(SCIPsetIsInfinity(set, dualbound) && SCIPsetIsInfinity(set, lp->lpobjval))
14641 && !(SCIPsetIsInfinity(set, -dualbound) && SCIPsetIsInfinity(set, -lp->lpobjval)) )
14642 {
14643 stilldualfeasible = SCIPsetIsFeasGE(set, dualbound, lp->lpobjval);
14644 SCIPsetDebugMsg(set, " dualbound=%.9f, lpbound=%.9g, dfeas=%u(%u)\n", dualbound, lp->lpobjval,
14645 SCIPsetIsFeasGE(set, dualbound, lp->lpobjval), dualfeasible != NULL ? stilldualfeasible : TRUE);
14646 }
14647
14648 if( primalfeasible != NULL )
14649 *primalfeasible = stillprimalfeasible;
14650 if( dualfeasible != NULL )
14651 *dualfeasible = stilldualfeasible;
14652
14653 /* free temporary memory */
14654 SCIPsetFreeBufferArray(set, &rstat);
14655 SCIPsetFreeBufferArray(set, &cstat);
14656 SCIPsetFreeBufferArray(set, &redcost);
14657#ifdef SCIP_USE_LPSOLVER_ACTIVITY
14658 SCIPsetFreeBufferArray(set, &activity);
14659#endif
14660 SCIPsetFreeBufferArray(set, &dualsol);
14661 SCIPsetFreeBufferArray(set, &primsol);
14662
14663 return SCIP_OKAY;
14664}
14665
14666/** stores LP solution with infinite objective value in the columns and rows */
14668 SCIP_LP* lp, /**< current LP data */
14669 SCIP_SET* set, /**< global SCIP settings */
14670 SCIP_STAT* stat, /**< problem statistics */
14671 SCIP_Bool* primalfeasible, /**< pointer to store whether the solution is primal feasible, or NULL */
14672 SCIP_Bool* rayfeasible /**< pointer to store whether the primal ray is a feasible unboundedness proof, or NULL */
14673 )
14674{
14675 SCIP_COL** lpicols;
14676 SCIP_ROW** lpirows;
14677 SCIP_Real* primsol;
14678 SCIP_Real* activity;
14679 SCIP_Real* ray;
14680 SCIP_Real rayobjval;
14681 SCIP_Real rayscale;
14682 SCIP_Longint lpcount;
14683 SCIP_COL* col;
14684 int nlpicols;
14685 int nlpirows;
14686 int c;
14687 int r;
14688
14689 assert(lp != NULL);
14690 assert(lp->flushed);
14691 assert(lp->solved);
14693 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
14694 assert(set != NULL);
14695 assert(stat != NULL);
14696 assert(lp->validsollp <= stat->lpcount);
14697
14698 if( primalfeasible != NULL )
14699 *primalfeasible = TRUE;
14700 if( rayfeasible != NULL )
14701 *rayfeasible = TRUE;
14702
14703 /* check if the values are already calculated */
14704 if( lp->validsollp == stat->lpcount )
14705 return SCIP_OKAY;
14706 lp->validsollp = stat->lpcount;
14707
14708 /* check if the LP solver is able to provide a primal unbounded ray */
14709 if( !SCIPlpiHasPrimalRay(lp->lpi) )
14710 {
14711 SCIPerrorMessage("LP solver has no primal ray to prove unboundedness.\n");
14712 return SCIP_LPERROR;
14713 }
14714
14715 SCIPsetDebugMsg(set, "getting new unbounded LP solution %" SCIP_LONGINT_FORMAT "\n", stat->lpcount);
14716
14717 /* get temporary memory */
14718 SCIP_CALL( SCIPsetAllocBufferArray(set, &primsol, lp->nlpicols) );
14719 SCIP_CALL( SCIPsetAllocBufferArray(set, &activity, lp->nlpirows) );
14721
14722 /* get primal unbounded ray */
14723 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, ray) );
14724
14725 lpicols = lp->lpicols;
14726 lpirows = lp->lpirows;
14727 nlpicols = lp->nlpicols;
14728 nlpirows = lp->nlpirows;
14729 lpcount = stat->lpcount;
14730
14731 /* calculate the objective value decrease of the ray and heuristically try to construct primal solution */
14732 rayobjval = 0.0;
14733 for( c = 0; c < nlpicols; ++c )
14734 {
14735 assert(lpicols[c] != NULL);
14736 assert(lpicols[c]->var != NULL);
14737
14738 col = lpicols[c];
14739
14740 /* there should only be a nonzero value in the ray if there is no finite bound in this direction */
14741 if( rayfeasible != NULL )
14742 {
14743 *rayfeasible = *rayfeasible
14744 && (!SCIPsetIsNegative(set, ray[c]) || SCIPsetIsInfinity(set, -col->lb))
14745 && (!SCIPsetIsPositive(set, ray[c]) || SCIPsetIsInfinity(set, col->ub));
14746 }
14747
14748 if( ! SCIPsetIsZero(set, ray[c]) )
14749 rayobjval += ray[c] * col->obj;
14750
14751 /* Many LP solvers cannot directly provide a feasible solution if they detected unboundedness. We therefore first
14752 * heuristically try to construct a primal solution.
14753 */
14754 primsol[c] = 0.0;
14755 if( SCIPsetIsFeasZero(set, ray[c]) )
14756 {
14757 /* if the ray component is 0, we try to satisfy as many rows as possible */
14758 if( SCIPvarGetNLocksDown(col->var) == 0 && ! SCIPsetIsInfinity(set, -col->lb) )
14759 primsol[c] = col->lb;
14760 else if( SCIPvarGetNLocksUp(col->var) == 0 && ! SCIPsetIsInfinity(set, col->ub) )
14761 primsol[c] = col->ub;
14762 }
14763
14764 /* make sure we respect the bounds */
14765 primsol[c] = MAX(primsol[c], col->lb);
14766 primsol[c] = MIN(primsol[c], col->ub);
14767
14768 assert( SCIPlpIsFeasGE(set, lp, primsol[c], col->lb) && SCIPlpIsFeasLE(set, lp, primsol[c], col->ub) );
14769 }
14770
14771 /* check feasibility of heuristic primal solution */
14772 for( r = 0; r < nlpirows; ++r )
14773 {
14774 SCIP_Real act;
14775 SCIP_ROW* row;
14776
14777 row = lpirows[r];
14778 assert( row != NULL );
14779 act = row->constant;
14780
14781 for( c = 0; c < row->nlpcols; ++c )
14782 {
14783 col = row->cols[c];
14784
14785 assert( col != NULL );
14786 assert( col->lppos >= 0 );
14787 assert( row->linkpos[c] >= 0 );
14788 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14789
14790 act += row->vals[c] * primsol[col->lppos];
14791 }
14792
14793 if( row->nunlinked > 0 )
14794 {
14795 for( c = row->nlpcols; c < row->len; ++c )
14796 {
14797 col = row->cols[c];
14798 assert( col != NULL );
14799
14800 if( col->lppos >= 0 )
14801 act += row->vals[c] * primsol[col->lppos];
14802 }
14803 }
14804
14805 /* check feasibility */
14806 if( (! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, act, row->lhs) ) ||
14807 (! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, act, row->rhs) ) )
14808 break;
14809 }
14810
14811 /* if heuristic primal solution is not feasible, try to obtain solution from LPI */
14812 if( r < nlpirows )
14813 {
14814 /* get primal feasible point */
14815 SCIP_CALL( SCIPlpiGetSol(lp->lpi, NULL, primsol, NULL, NULL, NULL) );
14816
14817 /* check bounds of primal solution */
14818 if( primalfeasible != NULL )
14819 {
14820 assert( *primalfeasible );
14821 for( c = 0; c < nlpicols; ++c )
14822 {
14823 assert( lpicols[c] != NULL );
14824 assert( lpicols[c]->var != NULL );
14825
14826 /* check whether primal solution satisfies the bounds; note that we also ensure that the primal
14827 * solution is within SCIP's infinity bounds; otherwise the rayscale below is not well-defined */
14828 if( SCIPsetIsInfinity(set, REALABS(primsol[c])) || SCIPlpIsFeasLT(set, lp, primsol[c], lpicols[c]->lb) ||
14829 SCIPlpIsFeasGT(set, lp, primsol[c], lpicols[c]->ub) )
14830 {
14831 *primalfeasible = FALSE;
14832 break;
14833 }
14834 }
14835 }
14836 }
14837
14838 /* compute activity and check feasibility of primal solution and ray */
14839 for( r = 0; r < nlpirows; ++r )
14840 {
14841 SCIP_Real primact;
14842 SCIP_Real rayact = 0.0;
14843 SCIP_ROW* row;
14844
14845 row = lpirows[r];
14846 assert( row != NULL );
14847
14848 primact = row->constant;
14849
14850 for( c = 0; c < row->nlpcols; ++c )
14851 {
14852 col = row->cols[c];
14853
14854 assert( col != NULL );
14855 assert( col->lppos >= 0 );
14856 assert( row->linkpos[c] >= 0 );
14857 assert( primsol[col->lppos] != SCIP_INVALID ); /*lint !e777*/
14858
14859 primact += row->vals[c] * primsol[col->lppos];
14860 rayact += row->vals[c] * ray[col->lppos];
14861 }
14862
14863 if( row->nunlinked > 0 )
14864 {
14865 for( c = row->nlpcols; c < row->len; ++c )
14866 {
14867 col = row->cols[c];
14868 assert( col != NULL );
14869
14870 if( col->lppos >= 0 )
14871 {
14872 primact += row->vals[c] * primsol[col->lppos];
14873 rayact += row->vals[c] * ray[col->lppos];
14874 }
14875 }
14876 }
14877
14878 /* check feasibility of primal solution */
14879 if( primalfeasible != NULL && *primalfeasible )
14880 {
14881 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, primact, row->lhs) ) ||
14882 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, primact, row->rhs) ) )
14883 *primalfeasible = FALSE;
14884 }
14885
14886 /* check feasibility of ray */
14887 if( rayfeasible != NULL && *rayfeasible )
14888 {
14889 if(( ! SCIPsetIsInfinity(set, -row->lhs) && SCIPlpIsFeasLT(set, lp, rayact, 0.0) ) ||
14890 ( ! SCIPsetIsInfinity(set, row->rhs) && SCIPlpIsFeasGT(set, lp, rayact, 0.0) ) )
14891 *rayfeasible = FALSE;
14892 }
14893
14894 /* store activity of primal solution */
14895 activity[r] = primact;
14896 }
14897
14898 if( primalfeasible != NULL && !(*primalfeasible) )
14899 {
14900 /* if the finite point is already infeasible, we do not have to add the ray */
14901 rayscale = 0.0;
14902 }
14903 else if( rayfeasible != NULL && !(*rayfeasible) )
14904 {
14905 /* if the ray is already infeasible (due to numerics), we do not want to add the ray */
14906 rayscale = 0.0;
14907 }
14908 else if( !SCIPsetIsNegative(set, rayobjval) )
14909 {
14910 /* due to numerical problems, the objective of the ray might be nonnegative
14911 *
14912 * @todo How to check for negative objective value here?
14913 */
14914 if( rayfeasible != NULL )
14915 *rayfeasible = FALSE;
14916
14917 rayscale = 0.0;
14918 }
14919 else
14920 {
14921 assert(rayobjval != 0.0);
14922
14923 /* scale the ray, such that the resulting point has infinite objective value */
14924 rayscale = -2.0 * SCIPsetInfinity(set) / rayobjval;
14925 assert(SCIPsetIsFeasPositive(set, rayscale));
14926
14927 /* ensure that unbounded point does not violate the bounds of the variables */
14928 for( c = 0; c < nlpicols; ++c )
14929 {
14930 if( SCIPsetIsPositive(set, ray[c]) )
14931 {
14932 if( !SCIPsetIsInfinity(set, primsol[c]) )
14933 rayscale = MIN(rayscale, (lpicols[c]->ub - primsol[c]) / ray[c]);
14934 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14935 else
14936 {
14937 assert(SCIPsetIsInfinity(set, lpicols[c]->ub));
14938 rayscale = MIN(rayscale, 1.0 / ray[c]);
14939 }
14940 }
14941 else if( SCIPsetIsNegative(set, ray[c]) )
14942 {
14943 if( !SCIPsetIsInfinity(set, -primsol[c]) )
14944 rayscale = MIN(rayscale, (lpicols[c]->lb - primsol[c]) / ray[c]);
14945 /* if primsol is infinity, as well as the bound, don't scale the ray to 0 */
14946 else
14947 {
14948 assert(SCIPsetIsInfinity(set, -lpicols[c]->lb));
14949 rayscale = MIN(rayscale, -1.0 / ray[c]);
14950 }
14951 }
14952
14953 assert(SCIPsetIsFeasPositive(set, rayscale));
14954 }
14955 }
14956
14957 SCIPsetDebugMsg(set, "unbounded LP solution: rayobjval=%f, rayscale=%f\n", rayobjval, rayscale);
14958
14959 /* calculate the unbounded point: x' = x + rayscale * ray */
14960 /* Note: We do not check the feasibility of the unbounded solution, because it will likely be infeasible due to the
14961 * typically large values in scaling. */
14962 for( c = 0; c < nlpicols; ++c )
14963 {
14964 if( SCIPsetIsZero(set, ray[c]) )
14965 lpicols[c]->primsol = primsol[c];
14966 else
14967 {
14968 SCIP_Real primsolval;
14969 primsolval = primsol[c] + rayscale * ray[c];
14970 lpicols[c]->primsol = MAX(-SCIPsetInfinity(set), MIN(SCIPsetInfinity(set), primsolval)); /*lint !e666*/
14971 }
14972 lpicols[c]->redcost = SCIP_INVALID;
14973 lpicols[c]->validredcostlp = -1;
14974 }
14975
14976 /* transfer solution */
14977 for( r = 0; r < nlpirows; ++r )
14978 {
14979 lpirows[r]->dualsol = SCIP_INVALID;
14980 lpirows[r]->activity = activity[r] + lpirows[r]->constant;
14981 lpirows[r]->validactivitylp = lpcount;
14982 }
14983
14984 /* free temporary memory */
14986 SCIPsetFreeBufferArray(set, &activity);
14987 SCIPsetFreeBufferArray(set, &primsol);
14988
14989 return SCIP_OKAY;
14990}
14991
14992/** returns primal ray proving the unboundedness of the current LP */
14994 SCIP_LP* lp, /**< current LP data */
14995 SCIP_SET* set, /**< global SCIP settings */
14996 SCIP_Real* ray /**< array for storing primal ray values, they are stored w.r.t. the problem index of the variables,
14997 * so the size of this array should be at least number of active variables
14998 * (all entries have to be initialized to 0 before) */
14999 )
15000{
15001 SCIP_COL** lpicols;
15002 SCIP_Real* lpiray;
15003 SCIP_VAR* var;
15004 int nlpicols;
15005 int c;
15006
15007 assert(lp != NULL);
15008 assert(set != NULL);
15009 assert(ray != NULL);
15010 assert(lp->flushed);
15011 assert(lp->solved);
15013 assert(SCIPsetIsInfinity(set, -lp->lpobjval));
15014
15015 /* check if the LP solver is able to provide a primal unbounded ray */
15016 if( !SCIPlpiHasPrimalRay(lp->lpi) )
15017 {
15018 SCIPerrorMessage("LP solver has no primal ray for unbounded LP\n");
15019 return SCIP_LPERROR;
15020 }
15021
15022 /* get temporary memory */
15024
15025 SCIPsetDebugMsg(set, "getting primal ray values\n");
15026
15027 /* get primal unbounded ray */
15028 SCIP_CALL( SCIPlpiGetPrimalRay(lp->lpi, lpiray) );
15029
15030 lpicols = lp->lpicols;
15031 nlpicols = lp->nlpicols;
15032
15033 /* store the ray values of active problem variables */
15034 for( c = 0; c < nlpicols; c++ )
15035 {
15036 assert(lpicols[c] != NULL);
15037
15038 var = lpicols[c]->var;
15039 assert(var != NULL);
15040 assert(SCIPvarGetProbindex(var) != -1);
15041 ray[SCIPvarGetProbindex(var)] = lpiray[c];
15042 }
15043
15044 SCIPsetFreeBufferArray(set, &lpiray);
15045
15046 return SCIP_OKAY;
15047}
15048
15049/** stores the dual Farkas multipliers for infeasibility proof in rows. besides, the proof is checked for validity if
15050 * lp/checkfarkas = TRUE.
15051 *
15052 * @note the check will not be performed if @p valid is NULL.
15053 */
15055 SCIP_LP* lp, /**< current LP data */
15056 SCIP_SET* set, /**< global SCIP settings */
15057 SCIP_STAT* stat, /**< problem statistics */
15058 SCIP_Bool forcedlpsolve, /**< would SCIP abort if the LP is not solved? */
15059 SCIP_Bool* valid /**< pointer to store whether the Farkas proof is valid or NULL */
15060 )
15061{
15062 SCIP_COL** lpicols;
15063 SCIP_ROW** lpirows;
15064 SCIP_Real* dualfarkas;
15065 SCIP_Real* farkascoefs;
15066 SCIP_Real farkaslhs;
15067 SCIP_Real maxactivity;
15068 SCIP_Bool checkfarkas;
15069 int nlpicols;
15070 int nlpirows;
15071 int c;
15072 int r;
15073
15074 assert(lp != NULL);
15075 assert(lp->flushed);
15076 assert(lp->solved);
15077 assert(lp->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE);
15078 assert(set != NULL);
15079 assert(stat != NULL);
15080 assert(lp->validfarkaslp <= stat->lpcount);
15081
15082 if( valid != NULL )
15083 *valid = TRUE;
15084
15085 /* check if the values are already calculated */
15086 if( lp->validfarkaslp == stat->lpcount )
15087 return SCIP_OKAY;
15088 lp->validfarkaslp = stat->lpcount;
15089
15090 farkascoefs = NULL;
15091 maxactivity = 0.0;
15092 farkaslhs = 0.0;
15093 checkfarkas = set->lp_checkfarkas && valid != NULL;
15094
15095 /* get temporary memory */
15096 SCIP_CALL( SCIPsetAllocBufferArray(set, &dualfarkas, lp->nlpirows) );
15097
15098 if( checkfarkas )
15099 {
15100 SCIP_CALL( SCIPsetAllocBufferArray(set, &farkascoefs, lp->nlpicols) );
15101 BMSclearMemoryArray(farkascoefs, lp->nlpicols);
15102 }
15103
15104 /* get dual Farkas infeasibility proof */
15105 SCIP_CALL( SCIPlpiGetDualfarkas(lp->lpi, dualfarkas) );
15106
15107 lpicols = lp->lpicols;
15108 lpirows = lp->lpirows;
15109 nlpicols = lp->nlpicols;
15110 nlpirows = lp->nlpirows;
15111
15112 /* store infeasibility proof in rows */
15113 SCIPsetDebugMsg(set, "LP is infeasible:\n");
15114 for( r = 0; r < nlpirows; ++r )
15115 {
15116 SCIPsetDebugMsg(set, " row <%s>: dualfarkas=%f\n", lpirows[r]->name, dualfarkas[r]);
15117 lpirows[r]->dualfarkas = dualfarkas[r];
15118 lpirows[r]->dualsol = SCIP_INVALID;
15119 lpirows[r]->activity = 0.0;
15120 lpirows[r]->validactivitylp = -1L;
15121 lpirows[r]->basisstatus = (unsigned int) SCIP_BASESTAT_BASIC;
15122
15123 if( checkfarkas && dualfarkas[r] != 0.0 ) /*lint !e777*/
15124 {
15125 assert(valid != NULL);
15126 assert(farkascoefs != NULL);
15127
15128 /* the infeasibility proof would be invalid if
15129 * (i) dualfarkas[r] > 0 and lhs = -inf
15130 * (ii) dualfarkas[r] < 0 and rhs = inf
15131 * however, due to numerics we accept slightly negative / positive values
15132 */
15133 if( (SCIPsetIsDualfeasGT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15134 || (SCIPsetIsDualfeasLT(set, dualfarkas[r], 0.0) && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15135 {
15136 SCIPsetDebugMsg(set, "farkas proof is invalid: row <%s>[lhs=%g,rhs=%g,c=%g] has multiplier %g\n",
15137 SCIProwGetName(lpirows[r]), lpirows[r]->lhs, lpirows[r]->rhs, lpirows[r]->constant, dualfarkas[r]);
15138
15139 *valid = FALSE;
15140 goto TERMINATE;
15141 }
15142
15143 /* dual multipliers, for which the corresponding row side in infinite, are treated as zero if they are zero
15144 * within tolerances (see above) but slighty positive / negative
15145 */
15146 if( (dualfarkas[r] > 0.0 && SCIPsetIsInfinity(set, -lpirows[r]->lhs))
15147 || (dualfarkas[r] < 0.0 && SCIPsetIsInfinity(set, lpirows[r]->rhs)) )
15148 continue;
15149
15150 /* iterate over all columns and scale with dual solution */
15151 for( c = 0; c < lpirows[r]->len; c++ )
15152 {
15153 int pos = SCIPcolGetLPPos(lpirows[r]->cols[c]);
15154
15155 if( pos == -1 )
15156 continue;
15157
15158 assert(pos >= 0 && pos < nlpicols);
15159
15160 farkascoefs[pos] += dualfarkas[r] * lpirows[r]->vals[c];
15161 }
15162
15163 /* the row contributes with its left-hand side to the proof */
15164 if( dualfarkas[r] > 0.0 )
15165 {
15166 assert(!SCIPsetIsInfinity(set, -lpirows[r]->lhs));
15167
15168 farkaslhs += dualfarkas[r] * lpirows[r]->lhs;
15169 }
15170 /* the row contributes with its right-hand side to the proof */
15171 else if( dualfarkas[r] < 0.0 )
15172 {
15173 assert(!SCIPsetIsInfinity(set, lpirows[r]->rhs));
15174
15175 farkaslhs += dualfarkas[r] * lpirows[r]->rhs;
15176 }
15177
15178 maxactivity += dualfarkas[r] * lpirows[r]->constant;
15179 }
15180 }
15181
15182 /* set columns as invalid */
15183 for( c = 0; c < nlpicols; ++c )
15184 {
15185 lpicols[c]->primsol = SCIP_INVALID;
15186 lpicols[c]->redcost = SCIP_INVALID;
15187 lpicols[c]->validredcostlp = -1L;
15188 lpicols[c]->validfarkaslp = -1L;
15189
15190 if( checkfarkas )
15191 {
15192 assert(valid != NULL);
15193 assert(farkascoefs != NULL);
15194 assert(SCIPcolGetLPPos(lpicols[c]) == c);
15195
15196 /* skip coefficients that are too close to zero */
15197 if( SCIPsetIsDualfeasZero(set, farkascoefs[c]) )
15198 continue;
15199
15200 /* calculate the maximal activity */
15201 if( farkascoefs[c] > 0.0 )
15202 {
15203 maxactivity += farkascoefs[c] * lpicols[c]->ub;
15204
15205 if( SCIPsetIsInfinity(set, lpicols[c]->ub) )
15206 {
15207 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15208 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15209
15210 *valid = FALSE;
15211 goto TERMINATE;
15212 }
15213 }
15214 else
15215 {
15216 maxactivity += farkascoefs[c] * lpicols[c]->lb;
15217
15218 if( SCIPsetIsInfinity(set, -lpicols[c]->lb) )
15219 {
15220 SCIPsetDebugMsg(set, "farkas proof is invalid: col <%s>[lb=%g,ub=%g] has coefficient %g\n",
15221 SCIPvarGetName(SCIPcolGetVar(lpicols[c])), lpicols[c]->lb, lpicols[c]->ub, farkascoefs[c]);
15222
15223 *valid = FALSE;
15224 goto TERMINATE;
15225 }
15226 }
15227 }
15228 }
15229
15230 /* check whether the farkasproof is valid for relative epsilon tolerance to allow feasibility tightening */
15231 if( checkfarkas
15232 && ( SCIPsetIsInfinity(set, maxactivity) || SCIPsetIsInfinity(set, -farkaslhs) || SCIPsetIsRelGE(set, maxactivity, farkaslhs) ) )
15233 {
15234 assert(valid != NULL);
15235
15236 SCIPsetDebugMsg(set, "farkas proof is invalid: maxactivity=%.12f, lhs=%.12f\n", maxactivity, farkaslhs);
15237
15238 if( forcedlpsolve && SCIPsetIsLT(set, maxactivity, farkaslhs) )
15239 SCIPmessagePrintWarning(set->scip->messagehdlr, "Unreliable farkas proof forced valid, result might not be optimal.\n");
15240 else
15241 *valid = FALSE;
15242 }
15243
15244 TERMINATE:
15245 /* free temporary memory */
15246 if( checkfarkas )
15247 SCIPsetFreeBufferArray(set, &farkascoefs);
15248
15249 SCIPsetFreeBufferArray(set, &dualfarkas);
15250
15251 return SCIP_OKAY;
15252}
15253
15254/** get number of iterations used in last LP solve */
15256 SCIP_LP* lp, /**< current LP data */
15257 int* iterations /**< pointer to store the iteration count */
15258 )
15259{
15260 assert(lp != NULL);
15261
15262 SCIP_CALL( SCIPlpiGetIterations(lp->lpi, iterations) );
15263
15264 return SCIP_OKAY;
15265}
15266
15267/** increases age of columns with solution value 0.0 and basic rows with activity not at its bounds,
15268 * resets age of non-zero columns and sharp rows
15269 */
15271 SCIP_LP* lp, /**< current LP data */
15272 SCIP_STAT* stat /**< problem statistics */
15273 )
15274{
15275 SCIP_COL** lpicols;
15276 SCIP_ROW** lpirows;
15277 int nlpicols;
15278 int nlpirows;
15279 int c;
15280 int r;
15281
15282 assert(lp != NULL);
15283 assert(lp->flushed);
15284 assert(lp->solved);
15285 assert(lp->nlpicols == lp->ncols);
15286 assert(lp->nlpirows == lp->nrows);
15287 assert(stat != NULL);
15288 assert(lp->validsollp == stat->lpcount);
15289
15290 SCIPdebugMessage("updating LP ages\n");
15291
15292 lpicols = lp->lpicols;
15293 lpirows = lp->lpirows;
15294 nlpicols = lp->nlpicols;
15295 nlpirows = lp->nlpirows;
15296
15297 for( c = 0; c < nlpicols; ++c )
15298 {
15299 assert(lpicols[c] == lp->cols[c]);
15300 if( lpicols[c]->primsol == 0.0 ) /* non-basic columns to remove are exactly at 0.0 */
15301 lpicols[c]->age++;
15302 else
15303 lpicols[c]->age = 0;
15304 /*SCIPstatDebugMsg(stat, " -> col <%s>: primsol=%f, age=%d\n",
15305 SCIPvarGetName(lpicols[c]->var), lpicols[c]->primsol, lpicols[c]->age);*/
15306 }
15307
15308 for( r = 0; r < nlpirows; ++r )
15309 {
15310 lpirows[r]->nlpsaftercreation++;
15311 assert(lpirows[r] == lp->rows[r]);
15312
15313 if( lpirows[r]->dualsol == 0.0 ) /* basic rows to remove are exactly at 0.0 */
15314 {
15315 lpirows[r]->age++;
15316 }
15317 else
15318 {
15319 lpirows[r]->activeinlpcounter++;
15320 lpirows[r]->age = 0;
15321 }
15322 /*debugMsg(scip, " -> row <%s>: activity=%f, age=%d\n", lpirows[r]->name, lpirows[r]->activity, lpirows[r]->age);*/
15323 }
15324
15325 return SCIP_OKAY;
15326}
15327
15328/* deletes the marked columns from the LP and the LP interface */
15329static
15331 SCIP_LP* lp, /**< current LP data */
15332 SCIP_SET* set, /**< global SCIP settings */
15333 int* coldstat /**< deletion status of columns: 1 if column should be deleted, 0 if not */
15334 )
15335{
15336 SCIP_COL* col;
15337 int ncols;
15338 int c;
15339
15340 assert(lp != NULL);
15341 assert(lp->flushed);
15342 assert(lp->ncols == lp->nlpicols);
15343 assert(!lp->diving);
15344 assert(coldstat != NULL);
15345 assert(lp->nlazycols <= lp->ncols);
15346
15347 ncols = lp->ncols;
15348
15349 /* delete columns in LP solver */
15350 SCIP_CALL( SCIPlpiDelColset(lp->lpi, coldstat) );
15351
15352 /* update LP data respectively */
15353 for( c = 0; c < ncols; ++c )
15354 {
15355 col = lp->cols[c];
15356 assert(col != NULL);
15357 assert(col == lp->lpicols[c]);
15358 assert(coldstat[c] <= c);
15359 col->lppos = coldstat[c];
15360 if( coldstat[c] == -1 )
15361 {
15362 assert(col->removable);
15363
15364 /* mark column to be deleted from the LPI, update column arrays of all linked rows, and update the objective
15365 * function vector norms
15366 */
15367 markColDeleted(col);
15368 colUpdateDelLP(col, set);
15369 lpUpdateObjNorms(lp, set, col->unchangedobj, 0.0);
15370 col->lpdepth = -1;
15371
15372 lp->cols[c] = NULL;
15373 lp->lpicols[c] = NULL;
15374 lp->ncols--;
15375 lp->nremovablecols--;
15376 lp->nlpicols--;
15377 }
15378 else if( coldstat[c] < c )
15379 {
15380 assert(lp->cols[coldstat[c]] == NULL);
15381 assert(lp->lpicols[coldstat[c]] == NULL);
15382 lp->cols[coldstat[c]] = col;
15383 lp->lpicols[coldstat[c]] = col;
15384 lp->cols[coldstat[c]]->lppos = coldstat[c];
15385 lp->cols[coldstat[c]]->lpipos = coldstat[c];
15386 lp->cols[c] = NULL;
15387 lp->lpicols[c] = NULL;
15388 }
15389 }
15390
15391 /* remove columns which are deleted from the lazy column array */
15392 c = 0;
15393 while( c < lp->nlazycols )
15394 {
15395 if( lp->lazycols[c]->lpipos < 0 )
15396 {
15397 lp->lazycols[c] = lp->lazycols[lp->nlazycols-1];
15398 lp->nlazycols--;
15399 }
15400 else
15401 c++;
15402 }
15403
15404 /* mark LP to be unsolved */
15405 if( lp->ncols < ncols )
15406 {
15407 assert(lp->ncols == lp->nlpicols);
15408 assert(lp->nchgcols == 0);
15409 assert(lp->flushed);
15410
15411 lp->lpifirstchgcol = lp->nlpicols;
15412
15413 /* mark the current solution invalid */
15414 lp->solved = FALSE;
15415 lp->primalfeasible = FALSE;
15416 lp->primalchecked = FALSE;
15417 lp->lpobjval = SCIP_INVALID;
15419 }
15420
15422 checkLinks(lp);
15423
15424 return SCIP_OKAY;
15425}
15426
15427/* deletes the marked rows from the LP and the LP interface */
15428static
15430 SCIP_LP* lp, /**< current LP data */
15431 BMS_BLKMEM* blkmem, /**< block memory buffers */
15432 SCIP_SET* set, /**< global SCIP settings */
15433 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15434 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15435 int* rowdstat /**< deletion status of rows: 1 if row should be deleted, 0 if not */
15436 )
15437{
15438 SCIP_ROW* row;
15439 int nrows;
15440 int r;
15441
15442 assert(lp != NULL);
15443 assert(lp->flushed);
15444 assert(lp->nrows == lp->nlpirows);
15445 assert(!lp->diving);
15446 assert(rowdstat != NULL);
15447
15448 nrows = lp->nrows;
15449
15450 /* delete rows in LP solver */
15451 SCIP_CALL( SCIPlpiDelRowset(lp->lpi, rowdstat) );
15452
15453 /* update LP data respectively */
15454 for( r = 0; r < nrows; ++r )
15455 {
15456 row = lp->rows[r];
15457 assert(row == lp->lpirows[r]);
15458 assert(rowdstat[r] <= r);
15459 assert(row != NULL);
15460 row->lppos = rowdstat[r];
15461 if( rowdstat[r] == -1 )
15462 {
15463 if( row->removable )
15464 lp->nremovablerows--;
15465
15466 /* mark row to be deleted from the LPI and update row arrays of all linked columns */
15467 markRowDeleted(row);
15468 rowUpdateDelLP(row);
15469 row->lpdepth = -1;
15470
15471 /* check, if row deletion events are tracked
15472 * if so, issue ROWDELETEDLP event
15473 */
15474 if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDLP) != 0 )
15475 {
15476 SCIP_EVENT* event;
15477
15478 SCIP_CALL( SCIPeventCreateRowDeletedLP(&event, blkmem, row) );
15479 SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
15480 }
15481
15482 SCIP_CALL( SCIProwRelease(&lp->lpirows[r], blkmem, set, lp) );
15483 SCIProwUnlock(lp->rows[r]);
15484 SCIP_CALL( SCIProwRelease(&lp->rows[r], blkmem, set, lp) );
15485 assert(lp->lpirows[r] == NULL);
15486 assert(lp->rows[r] == NULL);
15487 lp->nrows--;
15488 lp->nlpirows--;
15489 }
15490 else if( rowdstat[r] < r )
15491 {
15492 assert(lp->rows[rowdstat[r]] == NULL);
15493 assert(lp->lpirows[rowdstat[r]] == NULL);
15494 lp->rows[rowdstat[r]] = row;
15495 lp->lpirows[rowdstat[r]] = row;
15496 lp->rows[rowdstat[r]]->lppos = rowdstat[r];
15497 lp->rows[rowdstat[r]]->lpipos = rowdstat[r];
15498 lp->rows[r] = NULL;
15499 lp->lpirows[r] = NULL;
15500 }
15501 }
15502
15503 /* mark LP to be unsolved */
15504 if( lp->nrows < nrows )
15505 {
15506 assert(lp->nrows == lp->nlpirows);
15507 assert(lp->nchgrows == 0);
15508 assert(lp->flushed);
15509
15510 lp->lpifirstchgrow = lp->nlpirows;
15511
15512 /* mark the current solution invalid */
15513 lp->solved = FALSE;
15514 lp->dualfeasible = FALSE;
15515 lp->dualchecked = FALSE;
15516 lp->lpobjval = SCIP_INVALID;
15518 }
15519
15520 checkLinks(lp);
15521
15522 return SCIP_OKAY;
15523}
15524
15525/** removes all non-basic columns, that are too old, beginning with the given firstcol */
15526static
15528 SCIP_LP* lp, /**< current LP data */
15529 SCIP_SET* set, /**< global SCIP settings */
15530 SCIP_STAT* stat, /**< problem statistics */
15531 int firstcol /**< first column to check for clean up */
15532 )
15533{
15534 SCIP_COL** cols;
15535#ifndef NDEBUG
15536 SCIP_COL** lpicols;
15537#endif
15538 int* coldstat;
15539 int ncols;
15540 int ndelcols;
15541 int c;
15542
15543 assert(lp != NULL);
15544 assert(lp->flushed);
15545 assert(lp->ncols == lp->nlpicols);
15546 assert(lp->nremovablecols <= lp->ncols);
15547 assert(!lp->diving);
15548 assert(set != NULL);
15549 assert(stat != NULL);
15550
15551 if( lp->nremovablecols == 0 || set->lp_colagelimit == -1 || !lp->solisbasic )
15552 return SCIP_OKAY;
15553
15554 ncols = lp->ncols;
15555 cols = lp->cols;
15556#ifndef NDEBUG
15557 lpicols = lp->lpicols;
15558#endif
15559
15560 /* get temporary memory */
15561 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15562
15563 /* mark obsolete columns to be deleted */
15564 ndelcols = 0;
15565 BMSclearMemoryArray(coldstat, ncols);
15566 for( c = firstcol; c < ncols; ++c )
15567 {
15568 assert(cols[c] == lpicols[c]);
15569 assert(cols[c]->lppos == c);
15570 assert(cols[c]->lpipos == c);
15571 if( cols[c]->removable
15572 && 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 */
15573 && cols[c]->age > set->lp_colagelimit
15575 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15576 {
15577 assert(cols[c]->primsol == 0.0);
15578 coldstat[c] = 1;
15579 ndelcols++;
15580 cols[c]->obsoletenode = stat->nnodes;
15581 SCIPsetDebugMsg(set, "removing obsolete col <%s>: primsol=%f, bounds=[%g,%g]\n",
15582 SCIPvarGetName(cols[c]->var), cols[c]->primsol, cols[c]->lb, cols[c]->ub);
15583 }
15584 }
15585
15586 SCIPsetDebugMsg(set, "removing %d/%d obsolete columns from LP\n", ndelcols, ncols);
15587
15588 /* delete the marked columns in the LP solver interface, update the LP respectively */
15589 if( ndelcols > 0 )
15590 {
15591 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15592 }
15593 assert(lp->ncols == ncols - ndelcols);
15594
15595 /* release temporary memory */
15596 SCIPsetFreeBufferArray(set, &coldstat);
15597
15598 return SCIP_OKAY;
15599}
15600
15601/** removes all basic rows, that are too old, beginning with the given firstrow */
15602static
15604 SCIP_LP* lp, /**< current LP data */
15605 BMS_BLKMEM* blkmem, /**< block memory buffers */
15606 SCIP_SET* set, /**< global SCIP settings */
15607 SCIP_STAT* stat, /**< problem statistics */
15608 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15609 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15610 int firstrow /**< first row to check for clean up */
15611 )
15612{
15613 SCIP_ROW** rows;
15614#ifndef NDEBUG
15615 SCIP_ROW** lpirows;
15616#endif
15617 int* rowdstat;
15618 int nrows;
15619 int ndelrows;
15620 int r;
15621
15622 assert(lp != NULL);
15623 assert(lp->flushed);
15624 assert(lp->nrows == lp->nlpirows);
15625 assert(lp->nremovablerows <= lp->nrows);
15626 assert(!lp->diving);
15627 assert(set != NULL);
15628 assert(stat != NULL);
15629
15630 if( lp->nremovablerows == 0 || set->lp_rowagelimit == -1 || !lp->solisbasic )
15631 return SCIP_OKAY;
15632
15633 nrows = lp->nrows;
15634 rows = lp->rows;
15635#ifndef NDEBUG
15636 lpirows = lp->lpirows;
15637#endif
15638
15639 /* get temporary memory */
15640 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15641
15642 /* mark obsolete rows to be deleted */
15643 ndelrows = 0;
15644 BMSclearMemoryArray(rowdstat, nrows);
15645 for( r = firstrow; r < nrows; ++r )
15646 {
15647 assert(rows[r] == lpirows[r]);
15648 assert(rows[r]->lppos == r);
15649 assert(rows[r]->lpipos == r);
15650 if( rows[r]->removable
15651 && 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 */
15652 && rows[r]->age > set->lp_rowagelimit
15654 {
15655 rowdstat[r] = 1;
15656 ndelrows++;
15657 rows[r]->obsoletenode = stat->nnodes;
15658 SCIPsetDebugMsg(set, "removing obsolete row <%s>: activity=%f, sides=[%g,%g]\n",
15659 rows[r]->name, rows[r]->activity, rows[r]->lhs, rows[r]->rhs);
15660 }
15661 }
15662
15663 SCIPsetDebugMsg(set, "removing %d/%d obsolete rows from LP\n", ndelrows, nrows);
15664
15665 /* delete the marked rows in the LP solver interface, update the LP respectively */
15666 if( ndelrows > 0 )
15667 {
15668 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15669 }
15670 assert(lp->nrows == nrows - ndelrows);
15671
15672 /* release temporary memory */
15673 SCIPsetFreeBufferArray(set, &rowdstat);
15674
15675 return SCIP_OKAY;
15676}
15677
15678/** removes all non-basic columns and basic rows in the part of the LP created at the current node, that are too old */
15680 SCIP_LP* lp, /**< current LP data */
15681 BMS_BLKMEM* blkmem, /**< block memory buffers */
15682 SCIP_SET* set, /**< global SCIP settings */
15683 SCIP_STAT* stat, /**< problem statistics */
15684 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15685 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15686 )
15687{
15688 assert(lp != NULL);
15689 assert(lp->solved);
15690 assert(!lp->diving);
15692 assert(set != NULL);
15693
15694 SCIPsetDebugMsg(set, "removing obsolete columns starting with %d/%d, obsolete rows starting with %d/%d\n",
15695 lp->firstnewcol, lp->ncols, lp->firstnewrow, lp->nrows);
15696
15697 if( lp->firstnewcol < lp->ncols )
15698 {
15699 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, lp->firstnewcol) );
15700 }
15701 if( lp->firstnewrow < lp->nrows )
15702 {
15703 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15704 }
15705
15706 return SCIP_OKAY;
15707}
15708
15709/** removes all non-basic columns and basic rows in whole LP, that are too old */
15711 SCIP_LP* lp, /**< current LP data */
15712 BMS_BLKMEM* blkmem, /**< block memory buffers */
15713 SCIP_SET* set, /**< global SCIP settings */
15714 SCIP_STAT* stat, /**< problem statistics */
15715 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15716 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15717 )
15718{
15719 assert(lp != NULL);
15720 assert(lp->solved);
15721 assert(!lp->diving);
15723 assert(set != NULL);
15724
15725 SCIPsetDebugMsg(set, "removing all obsolete columns and rows\n");
15726
15727 if( 0 < lp->ncols )
15728 {
15729 SCIP_CALL( lpRemoveObsoleteCols(lp, set, stat, 0) );
15730 }
15731 if( 0 < lp->nrows )
15732 {
15733 SCIP_CALL( lpRemoveObsoleteRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15734 }
15735
15736 return SCIP_OKAY;
15737}
15738
15739/** removes all non-basic columns at 0.0 beginning with the given firstcol */
15740static
15742 SCIP_LP* lp, /**< current LP data */
15743 SCIP_SET* set, /**< global SCIP settings */
15744 SCIP_STAT* stat, /**< problem statistics */
15745 int firstcol /**< first column to check for clean up */
15746 )
15747{
15748 SCIP_COL** cols;
15749 SCIP_COL** lpicols;
15750 int* coldstat;
15751 int ncols;
15752 int ndelcols;
15753 int c;
15754
15755 assert(lp != NULL);
15756 assert(lp->flushed);
15757 assert(lp->ncols == lp->nlpicols);
15758 assert(!lp->diving);
15759 assert(stat != NULL);
15760 assert(lp->validsollp == stat->lpcount);
15761 assert(0 <= firstcol && firstcol < lp->ncols);
15762
15763 if( lp->nremovablecols == 0 || !lp->solisbasic )
15764 return SCIP_OKAY;
15765
15766 ncols = lp->ncols;
15767 cols = lp->cols;
15768 lpicols = lp->lpicols;
15769
15770 /* get temporary memory */
15771 SCIP_CALL( SCIPsetAllocBufferArray(set, &coldstat, ncols) );
15772
15773 /* mark unused columns to be deleted */
15774 ndelcols = 0;
15775 BMSclearMemoryArray(coldstat, ncols);
15776 for( c = firstcol; c < ncols; ++c )
15777 {
15778 assert(cols[c] == lpicols[c]);
15779 assert(cols[c]->lppos == c);
15780 assert(cols[c]->lpipos == c);
15781 if( lpicols[c]->removable
15782 && (SCIP_BASESTAT)lpicols[c]->basisstatus != SCIP_BASESTAT_BASIC
15783 && lpicols[c]->primsol == 0.0 /* non-basic columns to remove are exactly at 0.0 */
15784 && SCIPsetIsZero(set, SCIPcolGetBestBound(cols[c])) ) /* bestbd != 0 -> column would be priced in next time */
15785 {
15786 coldstat[c] = 1;
15787 ndelcols++;
15788 }
15789 }
15790
15791 SCIPsetDebugMsg(set, "removing %d/%d unused columns from LP\n", ndelcols, ncols);
15792
15793 /* delete the marked columns in the LP solver interface, update the LP respectively */
15794 if( ndelcols > 0 )
15795 {
15796 SCIP_CALL( lpDelColset(lp, set, coldstat) );
15797 }
15798 assert(lp->ncols == ncols - ndelcols);
15799
15800 /* release temporary memory */
15801 SCIPsetFreeBufferArray(set, &coldstat);
15802
15803 return SCIP_OKAY;
15804}
15805
15806/** removes all basic rows beginning with the given firstrow */
15807static
15809 SCIP_LP* lp, /**< current LP data */
15810 BMS_BLKMEM* blkmem, /**< block memory buffers */
15811 SCIP_SET* set, /**< global SCIP settings */
15812 SCIP_STAT* stat, /**< problem statistics */
15813 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15814 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15815 int firstrow /**< first row to check for clean up */
15816 )
15817{
15818#ifndef NDEBUG
15819 SCIP_ROW** rows;
15820#endif
15821 SCIP_ROW** lpirows;
15822 int* rowdstat;
15823 int nrows;
15824 int ndelrows;
15825 int r;
15826
15827 assert(lp != NULL);
15828 assert(lp->flushed);
15829 assert(lp->ncols == lp->nlpicols);
15830 assert(lp->nrows == lp->nlpirows);
15831 assert(!lp->diving);
15832 assert(stat != NULL);
15833 assert(lp->validsollp == stat->lpcount);
15834 assert(0 <= firstrow && firstrow < lp->nrows);
15835
15836 if( lp->nremovablerows == 0 || !lp->solisbasic )
15837 return SCIP_OKAY;
15838
15839#ifndef NDEBUG
15840 rows = lp->rows;
15841#endif
15842 nrows = lp->nrows;
15843 lpirows = lp->lpirows;
15844
15845 /* get temporary memory */
15846 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15847
15848 /* mark unused rows to be deleted */
15849 ndelrows = 0;
15850 BMSclearMemoryArray(rowdstat, nrows);
15851 for( r = firstrow; r < nrows; ++r )
15852 {
15853 assert(rows[r] == lpirows[r]);
15854 assert(rows[r]->lppos == r);
15855 assert(rows[r]->lpipos == r);
15856 if( lpirows[r]->removable && (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC )
15857 {
15858 rowdstat[r] = 1;
15859 ndelrows++;
15860 }
15861 }
15862
15863 SCIPsetDebugMsg(set, "removing %d/%d unused rows from LP\n", ndelrows, nrows);
15864
15865 /* delete the marked rows in the LP solver interface, update the LP respectively */
15866 if( ndelrows > 0 )
15867 {
15868 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
15869 }
15870 assert(lp->nrows == nrows - ndelrows);
15871
15872 /* release temporary memory */
15873 SCIPsetFreeBufferArray(set, &rowdstat);
15874
15875 return SCIP_OKAY;
15876}
15877
15878/** removes all non-basic columns at 0.0 and basic rows in the part of the LP created at the current node */
15880 SCIP_LP* lp, /**< current LP data */
15881 BMS_BLKMEM* blkmem, /**< block memory buffers */
15882 SCIP_SET* set, /**< global SCIP settings */
15883 SCIP_STAT* stat, /**< problem statistics */
15884 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15885 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15886 SCIP_Bool root /**< are we at the root node? */
15887 )
15888{
15889 SCIP_Bool cleanupcols;
15890 SCIP_Bool cleanuprows;
15891
15892 assert(lp != NULL);
15893 assert(lp->solved);
15894 assert(!lp->diving);
15896 assert(set != NULL);
15897
15898 /* check, if we want to clean up the columns and rows */
15899 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15900 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15901
15902 SCIPsetDebugMsg(set, "removing unused columns starting with %d/%d (%u), unused rows starting with %d/%d (%u), LP algo: %d, basic sol: %u\n",
15903 lp->firstnewcol, lp->ncols, cleanupcols, lp->firstnewrow, lp->nrows, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15904
15905 if( cleanupcols && lp->firstnewcol < lp->ncols )
15906 {
15907 SCIP_CALL( lpCleanupCols(lp, set, stat, lp->firstnewcol) );
15908 }
15909 if( cleanuprows && lp->firstnewrow < lp->nrows )
15910 {
15911 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, lp->firstnewrow) );
15912 }
15913
15914 return SCIP_OKAY;
15915}
15916
15917/** removes all non-basic columns at 0.0 and basic rows in the whole LP */
15919 SCIP_LP* lp, /**< current LP data */
15920 BMS_BLKMEM* blkmem, /**< block memory buffers */
15921 SCIP_SET* set, /**< global SCIP settings */
15922 SCIP_STAT* stat, /**< problem statistics */
15923 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15924 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
15925 SCIP_Bool root /**< are we at the root node? */
15926 )
15927{
15928 SCIP_Bool cleanupcols;
15929 SCIP_Bool cleanuprows;
15930
15931 assert(lp != NULL);
15932 assert(lp->solved);
15933 assert(!lp->diving);
15935 assert(set != NULL);
15936
15937 /* check, if we want to clean up the columns and rows */
15938 cleanupcols = (root ? set->lp_cleanupcolsroot : set->lp_cleanupcols);
15939 cleanuprows = (root ? set->lp_cleanuprowsroot : set->lp_cleanuprows);
15940
15941 SCIPsetDebugMsg(set, "removing all unused columns (%u) and rows (%u), LP algo: %d, basic sol: %u\n",
15942 cleanupcols, cleanuprows, lp->lastlpalgo, lp->solisbasic);
15943
15944 if( cleanupcols && 0 < lp->ncols )
15945 {
15946 SCIP_CALL( lpCleanupCols(lp, set, stat, 0) );
15947 }
15948 if( cleanuprows && 0 < lp->nrows )
15949 {
15950 SCIP_CALL( lpCleanupRows(lp, blkmem, set, stat, eventqueue, eventfilter, 0) );
15951 }
15952
15953 return SCIP_OKAY;
15954}
15955
15956/** removes all redundant rows that were added at the current node */
15958 SCIP_LP* lp, /**< current LP data */
15959 BMS_BLKMEM* blkmem, /**< block memory buffers */
15960 SCIP_SET* set, /**< global SCIP settings */
15961 SCIP_STAT* stat, /**< problem statistics */
15962 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
15963 SCIP_EVENTFILTER* eventfilter /**< global event filter */
15964 )
15965{
15966#ifndef NDEBUG
15967 SCIP_ROW** rows;
15968#endif
15969 SCIP_ROW** lpirows;
15970 int* rowdstat;
15971 int nrows;
15972 int ndelrows;
15973 int r;
15974
15975 assert(lp != NULL);
15976 assert(lp->flushed);
15977 assert(lp->ncols == lp->nlpicols);
15978 assert(lp->nrows == lp->nlpirows);
15979 assert(!lp->diving);
15980 assert(stat != NULL);
15981 assert(lp->validsollp == stat->lpcount);
15982 assert(lp->firstnewrow <= lp->nrows);
15983
15984 if( lp->firstnewrow == lp->nrows )
15985 return SCIP_OKAY;
15986
15987#ifndef NDEBUG
15988 rows = lp->rows;
15989#endif
15990 nrows = lp->nrows;
15991 lpirows = lp->lpirows;
15992
15993 /* get temporary memory */
15994 SCIP_CALL( SCIPsetAllocBufferArray(set, &rowdstat, nrows) );
15995
15996 /* mark redundant rows to be deleted (only delete basic rows!) */
15997 ndelrows = 0;
15998 BMSclearMemoryArray(rowdstat, nrows);
15999 for( r = lp->firstnewrow; r < nrows; ++r )
16000 {
16001 assert(rows[r] == lpirows[r]);
16002 assert(rows[r]->lppos == r);
16003 assert(rows[r]->lpipos == r);
16004 if( (!lp->solisbasic || (SCIP_BASESTAT)lpirows[r]->basisstatus == SCIP_BASESTAT_BASIC)
16005 && SCIProwIsRedundant(lpirows[r], set, stat) )
16006 {
16007 SCIPsetDebugMsg(set, "basic row <%s> is redundant: sides=[%g,%g], act=[%g,%g]\n",
16008 SCIProwGetName(lpirows[r]), SCIProwGetLhs(lpirows[r]), SCIProwGetRhs(lpirows[r]),
16009 SCIProwGetMinActivity(lpirows[r], set, stat), SCIProwGetMaxActivity(lpirows[r], set, stat));
16010 rowdstat[r] = 1;
16011 ndelrows++;
16012 }
16013 }
16014
16015 SCIPsetDebugMsg(set, "removing %d/%d redundant basic rows from LP\n", ndelrows, nrows);
16016
16017 /* delete the marked rows in the LP solver interface, update the LP respectively */
16018 if( ndelrows > 0 )
16019 {
16020 SCIP_CALL( lpDelRowset(lp, blkmem, set, eventqueue, eventfilter, rowdstat) );
16021 }
16022 assert(lp->nrows == nrows - ndelrows);
16023
16024 /* release temporary memory */
16025 SCIPsetFreeBufferArray(set, &rowdstat);
16026
16027 return SCIP_OKAY;
16028}
16029
16030/** initiates LP diving */
16032 SCIP_LP* lp, /**< current LP data */
16033 BMS_BLKMEM* blkmem, /**< block memory */
16034 SCIP_SET* set, /**< global SCIP settings */
16035 SCIP_STAT* stat /**< problem statistics */
16036 )
16037{
16038 int c;
16039 int r;
16040
16041 assert(lp != NULL);
16042 assert(lp->flushed || !lp->solved);
16043 assert(!lp->diving);
16044 assert(!lp->probing);
16045 assert(lp->divelpistate == NULL);
16046 assert(lp->divelpwasprimfeas);
16047 assert(lp->divelpwasdualfeas);
16048 assert(lp->validsollp <= stat->lpcount);
16049 assert(blkmem != NULL);
16050 assert(set != NULL);
16051 assert(lp->ndivechgsides == 0);
16052
16053 SCIPsetDebugMsg(set, "diving started (LP flushed: %u, LP solved: %u, solstat: %d)\n",
16054 lp->flushed, lp->solved, SCIPlpGetSolstat(lp));
16055
16056#ifndef NDEBUG
16057 for( c = 0; c < lp->ncols; ++c )
16058 {
16059 assert(lp->cols[c] != NULL);
16060 assert(lp->cols[c]->var != NULL);
16061 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16062 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16063 assert(SCIPsetIsFeasEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16064 assert(SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16065 assert(SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16066 }
16067#endif
16068
16069 /* save current LPI state (basis information) */
16070 SCIP_CALL( SCIPlpiGetState(lp->lpi, blkmem, &lp->divelpistate) );
16075
16076 /* save current LP values dependent on the solution */
16077 SCIP_CALL( lpStoreSolVals(lp, stat, blkmem) );
16078 assert(lp->storedsolvals != NULL);
16079 if( !set->lp_resolverestore && lp->solved )
16080 {
16081 SCIP_Bool store = TRUE;
16082
16083 switch ( lp->lpsolstat )
16084 {
16086 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16087 assert(lp->validsollp == stat->lpcount);
16088 break;
16091 assert(lp->validsollp == stat->lpcount);
16092 break;
16096 SCIP_CALL( SCIPlpGetSol(lp, set, stat, NULL, NULL) );
16097 assert(lp->validsollp == stat->lpcount);
16098 break;
16100 SCIP_CALL( SCIPlpGetDualfarkas(lp, set, stat, FALSE, NULL) );
16101 break;
16104 default:
16105 store = FALSE;
16106 }
16107
16108 if ( store )
16109 {
16110 for( c = 0; c < lp->ncols; ++c )
16111 {
16112 SCIP_CALL( colStoreSolVals(lp->cols[c], blkmem) );
16113 }
16114 for( r = 0; r < lp->nrows; ++r )
16115 {
16117 }
16118 }
16119 }
16120
16121 /* store LPI iteration limit */
16123
16124 /* remember the number of domain changes */
16125 lp->divenolddomchgs = stat->domchgcount;
16126
16127 /* store current number of rows */
16128 lp->ndivingrows = lp->nrows;
16129
16130 /* switch to diving mode */
16131 lp->diving = TRUE;
16132
16133 return SCIP_OKAY;
16134}
16135
16136/** quits LP diving and resets bounds and objective values of columns to the current node's values */
16138 SCIP_LP* lp, /**< current LP data */
16139 BMS_BLKMEM* blkmem, /**< block memory */
16140 SCIP_SET* set, /**< global SCIP settings */
16141 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16142 SCIP_STAT* stat, /**< problem statistics */
16143 SCIP_EVENTQUEUE* eventqueue, /**< event queue */
16144 SCIP_EVENTFILTER* eventfilter, /**< global event filter */
16145 SCIP_PROB* prob, /**< problem data */
16146 SCIP_VAR** vars, /**< array with all active variables */
16147 int nvars /**< number of active variables */
16148 )
16149{
16150 SCIP_VAR* var;
16151 int v;
16152
16153 assert(lp != NULL);
16154 assert(lp->diving);
16155 assert(blkmem != NULL);
16156 assert(nvars == 0 || vars != NULL);
16157
16158 SCIPsetDebugMsg(set, "diving ended (LP flushed: %u, solstat: %d)\n", lp->flushed, SCIPlpGetSolstat(lp));
16159
16160 /* reset all columns' objective values and bounds to its original values */
16161 for( v = 0; v < nvars; ++v )
16162 {
16163 var = vars[v];
16164 assert(var != NULL);
16166 {
16170 }
16171 }
16172
16173 /* remove rows which were added in diving mode */
16174 SCIP_CALL( SCIPlpShrinkRows(lp, blkmem, set, eventqueue, eventfilter, lp->ndivingrows) );
16175
16176 /* undo changes to left hand sides and right hand sides */
16177 while( lp->ndivechgsides > 0 )
16178 {
16179 SCIP_Real oldside;
16180 SCIP_SIDETYPE sidetype;
16181 SCIP_ROW* row;
16182
16183 lp->ndivechgsides--;
16184 oldside = lp->divechgsides[lp->ndivechgsides];
16185 sidetype = lp->divechgsidetypes[lp->ndivechgsides];
16186 row = lp->divechgrows[lp->ndivechgsides];
16187
16188 if( sidetype == SCIP_SIDETYPE_LEFT )
16189 {
16190 SCIP_CALL( SCIProwChgLhs(row, blkmem, set, eventqueue, lp, oldside) );
16191 }
16192 else
16193 {
16194 SCIP_CALL( SCIProwChgRhs(row, blkmem, set, eventqueue, lp, oldside) );
16195 }
16196 }
16197
16198 /* restore LPI iteration limit */
16200
16201 /* reload LPI state saved at start of diving and free it afterwards; it may be NULL, in which case simply nothing
16202 * happens
16203 */
16204 SCIP_CALL( SCIPlpSetState(lp, blkmem, set, prob, eventqueue, lp->divelpistate,
16206 SCIP_CALL( SCIPlpFreeState(lp, blkmem, &lp->divelpistate) );
16207 lp->divelpwasprimfeas = TRUE;
16208 lp->divelpwasdualfeas = TRUE;
16211 assert(lp->divelpistate == NULL);
16212
16213 /* switch to standard (non-diving) mode */
16214 lp->diving = FALSE;
16215 lp->divingobjchg = FALSE;
16216
16217 /* if the LP was solved before starting the dive, but not to optimality (or unboundedness), then we need to solve the
16218 * LP again to reset the solution (e.g. we do not save the Farkas proof for infeasible LPs, because we assume that we
16219 * are not called in this case, anyway); restoring by solving the LP again in either case can be forced by setting
16220 * the parameter resolverestore to TRUE
16221 * restoring an unbounded ray after solve does not seem to work currently (bug 631), so we resolve also in this case
16222 */
16223 assert(lp->storedsolvals != NULL);
16224 if( lp->storedsolvals->lpissolved
16225 && (set->lp_resolverestore || lp->storedsolvals->lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || lp->divenolddomchgs < stat->domchgcount) )
16226 {
16227 SCIP_Bool lperror;
16228
16229 SCIP_CALL( SCIPlpSolveAndEval(lp, set, messagehdlr, blkmem, stat, eventqueue, eventfilter, prob, -1LL, FALSE, FALSE, FALSE, FALSE, &lperror) );
16230 if( lperror )
16231 {
16232 lpNumericalTroubleMessage(messagehdlr, set, stat, SCIP_VERBLEVEL_FULL, "unresolved when resolving LP after diving");
16233 lp->resolvelperror = TRUE;
16234 }
16239 {
16240 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_FULL,
16241 "LP was not resolved to a sufficient status after diving\n");
16242 lp->resolvelperror = TRUE;
16243 }
16244 }
16245 /* otherwise, we can just reload the buffered LP solution values at start of diving; this has the advantage that we
16246 * are guaranteed to continue with the same LP status as before diving, while in numerically difficult cases, a
16247 * re-solve as above can lead to a different LP status
16248 */
16249 else
16250 {
16251 int c;
16252 int r;
16253
16254 /* if there are lazy bounds, remove them from the LP */
16255 if( lp->nlazycols > 0 )
16256 {
16257 /* @todo avoid loosing primal feasibility here after changing the objective already did destroy dual feasibility;
16258 * first resolve LP?
16259 */
16261 assert(lp->diving == lp->divinglazyapplied);
16262
16263 /* flush changes to the LP solver */
16264 SCIP_CALL( SCIPlpFlush(lp, blkmem, set, prob, eventqueue) );
16265 }
16266
16267 /* increment lp counter to ensure that we do not use solution values from the last solved diving lp */
16268 SCIPstatIncrement(stat, set, lpcount);
16269
16270 /* restore LP solution values in lp data, columns and rows */
16271 if( lp->storedsolvals->lpissolved &&
16278 )
16279 {
16280 SCIP_CALL( lpRestoreSolVals(lp, blkmem, stat->lpcount) );
16281
16282 for( c = 0; c < lp->ncols; ++c )
16283 {
16284 SCIP_CALL( colRestoreSolVals(lp->cols[c], blkmem, stat->lpcount, set->lp_freesolvalbuffers) );
16285 }
16286 for( r = 0; r < lp->nrows; ++r )
16287 {
16288 SCIP_CALL( rowRestoreSolVals(lp->rows[r], blkmem, stat->lpcount, set->lp_freesolvalbuffers, lp->storedsolvals->lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE) );
16289 }
16290 }
16291 else
16292 {
16293 SCIP_CALL( lpRestoreSolVals(lp, blkmem, -1LL) );
16294 }
16295 }
16296
16297#ifndef NDEBUG
16298 {
16299 int c;
16300 for( c = 0; c < lp->ncols; ++c )
16301 {
16302 assert(lp->cols[c] != NULL);
16303 assert(lp->cols[c]->var != NULL);
16304 assert(SCIPvarGetStatus(lp->cols[c]->var) == SCIP_VARSTATUS_COLUMN);
16305 assert(SCIPvarGetCol(lp->cols[c]->var) == lp->cols[c]);
16306 assert(SCIPsetIsEQ(set, SCIPvarGetObj(lp->cols[c]->var), lp->cols[c]->obj));
16307 assert(SCIPsetIsEQ(set, SCIPvarGetLbLocal(lp->cols[c]->var), lp->cols[c]->lb));
16308 assert(SCIPsetIsEQ(set, SCIPvarGetUbLocal(lp->cols[c]->var), lp->cols[c]->ub));
16309 }
16310 }
16311#endif
16312
16313 return SCIP_OKAY;
16314}
16315
16316#define DIVESTACKGROWFACT 1.5
16317
16318/** records a current row side such that any change will be undone after diving */
16320 SCIP_LP* lp, /**< LP data object */
16321 SCIP_ROW* row, /**< row affected by the change */
16322 SCIP_SIDETYPE sidetype /**< side type */
16323 )
16324{
16325 assert(lp != NULL);
16326 assert(row != NULL);
16327
16328 if( lp->ndivechgsides == lp->divechgsidessize )
16329 {
16331 }
16332 assert(lp->ndivechgsides < lp->divechgsidessize);
16333
16334 lp->divechgsides[lp->ndivechgsides] = (sidetype == SCIP_SIDETYPE_LEFT) ? row->lhs : row->rhs;
16335 lp->divechgsidetypes[lp->ndivechgsides] = sidetype;
16336 lp->divechgrows[lp->ndivechgsides] = row;
16337 lp->ndivechgsides++;
16338
16339 return SCIP_OKAY;
16340}
16341
16342/** informs the LP that probing mode was initiated */
16344 SCIP_LP* lp /**< current LP data */
16345 )
16346{
16347 assert(lp != NULL);
16348 assert(!lp->probing);
16349 assert(!lp->strongbranching);
16350 assert(!lp->strongbranchprobing);
16351
16352 lp->probing = TRUE;
16353
16354 return SCIP_OKAY;
16355}
16356
16357/** informs the LP that probing mode was finished */
16359 SCIP_LP* lp /**< current LP data */
16360 )
16361{
16362 assert(lp != NULL);
16363 assert(lp->probing);
16364 assert(!lp->strongbranching);
16365 assert(!lp->strongbranchprobing);
16366
16367 lp->probing = FALSE;
16368
16369 return SCIP_OKAY;
16370}
16371
16372/** informs the LP that the probing mode is now used for strongbranching */
16374 SCIP_LP* lp /**< current LP data */
16375 )
16376{
16377 assert(lp != NULL);
16378 assert(lp->probing);
16379 assert(!lp->strongbranching);
16380 assert(!lp->strongbranchprobing);
16381
16383}
16384
16385/** informs the LP that the probing mode is not used for strongbranching anymore */
16387 SCIP_LP* lp /**< current LP data */
16388 )
16389{
16390 assert(lp != NULL);
16391 assert(lp->probing);
16392 assert(!lp->strongbranching);
16393 assert(lp->strongbranchprobing);
16394
16396}
16397
16398/** calculates y*b + min{(c - y*A)*x | lb <= x <= ub} for given vectors y and c;
16399 * the vector b is defined with b[i] = lhs[i] if y[i] >= 0, b[i] = rhs[i] if y[i] < 0
16400 * Calculating this value in interval arithmetics gives a proved lower LP bound for the following reason (assuming,
16401 * we have only left hand sides):
16402 * min{cx | b <= Ax, lb <= x <= ub}
16403 * >= min{cx | yb <= yAx, lb <= x <= ub} (restriction in minimum is relaxed)
16404 * == yb + min{cx - yb | yb <= yAx, lb <= x <= ub} (added yb - yb == 0)
16405 * >= yb + min{cx - yAx | yb <= yAx, lb <= x <= ub} (because yAx >= yb inside minimum)
16406 * >= yb + min{cx - yAx | lb <= x <= ub} (restriction in minimum is relaxed)
16407 */
16408static
16410 SCIP_LP* lp, /**< current LP data */
16411 SCIP_SET* set, /**< global SCIP settings */
16412 SCIP_Bool usefarkas, /**< use y = dual Farkas and c = 0 instead of y = dual solution and c = obj? */
16413 SCIP_Real* bound /**< result of interval arithmetic minimization */
16414 )
16415{
16416 SCIP_INTERVAL* yinter;
16418 SCIP_INTERVAL ytb;
16419 SCIP_INTERVAL prod;
16420 SCIP_INTERVAL diff;
16422 SCIP_INTERVAL minprod;
16424 SCIP_ROW* row;
16425 SCIP_COL* col;
16426 SCIP_Real y;
16427 SCIP_Real c;
16428 int i;
16429 int j;
16430
16431 assert(lp != NULL);
16432 assert(lp->solved);
16433 assert(set != NULL);
16434 assert(bound != NULL);
16435
16436 /* allocate buffer for storing y in interval arithmetic */
16437 SCIP_CALL( SCIPsetAllocBufferArray(set, &yinter, lp->nrows) );
16438
16439 /* create y vector in interval arithmetic, setting near zeros to zero; calculate y^Tb */
16440 SCIPintervalSet(&ytb, 0.0);
16441 for( j = 0; j < lp->nrows; ++j )
16442 {
16443 row = lp->rows[j];
16444 assert(row != NULL);
16445
16446 y = (usefarkas ? row->dualfarkas : row->dualsol);
16447
16449 {
16450 SCIPintervalSet(&yinter[j], y);
16451 SCIPintervalSet(&b, row->lhs - row->constant);
16452 }
16453 else if( SCIPsetIsFeasNegative(set, y) )
16454 {
16455 SCIPintervalSet(&yinter[j], y);
16456 SCIPintervalSet(&b, row->rhs - row->constant);
16457 }
16458 else
16459 {
16460 SCIPintervalSet(&yinter[j], 0.0);
16461 SCIPintervalSet(&b, 0.0);
16462 }
16463
16464 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[j], b);
16465 SCIPintervalAdd(SCIPsetInfinity(set), &ytb, ytb, prod);
16466 }
16467
16468 /* calculate min{(c^T - y^TA)x} */
16469 SCIPintervalSet(&minprod, 0.0);
16470 for( j = 0; j < lp->ncols; ++j )
16471 {
16472 col = lp->cols[j];
16473 assert(col != NULL);
16474 assert(col->nunlinked == 0);
16475
16477
16478 c = usefarkas ? 0.0 : col->obj;
16479 SCIPintervalSet(&diff, c);
16480
16481 for( i = 0; i < col->nlprows; ++i )
16482 {
16483 assert(col->rows[i] != NULL);
16484 assert(col->rows[i]->lppos >= 0);
16485 assert(col->linkpos[i] >= 0);
16486 SCIPintervalSet(&a, col->vals[i]);
16487 SCIPintervalMul(SCIPsetInfinity(set), &prod, yinter[col->rows[i]->lppos], a);
16488 SCIPintervalSub(SCIPsetInfinity(set), &diff, diff, prod);
16489 }
16490
16491#ifndef NDEBUG
16492 for( i = col->nlprows; i < col->len; ++i )
16493 {
16494 assert(col->rows[i] != NULL);
16495 assert(col->rows[i]->lppos == -1);
16496 assert(col->rows[i]->dualsol == 0.0);
16497 assert(col->rows[i]->dualfarkas == 0.0);
16498 assert(col->linkpos[i] >= 0);
16499 }
16500#endif
16501
16502 SCIPintervalSetBounds(&x, col->lb, col->ub);
16503 SCIPintervalMul(SCIPsetInfinity(set), &diff, diff, x);
16504 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, diff);
16505 }
16506
16507 /* add y^Tb */
16508 SCIPintervalAdd(SCIPsetInfinity(set), &minprod, minprod, ytb);
16509
16510 /* free buffer for storing y in interval arithmetic */
16511 SCIPsetFreeBufferArray(set, &yinter);
16512
16513 *bound = SCIPintervalGetInf(minprod);
16514
16515 return SCIP_OKAY;
16516}
16517
16518/** gets proven lower (dual) bound of last LP solution */
16520 SCIP_LP* lp, /**< current LP data */
16521 SCIP_SET* set, /**< global SCIP settings */
16522 SCIP_Real* bound /**< pointer to store proven dual bound */
16523 )
16524{
16526
16527 SCIPsetDebugMsg(set, "proved lower bound of LP: %.15g\n", *bound);
16528
16529 return SCIP_OKAY;
16530}
16531
16532/** gets proven dual bound of last LP solution */
16534 SCIP_LP* lp, /**< current LP data */
16535 SCIP_SET* set, /**< global SCIP settings */
16536 SCIP_Bool* proved /**< pointer to store whether infeasibility is proven */
16537 )
16538{
16540
16541 assert(proved != NULL);
16542
16543 SCIP_CALL( provedBound(lp, set, TRUE, &bound) );
16544
16545 *proved = (bound > 0.0);
16546
16547 SCIPsetDebugMsg(set, "proved Farkas value of LP: %g -> infeasibility %sproved\n", bound, *proved ? "" : "not ");
16548
16549 return SCIP_OKAY;
16550}
16551
16552
16553
16554/** writes LP to a file */
16556 SCIP_LP* lp, /**< current LP data */
16557 const char* fname /**< file name */
16558 )
16559{
16560 assert(lp != NULL);
16561 assert(lp->flushed);
16562 assert(fname != NULL);
16563
16564 SCIP_CALL( SCIPlpiWriteLP(lp->lpi, fname) );
16565
16566 return SCIP_OKAY;
16567}
16568
16569/** writes MIP relaxation of the current B&B node to a file */
16571 SCIP_LP* lp, /**< current LP data */
16572 SCIP_SET* set, /**< global SCIP settings */
16573 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
16574 const char* fname, /**< file name */
16575 SCIP_Bool genericnames, /**< should generic names like x_i and row_j be used in order to avoid
16576 * troubles with reserved symbols? */
16577 SCIP_Bool origobj, /**< should the original objective function be used? */
16578 SCIP_OBJSENSE objsense, /**< objective sense */
16579 SCIP_Real objscale, /**< objective scaling factor */
16580 SCIP_Real objoffset, /**< objective offset, e.g., caused by variable fixings in presolving */
16581 SCIP_Bool lazyconss /**< output removable rows as lazy constraints? */
16582 )
16583{
16584 FILE* file;
16585 int i;
16586 int j;
16587 char rowname[SCIP_MAXSTRLEN];
16588 SCIP_Real coeff;
16589
16590 assert(lp != NULL);
16591 assert(lp->flushed);
16592 assert(fname != NULL);
16593
16594 SCIPsetDebugMsg(set, "Start to write MIP to file <%s>\n", fname);
16595 file = fopen(fname, "w");
16596 if( file == NULL )
16597 {
16598 SCIPerrorMessage("cannot open file <%s> for writing\n", fname);
16599 SCIPprintSysError(fname);
16600 return SCIP_FILECREATEERROR;
16601 }
16602
16603 /* print comments */
16604 if( genericnames )
16605 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Original Variable and Constraint Names have been replaced by generic names.\n");
16606 else
16607 {
16608 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Warning: Variable and Constraint Names should not contain special characters like '+', '=' etc.\n");
16609 SCIPmessageFPrintInfo(messagehdlr, file, "\\ If this is the case, the model may be corrupted!\n");
16610 }
16611
16612 if( origobj && objoffset != 0.0 )
16613 {
16614 SCIPmessageFPrintInfo(messagehdlr, file, "\\ An artificial variable 'objoffset' has been added and fixed to 1.\n");
16615 SCIPmessageFPrintInfo(messagehdlr, file, "\\ Switching this variable to 0 will disable the offset in the objective.\n\n");
16616 }
16617
16618 /* print objective function */
16619 /**@note the transformed problem in SCIP is always a minimization problem */
16620 if( !origobj || objsense == SCIP_OBJSENSE_MINIMIZE )
16621 SCIPmessageFPrintInfo(messagehdlr, file, "Minimize");
16622 else
16623 SCIPmessageFPrintInfo(messagehdlr, file, "Maximize");
16624
16625 /* print objective */
16626 SCIPmessageFPrintInfo(messagehdlr, file, "\nObj:");
16627 j = 0;
16628 for( i = 0; i < lp->ncols; ++i )
16629 {
16630 if( lp->cols[i]->obj != 0.0 )
16631 {
16632 coeff = lp->cols[i]->obj;
16633 if( origobj )
16634 {
16635 coeff *= (SCIP_Real) objsense;
16636 coeff *= objscale;
16637 }
16638
16639 if( genericnames )
16640 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", coeff, lp->cols[i]->lppos);
16641 else
16642 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", coeff, lp->cols[i]->var->name);
16643
16644 ++j;
16645 if( j % 10 == 0 )
16646 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16647 }
16648 }
16649 /* add artificial variable 'objoffset' to transfer objective offset */
16650 if( origobj && objoffset != 0.0 )
16651 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g objoffset", objoffset * (SCIP_Real) objsense * objscale);
16652
16653 /* print constraint section */
16654 SCIPmessageFPrintInfo(messagehdlr, file, "\nSubject to\n");
16655 for( i = 0; i < lp->nrows; i++ )
16656 {
16657 char type = 'i';
16658
16659 /* skip removable rows if we want to write them as lazy constraints */
16660 if ( lazyconss && SCIProwIsRemovable(lp->rows[i]) )
16661 continue;
16662
16663 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16664 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16665 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16666 * type 'i' means: lhs and rhs are both infinite */
16667 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16668 type = 'r';
16669 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16670 type = 'l';
16671 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16672 type = 'e';
16673 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16674 type = 'b';
16675
16676 /* print name of row */
16677 if( genericnames )
16678 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16679 else
16680 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16681
16682 WRITEROW:
16683 switch( type )
16684 {
16685 case 'r':
16686 case 'l':
16687 case 'e':
16688 if( strlen(rowname) > 0 )
16689 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16690 break;
16691 case 'i':
16692 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16693 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16694 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n", lp->rows[i]->name);
16695 type = 'b';
16696 /*lint -fallthrough*/
16697 case 'b':
16698 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16699 break;
16700 default:
16701 assert(type == 'B');
16702 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16703 break;
16704 }
16705
16706 /* print coefficients and variables */
16707 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16708 {
16709 if( genericnames )
16710 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16711 else
16712 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16713
16714 if( (j+1) % 10 == 0 )
16715 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16716 }
16717
16718 /* print right hand side */
16719 switch( type )
16720 {
16721 case 'b':
16722 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16723 type = 'B';
16724 goto WRITEROW;
16725 case 'l':
16726 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16727 break;
16728 case 'B':
16729 case 'r':
16730 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16731 break;
16732 case 'e':
16733 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16734 break;
16735 default:
16736 SCIPerrorMessage("Undefined row type!\n");
16737 fclose(file);
16738 return SCIP_ERROR;
16739 }
16740 }
16741
16742 if ( lazyconss )
16743 {
16744 /* print lazy constraint section */
16745 SCIPmessageFPrintInfo(messagehdlr, file, "lazy constraints\n");
16746 for( i = 0; i < lp->nrows; i++ )
16747 {
16748 char type = 'i';
16749
16750 /* skip non-removable rows if we want to write lazy constraints */
16751 if ( ! SCIProwIsRemovable(lp->rows[i]) )
16752 continue;
16753
16754 /* constraint types: 'l' means: only lhs exists, 'r' means: only rhs exists, 'e' means: both sides exist and are
16755 * equal, 'b' and 'B' mean: both sides exist, if the type is 'b', the lhs will be written, if the type is 'B',
16756 * the rhs will be written. Ergo: set type to b first, change it to 'B' afterwards and go back to WRITEROW.
16757 * type 'i' means: lhs and rhs are both infinite */
16758 if( SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16759 type = 'r';
16760 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16761 type = 'l';
16762 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && SCIPsetIsEQ(set, lp->rows[i]->lhs, lp->rows[i]->rhs) )
16763 type = 'e';
16764 else if( !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->lhs)) && !SCIPsetIsInfinity(set, REALABS(lp->rows[i]->rhs)) )
16765 type = 'b';
16766
16767 /* print name of row */
16768 if( genericnames )
16769 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "row_%d", lp->rows[i]->lppos);
16770 else
16771 (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s", lp->rows[i]->name);
16772
16773 WRITELAZYROW:
16774 switch( type )
16775 {
16776 case 'r':
16777 case 'l':
16778 case 'e':
16779 if( strlen(rowname) > 0 )
16780 SCIPmessageFPrintInfo(messagehdlr, file, "%s: ", rowname);
16781 break;
16782 case 'i':
16783 SCIPmessageFPrintInfo(messagehdlr, file, "\\\\ WARNING: The lhs and the rhs of the row with original name <%s>", lp->rows[i]->name);
16784 SCIPmessageFPrintInfo(messagehdlr, file, "are not in a valid range. The following two constraints may be corrupted!\n");
16785 SCIPmessagePrintWarning(messagehdlr, "The lhs and rhs of row <%s> are not in a valid range.\n",lp->rows[i]->name);
16786 type = 'b';
16787 /*lint -fallthrough*/
16788 case 'b':
16789 SCIPmessageFPrintInfo(messagehdlr, file, "%s_lhs: ", rowname);
16790 break;
16791 default:
16792 assert(type == 'B');
16793 SCIPmessageFPrintInfo(messagehdlr, file, "%s_rhs: ", rowname);
16794 break;
16795 }
16796
16797 /* print coefficients and variables */
16798 for( j = 0; j < lp->rows[i]->nlpcols; ++j )
16799 {
16800 if( genericnames )
16801 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g x_%d", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->lppos);
16802 else
16803 SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g %s", lp->rows[i]->vals[j], lp->rows[i]->cols[j]->var->name);
16804
16805 if( (j+1) % 10 == 0 )
16806 SCIPmessageFPrintInfo(messagehdlr, file, "\n ");
16807 }
16808
16809 /* print right hand side */
16810 switch( type )
16811 {
16812 case 'b':
16813 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16814 type = 'B';
16815 goto WRITELAZYROW;
16816 case 'l':
16817 SCIPmessageFPrintInfo(messagehdlr, file, " >= %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16818 break;
16819 case 'B':
16820 case 'r':
16821 SCIPmessageFPrintInfo(messagehdlr, file, " <= %.15g\n", lp->rows[i]->rhs - lp->rows[i]->constant);
16822 break;
16823 case 'e':
16824 SCIPmessageFPrintInfo(messagehdlr, file, " = %.15g\n", lp->rows[i]->lhs - lp->rows[i]->constant);
16825 break;
16826 default:
16827 SCIPerrorMessage("Undefined row type!\n");
16828 fclose(file);
16829 return SCIP_ERROR;
16830 }
16831 }
16832 }
16833
16834 /* print variable bounds */
16835 SCIPmessageFPrintInfo(messagehdlr, file, "Bounds\n");
16836 for( i = 0; i < lp->ncols; ++i )
16837 {
16838 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) || !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16839 {
16840 /* print lower bound as far this one is not infinity */
16841 if( !SCIPsetIsInfinity(set,-lp->cols[i]->lb) )
16842 SCIPmessageFPrintInfo(messagehdlr, file, " %.15g <=", lp->cols[i]->lb);
16843
16844 /* print variable name */
16845 if( genericnames )
16846 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16847 else
16848 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16849
16850 /* print upper bound as far this one is not infinity */
16851 if( !SCIPsetIsInfinity(set,lp->cols[i]->ub) )
16852 SCIPmessageFPrintInfo(messagehdlr, file, "<= %.15g", lp->cols[i]->ub);
16853 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16854 }
16855 }
16856 if( origobj && objoffset != 0.0 )
16857 SCIPmessageFPrintInfo(messagehdlr, file, " objoffset = 1\n");
16858
16859 /* print integer variables */
16860 SCIPmessageFPrintInfo(messagehdlr, file, "Generals\n");
16861 j = 0;
16862 for( i = 0; i < lp->ncols; ++i )
16863 {
16864 if( SCIPvarIsIntegral(lp->cols[i]->var) )
16865 {
16866 /* print variable name */
16867 if( genericnames )
16868 SCIPmessageFPrintInfo(messagehdlr, file, " x_%d ", lp->cols[i]->lppos);
16869 else
16870 SCIPmessageFPrintInfo(messagehdlr, file, " %s ", lp->cols[i]->var->name);
16871
16872 j++;
16873 if( j % 10 == 0 )
16874 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
16875 }
16876 }
16877
16878 SCIPmessageFPrintInfo(messagehdlr, file, "\nEnd");
16879 fclose(file);
16880
16881 return SCIP_OKAY;
16882}
16883
16884/*
16885 * simple functions implemented as defines
16886 */
16887
16888/* In debug mode, the following methods are implemented as function calls to ensure
16889 * type validity.
16890 * In optimized mode, the methods are implemented as defines to improve performance.
16891 * However, we want to have them in the library anyways, so we have to undef the defines.
16892 */
16893
16894#undef SCIPcolGetObj
16895#undef SCIPcolGetLb
16896#undef SCIPcolGetUb
16897#undef SCIPcolGetBestBound
16898#undef SCIPcolGetPrimsol
16899#undef SCIPcolGetMinPrimsol
16900#undef SCIPcolGetMaxPrimsol
16901#undef SCIPcolGetBasisStatus
16902#undef SCIPcolGetVar
16903#undef SCIPcolGetIndex
16904#undef SCIPcolGetVarProbindex
16905#undef SCIPcolIsIntegral
16906#undef SCIPcolIsRemovable
16907#undef SCIPcolGetLPPos
16908#undef SCIPcolGetLPDepth
16909#undef SCIPcolIsInLP
16910#undef SCIPcolGetNNonz
16911#undef SCIPcolGetNLPNonz
16912#undef SCIPcolGetRows
16913#undef SCIPcolGetVals
16914#undef SCIPcolGetStrongbranchNode
16915#undef SCIPcolGetNStrongbranchs
16916#undef SCIPcolGetAge
16917#undef SCIPboundtypeOpposite
16918#undef SCIProwGetNNonz
16919#undef SCIProwGetNLPNonz
16920#undef SCIProwGetCols
16921#undef SCIProwGetVals
16922#undef SCIProwGetConstant
16923#undef SCIProwGetNorm
16924#undef SCIProwGetSumNorm
16925#undef SCIProwGetLhs
16926#undef SCIProwGetRhs
16927#undef SCIProwGetDualsol
16928#undef SCIProwGetDualfarkas
16929#undef SCIProwGetBasisStatus
16930#undef SCIProwGetName
16931#undef SCIProwGetIndex
16932#undef SCIProwGetAge
16933#undef SCIProwGetRank
16934#undef SCIProwIsIntegral
16935#undef SCIProwIsLocal
16936#undef SCIProwIsModifiable
16937#undef SCIProwIsRemovable
16938#undef SCIProwGetOrigintype
16939#undef SCIProwGetOriginCons
16940#undef SCIProwGetOriginConshdlr
16941#undef SCIProwGetOriginSepa
16942#undef SCIProwIsInGlobalCutpool
16943#undef SCIProwGetLPPos
16944#undef SCIProwGetLPDepth
16945#undef SCIProwIsInLP
16946#undef SCIProwGetActiveLPCount
16947#undef SCIProwGetNLPsAfterCreation
16948#undef SCIProwChgRank
16949#undef SCIPlpGetCols
16950#undef SCIPlpGetNCols
16951#undef SCIPlpGetRows
16952#undef SCIPlpGetNRows
16953#undef SCIPlpGetNewcols
16954#undef SCIPlpGetNNewcols
16955#undef SCIPlpGetNewrows
16956#undef SCIPlpGetNNewrows
16957#undef SCIPlpGetObjNorm
16958#undef SCIPlpGetRootObjval
16959#undef SCIPlpGetRootColumnObjval
16960#undef SCIPlpGetRootLooseObjval
16961#undef SCIPlpGetLPI
16962#undef SCIPlpSetIsRelax
16963#undef SCIPlpIsRelax
16964#undef SCIPlpIsSolved
16965#undef SCIPlpIsSolBasic
16966#undef SCIPlpDiving
16967#undef SCIPlpDivingObjChanged
16968#undef SCIPlpMarkDivingObjChanged
16969#undef SCIPlpUnmarkDivingObjChanged
16970#undef SCIPlpDivingRowsChanged
16971#undef SCIPlpIsFeasEQ
16972#undef SCIPlpIsFeasLT
16973#undef SCIPlpIsFeasLE
16974#undef SCIPlpIsFeasGT
16975#undef SCIPlpIsFeasGE
16976#undef SCIPlpIsFeasZero
16977#undef SCIPlpIsFeasPositive
16978#undef SCIPlpIsFeasNegative
16979
16980/** gets objective value of column */
16982 SCIP_COL* col /**< LP column */
16983 )
16984{
16985 assert(col != NULL);
16986
16987 return col->obj;
16988}
16989
16990/** gets lower bound of column */
16992 SCIP_COL* col /**< LP column */
16993 )
16994{
16995 assert(col != NULL);
16996
16997 return col->lb;
16998}
16999
17000/** gets upper bound of column */
17002 SCIP_COL* col /**< LP column */
17003 )
17004{
17005 assert(col != NULL);
17006
17007 return col->ub;
17008}
17009
17010/** gets best bound of column with respect to the objective function */
17012 SCIP_COL* col /**< LP column */
17013 )
17014{
17015 assert(col != NULL);
17016
17017 if( col->obj >= 0.0 )
17018 return col->lb;
17019 else
17020 return col->ub;
17021}
17022
17023/** gets the primal LP solution of a column */
17025 SCIP_COL* col /**< LP column */
17026 )
17027{
17028 assert(col != NULL);
17029
17030 if( col->lppos >= 0 )
17031 return col->primsol;
17032 else
17033 return 0.0;
17034}
17035
17036/** gets the minimal LP solution value, this column ever assumed */
17038 SCIP_COL* col /**< LP column */
17039 )
17040{
17041 assert(col != NULL);
17042
17043 return col->minprimsol;
17044}
17045
17046/** gets the maximal LP solution value, this column ever assumed */
17048 SCIP_COL* col /**< LP column */
17049 )
17050{
17051 assert(col != NULL);
17052
17053 return col->maxprimsol;
17054}
17055
17056/** gets the basis status of a column in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17057 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_ZERO for columns not in the current SCIP_LP
17058 */
17060 SCIP_COL* col /**< LP column */
17061 )
17062{
17063 assert(col != NULL);
17064 assert(col->lppos >= 0 || (SCIP_BASESTAT)col->basisstatus == SCIP_BASESTAT_ZERO);
17065
17066 return (SCIP_BASESTAT)col->basisstatus;
17067}
17068
17069/** gets variable this column represents */
17071 SCIP_COL* col /**< LP column */
17072 )
17073{
17074 assert(col != NULL);
17075
17076 return col->var;
17077}
17078
17079/** gets unique index of col */
17081 SCIP_COL* col /**< LP col */
17082 )
17083{
17084 assert(col != NULL);
17085
17086 return col->index;
17087}
17088
17089/** gets probindex of corresponding variable */
17091 SCIP_COL* col /**< LP col */
17092 )
17093{
17094 assert(col != NULL);
17095
17096 return col->var_probindex;
17097}
17098
17099/** returns whether the associated variable is of integral type (binary, integer, implicit integer) */
17101 SCIP_COL* col /**< LP column */
17102 )
17103{
17104 assert(col != NULL);
17105 assert(SCIPvarIsIntegral(col->var) == col->integral);
17106
17107 return col->integral;
17108}
17109
17110/** returns TRUE iff column is removable from the LP (due to aging or cleanup) */
17112 SCIP_COL* col /**< LP column */
17113 )
17114{
17115 assert(col != NULL);
17116
17117 return col->removable;
17118}
17119
17120/** gets position of column in current LP, or -1 if it is not in LP */
17122 SCIP_COL* col /**< LP column */
17123 )
17124{
17125 assert(col != NULL);
17126 assert((col->lppos == -1) == (col->lpdepth == -1));
17127
17128 return col->lppos;
17129}
17130
17131/** gets depth in the tree where the column entered the LP, or -1 if it is not in LP */
17133 SCIP_COL* col /**< LP column */
17134 )
17135{
17136 assert(col != NULL);
17137 assert((col->lppos == -1) == (col->lpdepth == -1));
17138
17139 return col->lpdepth;
17140}
17141
17142/** returns TRUE iff column is member of current LP */
17144 SCIP_COL* col /**< LP column */
17145 )
17146{
17147 assert(col != NULL);
17148 assert((col->lppos == -1) == (col->lpdepth == -1));
17149
17150 return (col->lppos >= 0);
17151}
17152
17153/** get number of nonzero entries in column vector */
17155 SCIP_COL* col /**< LP column */
17156 )
17157{
17158 assert(col != NULL);
17159
17160 return col->len;
17161}
17162
17163/** get number of nonzero entries in column vector, that correspond to rows currently in the SCIP_LP;
17164 *
17165 * @warning This method is only applicable on columns, that are completely linked to their rows (e.g. a column
17166 * 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
17167 */
17169 SCIP_COL* col /**< LP column */
17170 )
17171{
17172 assert(col != NULL);
17173 assert(col->nunlinked == 0);
17174
17175 return col->nlprows;
17176}
17177
17178/** gets array with rows of nonzero entries */
17180 SCIP_COL* col /**< LP column */
17181 )
17182{
17183 assert(col != NULL);
17184
17185 return col->rows;
17186}
17187
17188/** gets array with coefficients of nonzero entries */
17190 SCIP_COL* col /**< LP column */
17191 )
17192{
17193 assert(col != NULL);
17194
17195 return col->vals;
17196}
17197
17198/** gets node number of the last node in current branch and bound run, where strong branching was used on the
17199 * given column, or -1 if strong branching was never applied to the column in current run
17200 */
17202 SCIP_COL* col /**< LP column */
17203 )
17204{
17205 assert(col != NULL);
17206
17207 return col->sbnode;
17208}
17209
17210/** gets number of times, strong branching was applied in current run on the given column */
17212 SCIP_COL* col /**< LP column */
17213 )
17214{
17215 assert(col != NULL);
17216
17217 return col->nsbcalls;
17218}
17219
17220/** 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 */
17222 SCIP_COL* col /**< LP column */
17223 )
17224{
17225 assert(col != NULL);
17226
17227 return col->age;
17228}
17229
17230/** gets opposite bound type of given bound type */
17232 SCIP_BOUNDTYPE boundtype /**< type of bound (lower or upper) */
17233 )
17234{
17235 assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
17236
17238}
17239
17240/** get number of nonzero entries in row vector */
17242 SCIP_ROW* row /**< LP row */
17243 )
17244{
17245 assert(row != NULL);
17246
17247 return row->len;
17248}
17249
17250/** get number of nonzero entries in row vector, that correspond to columns currently in the SCIP_LP;
17251 *
17252 * @warning This method is only applicable on rows, that are completely linked to their columns (e.g. a row
17253 * 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
17254 */
17256 SCIP_ROW* row /**< LP row */
17257 )
17258{
17259 assert(row != NULL);
17260 assert(row->nunlinked == 0);
17261
17262 return row->nlpcols;
17263}
17264
17265/** gets array with columns of nonzero entries */
17267 SCIP_ROW* row /**< LP row */
17268 )
17269{
17270 assert(row != NULL);
17271
17272 return row->cols;
17273}
17274
17275/** gets array with coefficients of nonzero entries */
17277 SCIP_ROW* row /**< LP row */
17278 )
17279{
17280 assert(row != NULL);
17281
17282 return row->vals;
17283}
17284
17285/** gets constant shift of row */
17287 SCIP_ROW* row /**< LP row */
17288 )
17289{
17290 assert(row != NULL);
17291
17292 return row->constant;
17293}
17294
17295/** gets Euclidean norm of row vector */
17297 SCIP_ROW* row /**< LP row */
17298 )
17299{
17300 assert(row != NULL);
17301
17302 checkRowSqrnorm(row);
17303
17304 return sqrt(row->sqrnorm);
17305}
17306
17307/** gets sum norm of row vector (sum of absolute values of coefficients) */
17309 SCIP_ROW* row /**< LP row */
17310 )
17311{
17312 assert(row != NULL);
17313
17314 checkRowSumnorm(row);
17315
17316 return row->sumnorm;
17317}
17318
17319/** returns the left hand side of the row */
17321 SCIP_ROW* row /**< LP row */
17322 )
17323{
17324 assert(row != NULL);
17325
17326 return row->lhs;
17327}
17328
17329/** returns the right hand side of the row */
17331 SCIP_ROW* row /**< LP row */
17332 )
17333{
17334 assert(row != NULL);
17335
17336 return row->rhs;
17337}
17338
17339/** gets the dual LP solution of a row */
17341 SCIP_ROW* row /**< LP row */
17342 )
17343{
17344 assert(row != NULL);
17345
17346 if( row->lppos >= 0 )
17347 return row->dualsol;
17348 else
17349 return 0.0;
17350}
17351
17352/** gets the dual Farkas coefficient of a row in an infeasible LP */
17354 SCIP_ROW* row /**< LP row */
17355 )
17356{
17357 assert(row != NULL);
17358
17359 if( row->lppos >= 0 )
17360 return row->dualfarkas;
17361 else
17362 return 0.0;
17363}
17364
17365/** gets the basis status of a row in the LP solution; only valid for LPs with status SCIP_LPSOLSTAT_OPTIMAL
17366 * and with SCIPisLPSolBasic(scip) == TRUE; returns SCIP_BASESTAT_BASIC for rows not in the current SCIP_LP
17367 */
17369 SCIP_ROW* row /**< LP row */
17370 )
17371{
17372 assert(row != NULL);
17373 assert(row->lppos >= 0 || (SCIP_BASESTAT)row->basisstatus == SCIP_BASESTAT_BASIC);
17374
17375 return (SCIP_BASESTAT)row->basisstatus;
17376}
17377
17378/** returns the name of the row */
17379const char* SCIProwGetName(
17380 SCIP_ROW* row /**< LP row */
17381 )
17382{
17383 assert(row != NULL);
17384
17385 return row->name;
17386}
17387
17388/** gets unique index of row */
17390 SCIP_ROW* row /**< LP row */
17391 )
17392{
17393 assert(row != NULL);
17394
17395 return row->index;
17396}
17397
17398/** gets age of row */
17400 SCIP_ROW* row /**< LP row */
17401 )
17402{
17403 assert(row != NULL);
17404
17405 return row->age;
17406}
17407
17408/** gets rank of row */
17410 SCIP_ROW* row /**< LP row */
17411 )
17412{
17413 assert(row != NULL);
17414
17415 return row->rank;
17416}
17417
17418/** returns TRUE iff the activity of the row (without the row's constant) is always integral in a feasible solution */
17420 SCIP_ROW* row /**< LP row */
17421 )
17422{
17423 assert(row != NULL);
17424
17425 return row->integral;
17426}
17427
17428/** returns TRUE iff row is only valid locally */
17430 SCIP_ROW* row /**< LP row */
17431 )
17432{
17433 assert(row != NULL);
17434
17435 return row->local;
17436}
17437
17438/** returns TRUE iff row is modifiable during node processing (subject to column generation) */
17440 SCIP_ROW* row /**< LP row */
17441 )
17442{
17443 assert(row != NULL);
17444
17445 return row->modifiable;
17446}
17447
17448/** returns TRUE iff row is removable from the LP (due to aging or cleanup) */
17450 SCIP_ROW* row /**< LP row */
17451 )
17452{
17453 assert(row != NULL);
17454
17455 return row->removable;
17456}
17457
17458/** returns type of origin that created the row */
17460 SCIP_ROW* row /**< LP row */
17461 )
17462{
17463 assert( row != NULL );
17464
17465 return (SCIP_ROWORIGINTYPE) row->origintype;
17466}
17467
17468/** returns origin constraint that created the row (NULL if not available) */
17470 SCIP_ROW* row /**< LP row */
17471 )
17472{
17473 assert( row != NULL );
17474
17476 {
17477 assert( row->origin != NULL );
17478 return (SCIP_CONS*) row->origin;
17479 }
17480 return NULL;
17481}
17482
17483/** returns origin constraint handler that created the row (NULL if not available) */
17485 SCIP_ROW* row /**< LP row */
17486 )
17487{
17488 assert( row != NULL );
17489
17491 {
17492 assert( row->origin != NULL );
17493 return (SCIP_CONSHDLR*) row->origin;
17494 }
17496 {
17497 assert(row->origin != NULL);
17498 return SCIPconsGetHdlr((SCIP_CONS*)row->origin);
17499 }
17500 return NULL;
17501}
17502
17503/** returns origin separator that created the row (NULL if not available) */
17505 SCIP_ROW* row /**< LP row */
17506 )
17507{
17508 assert( row != NULL );
17509
17511 {
17512 assert( row->origin != NULL );
17513 return (SCIP_SEPA*) row->origin;
17514 }
17515 return NULL;
17516}
17517
17518/** returns TRUE iff row is member of the global cut pool */
17520 SCIP_ROW* row /**< LP row */
17521 )
17522{
17523 assert(row != NULL);
17524
17525 return row->inglobalcutpool;
17526}
17527
17528/** gets position of row in current LP, or -1 if it is not in LP */
17530 SCIP_ROW* row /**< LP row */
17531 )
17532{
17533 assert(row != NULL);
17534 assert((row->lppos == -1) == (row->lpdepth == -1));
17535
17536 return row->lppos;
17537}
17538
17539/** gets depth in the tree where the row entered the LP, or -1 if it is not in LP */
17541 SCIP_ROW* row /**< LP row */
17542 )
17543{
17544 assert(row != NULL);
17545 assert((row->lppos == -1) == (row->lpdepth == -1));
17546
17547 return row->lpdepth;
17548}
17549
17550/** returns TRUE iff row is member of current LP */
17552 SCIP_ROW* row /**< LP row */
17553 )
17554{
17555 assert(row != NULL);
17556 assert((row->lppos == -1) == (row->lpdepth == -1));
17557
17558 return (row->lppos >= 0);
17559}
17560
17561/** changes the rank of LP row */
17563 SCIP_ROW* row, /**< LP row */
17564 int rank /**< new value for rank */
17565 )
17566{
17567 assert(row != NULL);
17568
17569 row->rank = rank;
17570}
17571
17572/** returns the number of times that this row has been sharp in an optimal LP solution */
17574 SCIP_ROW* row /**< row */
17575 )
17576{
17577 assert(row != NULL);
17578
17579 return row->activeinlpcounter;
17580}
17581
17582/** returns the number of LPs since this row has been created */
17584 SCIP_ROW* row /**< row */
17585 )
17586{
17587 assert(row != NULL);
17588
17589 return row->nlpsaftercreation;
17590}
17591
17592/** gets array with columns of the LP */
17594 SCIP_LP* lp /**< current LP data */
17595 )
17596{
17597 assert(lp != NULL);
17598
17599 return lp->cols;
17600}
17601
17602/** gets current number of columns in LP */
17604 SCIP_LP* lp /**< current LP data */
17605 )
17606{
17607 assert(lp != NULL);
17608
17609 return lp->ncols;
17610}
17611
17612/** gets current number of unfixed columns in LP */
17614 SCIP_LP* lp, /**< current LP data */
17615 SCIP_Real eps /**< numerical tolerance */
17616 )
17617{
17618 SCIP_COL** lpcols;
17619 int nlpcols;
17620 int nunfixedcols;
17621 int c;
17622
17623 assert(lp != NULL);
17624 assert(eps > 0.0);
17625
17626 lpcols = lp->cols;
17627 nlpcols = lp->ncols;
17628
17629 nunfixedcols = 0;
17630 for( c = 0; c < nlpcols; ++c )
17631 {
17632 if( lpcols[c]->ub - lpcols[c]->lb > eps )
17633 ++nunfixedcols;
17634 }
17635
17636 return nunfixedcols;
17637}
17638
17639/** gets array with rows of the LP */
17641 SCIP_LP* lp /**< current LP data */
17642 )
17643{
17644 assert(lp != NULL);
17645
17646 return lp->rows;
17647}
17648
17649/** gets current number of rows in LP */
17651 SCIP_LP* lp /**< current LP data */
17652 )
17653{
17654 assert(lp != NULL);
17655
17656 return lp->nrows;
17657}
17658
17659/** gets array with newly added columns after the last mark */
17661 SCIP_LP* lp /**< current LP data */
17662 )
17663{
17664 assert(lp != NULL);
17665 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17666
17667 return &(lp->cols[lp->firstnewcol]);
17668}
17669
17670/** gets number of newly added columns after the last mark */
17672 SCIP_LP* lp /**< current LP data */
17673 )
17674{
17675 assert(lp != NULL);
17676 assert(0 <= lp->firstnewcol && lp->firstnewcol <= lp->ncols);
17677
17678 return lp->ncols - lp->firstnewcol;
17679}
17680
17681/** gets array with newly added rows after the last mark */
17683 SCIP_LP* lp /**< current LP data */
17684 )
17685{
17686 assert(lp != NULL);
17687 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17688
17689 return &(lp->rows[lp->firstnewrow]);
17690}
17691
17692/** gets number of newly added rows after the last mark */
17694 SCIP_LP* lp /**< current LP data */
17695 )
17696{
17697 assert(lp != NULL);
17698 assert(0 <= lp->firstnewrow && lp->firstnewrow <= lp->nrows);
17699
17700 return lp->nrows - lp->firstnewrow;
17701}
17702
17703/** recalculates Euclidean norm of objective function vector of column variables if it have gotten unreliable during calculation */
17705 SCIP_SET* set, /**< global SCIP settings */
17706 SCIP_LP* lp /**< LP data */
17707 )
17708{
17709 if( lp->objsqrnormunreliable )
17710 {
17711 SCIP_COL** cols;
17712 int c;
17713
17714 cols = lp->cols;
17715 assert(cols != NULL || lp->ncols == 0);
17716
17717 lp->objsqrnorm = 0.0;
17718
17719 for( c = lp->ncols - 1; c >= 0; --c )
17720 {
17721 lp->objsqrnorm += SQR(cols[c]->unchangedobj); /*lint !e613*/
17722 }
17723 assert(SCIPsetIsGE(set, lp->objsqrnorm, 0.0));
17724
17725 /* due to numerical troubles it still can appear that lp->objsqrnorm is a little bit smaller than 0 */
17726 lp->objsqrnorm = MAX(lp->objsqrnorm, 0.0);
17727
17729 }
17730 return;
17731}
17732
17733/** gets Euclidean norm of objective function vector of column variables, only use this method if
17734 * lp->objsqrnormunreliable == FALSE, so probably you have to call SCIPlpRecalculateObjSqrNorm before */
17736 SCIP_LP* lp /**< LP data */
17737 )
17738{
17739 assert(lp != NULL);
17740 assert(!lp->objsqrnormunreliable);
17741 assert(lp->objsqrnorm >= 0.0);
17742
17743 return sqrt(lp->objsqrnorm);
17744}
17745
17746/** sets whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17748 SCIP_LP* lp, /**< LP data */
17749 SCIP_Bool isrelax /**< is the root lp a relaxation of the problem? */
17750 )
17751{
17752 assert(lp != NULL);
17753
17754 lp->rootlpisrelax = isrelax;
17755}
17756
17757/** returns whether the root lp is a relaxation of the problem and its optimal objective value is a global lower bound */
17759 SCIP_LP* lp /**< LP data */
17760 )
17761{
17762 assert(lp != NULL);
17763
17764 return lp->rootlpisrelax;
17765}
17766
17767/** gets the objective value of the root node LP; returns SCIP_INVALID if the root node LP was not (yet) solved */
17769 SCIP_LP* lp /**< LP data */
17770 )
17771{
17772 assert(lp != NULL);
17773
17774 return MIN(lp->rootlpobjval + lp->rootlooseobjval, SCIP_INVALID);
17775}
17776
17777/** gets part of the objective value of the root node LP that results from COLUMN variables only;
17778 * returns SCIP_INVALID if the root node LP was not (yet) solved
17779 */
17781 SCIP_LP* lp /**< LP data */
17782 )
17783{
17784 assert(lp != NULL);
17785
17786 return lp->rootlpobjval;
17787}
17788
17789/** gets part of the objective value of the root node LP that results from LOOSE variables only;
17790 * returns SCIP_INVALID if the root node LP was not (yet) solved
17791 */
17793 SCIP_LP* lp /**< LP data */
17794 )
17795{
17796 assert(lp != NULL);
17797
17798 return lp->rootlooseobjval;
17799}
17800
17801/** gets the LP solver interface */
17803 SCIP_LP* lp /**< current LP data */
17804 )
17805{
17806 assert(lp != NULL);
17807
17808 return lp->lpi;
17809}
17810
17811/** sets whether the current LP is a relaxation of the current problem and its optimal objective value is a local lower bound */
17813 SCIP_LP* lp, /**< LP data */
17814 SCIP_Bool relax /**< is the current lp a relaxation? */
17815 )
17816{
17817 assert(lp != NULL);
17818
17819 lp->isrelax = relax;
17820}
17821
17822/** returns whether the current LP is a relaxation of the problem for which it has been solved and its
17823 * solution value a valid local lower bound?
17824 */
17826 SCIP_LP* lp /**< LP data */
17827 )
17828{
17829 assert(lp != NULL);
17830
17831 return lp->isrelax;
17832}
17833
17834/** returns whether the current LP is flushed and solved */
17836 SCIP_LP* lp /**< current LP data */
17837 )
17838{
17839 assert(lp != NULL);
17840
17841 return lp->flushed && lp->solved;
17842}
17843
17844/** return whether the current LP solution passed the primal feasibility check */
17846 SCIP_LP* lp /**< current LP data */
17847 )
17848{
17849 assert(lp != NULL);
17850
17851 return (lp->primalchecked && lp->primalfeasible);
17852}
17853
17854/** return whether the current LP solution passed the dual feasibility check */
17856 SCIP_LP* lp /**< current LP data */
17857 )
17858{
17859 assert(lp != NULL);
17860
17861 return (lp->dualchecked && lp->dualfeasible);
17862}
17863
17864/** returns whether the current LP solution is a basic solution */
17866 SCIP_LP* lp /**< current LP data */
17867 )
17868{
17869 assert(lp != NULL);
17870
17871 return lp->solisbasic;
17872}
17873
17874/** returns whether the LP is in diving mode */
17876 SCIP_LP* lp /**< current LP data */
17877 )
17878{
17879 assert(lp != NULL);
17880
17881 return lp->diving;
17882}
17883
17884/** returns whether the LP is in diving mode and the objective value of at least one column was changed */
17886 SCIP_LP* lp /**< current LP data */
17887 )
17888{
17889 assert(lp != NULL);
17890
17891 return lp->divingobjchg;
17892}
17893
17894/** marks the diving LP to have a changed objective function */
17896 SCIP_LP* lp /**< current LP data */
17897 )
17898{
17899 assert(lp != NULL);
17900 assert(lp->diving || lp->probing);
17901
17902 lp->divingobjchg = TRUE;
17903}
17904
17905/** marks the diving LP to not have a changed objective function anymore */
17907 SCIP_LP* lp /**< current LP data */
17908 )
17909{
17910 assert(lp != NULL);
17911 assert(lp->diving || lp->probing);
17912
17913 lp->divingobjchg = FALSE;
17914}
17915
17916/* returns TRUE if at least one left/right hand side of an LP row was changed during diving mode */
17918 SCIP_LP* lp /**< current LP data */
17919 )
17920{
17921 assert(lp != NULL);
17922 assert(lp->diving || lp->ndivechgsides == 0);
17923
17924 return (lp->ndivechgsides > 0);
17925}
17926
17927/** compute relative interior point with auxiliary lpi, see SCIPlpComputeRelIntPoint() */
17928static
17930 SCIP_LPI* lpi, /**< auxiliary LP interface */
17931 SCIP_SET* set, /**< global SCIP settings */
17932 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
17933 SCIP_LP* lp, /**< LP data */
17934 SCIP_PROB* prob, /**< problem data */
17935 SCIP_Bool relaxrows, /**< should the rows be relaxed */
17936 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
17937 SCIP_Real timelimit, /**< time limit for LP solver */
17938 int iterlimit, /**< iteration limit for LP solver */
17939 SCIP_Real* point, /**< array to store relative interior point on exit */
17940 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
17941 )
17942{
17943 SCIP_RETCODE retcode;
17944 SCIP_Real* primal;
17945 SCIP_Real* obj;
17946 SCIP_Real* lb;
17947 SCIP_Real* ub;
17948 SCIP_Real* matvals;
17949 SCIP_Real* matlhs;
17950 SCIP_Real* matrhs;
17951 SCIP_Real objval;
17952 SCIP_Real alpha;
17953 int* matinds;
17954 int* matbeg;
17955#ifndef NDEBUG
17956 int nslacks;
17957#endif
17958 int nnewcols;
17959 int ntotnonz = 0;
17960 int ntotrows = 0;
17961 int matrowidx;
17962 int matidx;
17963 int cnt;
17964 int j;
17965 int i;
17966
17967 assert(lpi != NULL);
17968
17969 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_FEASTOL, lp->feastol);
17970 if( retcode != SCIP_OKAY )
17971 {
17972 /* stop execution on error, since result is likely to be unsuable */
17973 SCIPmessagePrintWarning(messagehdlr, "Could not set feasibility tolerance of LP solver for relative interior point computation.\n");
17974 return SCIP_LPERROR;
17975 }
17976
17978 if( retcode != SCIP_OKAY )
17979 {
17980 /* stop execution on error, since result is likely to be unsuable */
17981 SCIPmessagePrintWarning(messagehdlr, "Could not set dual feasibility tolerance of LP solver for relative interior point computation.\n");
17982 return SCIP_LPERROR;
17983 }
17984
17985 /* get storage */
17986 nnewcols = 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1;
17987 SCIP_CALL( SCIPsetAllocBufferArray(set, &lb, nnewcols) );
17988 SCIP_CALL( SCIPsetAllocBufferArray(set, &ub, nnewcols) );
17989 SCIP_CALL( SCIPsetAllocBufferArray(set, &obj, nnewcols) );
17990
17991 /* create original columns (bounds are relaxed below, unless the variable is fixed) */
17992 for( j = 0; j < lp->ncols; ++j )
17993 {
17994 /* note: if the variable is fixed we cannot simply fix the variables (because alpha scales the problem) */
17995 obj[j] = 0.0;
17996 lb[j] = -SCIPlpiInfinity(lpi);
17997 ub[j] = SCIPlpiInfinity(lpi);
17998 /* note: we could also use the original bounds - free variables seem to be faster. */
17999 }
18000
18001 /* add artificial alpha variable */
18002 nnewcols = lp->ncols;
18003 obj[nnewcols] = 0.0;
18004 lb[nnewcols] = 1.0;
18005 ub[nnewcols] = SCIPlpiInfinity(lpi);
18006 ++nnewcols;
18007
18008 /* create slacks for rows */
18009 for( i = 0; i < lp->nrows; ++i )
18010 {
18011 SCIP_ROW* row;
18012
18013 row = lp->rows[i];
18014 assert( row != NULL );
18015
18016 if( SCIProwIsModifiable(row) )
18017 continue;
18018
18019 /* make sure row is sorted */
18020 rowSortLP(row);
18021 assert( row->lpcolssorted );
18022
18023 /* check whether we have an equation */
18024 if( SCIPsetIsEQ(set, row->lhs, row->rhs) )
18025 {
18026 assert( !SCIPsetIsInfinity(set, REALABS(row->lhs)) );
18027 assert( !SCIPsetIsInfinity(set, REALABS(row->rhs)) );
18028 ntotnonz += row->nlpcols + 1;
18029 ++ntotrows;
18030 }
18031 else
18032 {
18033 /* otherwise add slacks for each side if necessary */
18034 if ( ! SCIPsetIsInfinity(set, REALABS(row->lhs)) )
18035 {
18036 if ( relaxrows )
18037 {
18038 lb[nnewcols] = 0.0;
18039 ub[nnewcols] = 1.0;
18040 obj[nnewcols++] = 1.0;
18041 ntotnonz += row->nlpcols + 2;
18042 }
18043 else
18044 ntotnonz += row->nlpcols + 1;
18045 ++ntotrows;
18046 }
18047 if ( ! SCIPsetIsInfinity(set, REALABS(row->rhs)) )
18048 {
18049 if ( relaxrows )
18050 {
18051 lb[nnewcols] = 0.0;
18052 ub[nnewcols] = 1.0;
18053 obj[nnewcols++] = 1.0;
18054 ntotnonz += row->nlpcols + 2;
18055 }
18056 else
18057 ntotnonz += row->nlpcols + 1;
18058 ++ntotrows;
18059 }
18060 }
18061 }
18062
18063 /* create slacks for objective cutoff row */
18064 if( inclobjcutoff && relaxrows )
18065 {
18066 /* add slacks for right hand side */
18067 lb[nnewcols] = 0.0;
18068 ub[nnewcols] = 1.0;
18069 obj[nnewcols++] = 1.0;
18070 ntotnonz += lp->ncols + 2;
18071 ++ntotrows;
18072 }
18073
18074 /* create slacks for bounds */
18075 for( j = 0; j < lp->ncols; ++j )
18076 {
18077 SCIP_COL* col;
18078
18079 col = lp->cols[j];
18080 assert( col != NULL );
18081
18082 /* no slacks for fixed variables */
18083 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18084 {
18085 ++ntotrows;
18086 ntotnonz += 2;
18087 }
18088 else
18089 {
18090 /* add slacks for each bound if necessary */
18091 if ( ! SCIPsetIsInfinity(set, REALABS(col->lb)) )
18092 {
18093 lb[nnewcols] = 0.0;
18094 ub[nnewcols] = 1.0;
18095 obj[nnewcols++] = 1.0;
18096 ntotnonz += 3;
18097 ++ntotrows;
18098 }
18099 if( ! SCIPsetIsInfinity(set, REALABS(col->ub)) )
18100 {
18101 lb[nnewcols] = 0.0;
18102 ub[nnewcols] = 1.0;
18103 obj[nnewcols++] = 1.0;
18104 ntotnonz += 3;
18105 ++ntotrows;
18106 }
18107 }
18108 }
18109#ifndef NDEBUG
18110 nslacks = nnewcols - lp->ncols - 1;
18111 assert( nslacks >= 0 );
18112 assert( nnewcols <= 3*lp->ncols + 2*lp->nrows + (inclobjcutoff ? 1 : 0) + 1 );
18113#endif
18114
18115 /* add columns */
18116 SCIP_CALL( SCIPlpiAddCols(lpi, nnewcols, obj, lb, ub, NULL, 0, NULL, NULL, NULL) );
18117
18118 /* free storage */
18122
18123 /* prepare storage for rows */
18124 SCIP_CALL( SCIPsetAllocBufferArray(set, &matinds, ntotnonz) );
18125 SCIP_CALL( SCIPsetAllocBufferArray(set, &matvals, ntotnonz) );
18126 SCIP_CALL( SCIPsetAllocBufferArray(set, &matbeg, ntotrows) );
18127 SCIP_CALL( SCIPsetAllocBufferArray(set, &matlhs, ntotrows) );
18128 SCIP_CALL( SCIPsetAllocBufferArray(set, &matrhs, ntotrows) );
18129
18130 /* create rows arising from original rows */
18131 cnt = 0;
18132 matrowidx = 0;
18133 matidx = 0;
18134 for( i = 0; i < lp->nrows; ++i )
18135 {
18136 SCIP_ROW* row;
18137 SCIP_COL** rowcols;
18138 SCIP_Real* rowvals;
18139 SCIP_Real lhs;
18140 SCIP_Real rhs;
18141 int nnonz;
18142
18143 row = lp->rows[i];
18144 assert( row != NULL );
18145
18146 if( SCIProwIsModifiable(row) )
18147 continue;
18148 assert( row->lpcolssorted );
18149
18150 /* get row data */
18151 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18152 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18153 nnonz = row->nlpcols;
18154 assert( nnonz <= lp->ncols );
18155 rowcols = row->cols;
18156 rowvals = row->vals;
18157
18158 /* if we have an equation */
18159 if( SCIPsetIsEQ(set, lhs, rhs) )
18160 {
18161 /* set up indices */
18162 matbeg[matrowidx] = matidx;
18163 for( j = 0; j < nnonz; ++j )
18164 {
18165 assert( rowcols[j] != NULL );
18166 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18167 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18168 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18169 matinds[matidx] = rowcols[j]->lppos;
18170 matvals[matidx++] = rowvals[j];
18171 assert( matidx <= ntotnonz );
18172 }
18173
18174 /* add artificial variable */
18175 if ( ! SCIPsetIsZero(set, rhs) )
18176 {
18177 matinds[matidx] = lp->ncols;
18178 matvals[matidx++] = -rhs;
18179 assert( matidx <= ntotnonz );
18180 }
18181
18182 matlhs[matrowidx] = 0.0;
18183 matrhs[matrowidx++] = 0.0;
18184 assert( matrowidx <= ntotrows );
18185 }
18186 else
18187 {
18188 SCIP_Real abslhs = REALABS(lhs);
18189 SCIP_Real absrhs = REALABS(rhs);
18190
18191 assert(!SCIPsetIsEQ(set, lhs, rhs));
18192
18193 /* treat lhs */
18194 if( !SCIPsetIsInfinity(set, abslhs) )
18195 {
18196 /* set up indices */
18197 matbeg[matrowidx] = matidx;
18198 for( j = 0; j < nnonz; ++j )
18199 {
18200 assert( rowcols[j] != NULL );
18201 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18202 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18203 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18204 matinds[matidx] = rowcols[j]->lppos;
18205 matvals[matidx++] = rowvals[j];
18206 assert( matidx <= ntotnonz );
18207 }
18208
18209 /* add artificial variable */
18210 if ( ! SCIPsetIsZero(set, lhs) )
18211 {
18212 matinds[matidx] = lp->ncols;
18213 matvals[matidx++] = -lhs;
18214 assert( matidx <= ntotnonz );
18215 }
18216
18217 if( relaxrows )
18218 {
18219 /* add slack variable */
18220 matvals[matidx] = -MAX(1.0, lhs); /*lint !e679*/
18221 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18222 assert( matidx <= ntotnonz );
18223 ++cnt;
18224 }
18225
18226 matlhs[matrowidx] = 0.0;
18227 matrhs[matrowidx++] = SCIPlpiInfinity(lpi);
18228 assert( matrowidx <= ntotrows );
18229 }
18230
18231 /* treat rhs */
18232 if( !SCIPsetIsInfinity(set, absrhs) )
18233 {
18234 /* set up indices */
18235 matbeg[matrowidx] = matidx;
18236 for( j = 0; j < nnonz; ++j )
18237 {
18238 assert( rowcols[j] != NULL );
18239 assert( 0 <= rowcols[j]->lppos && rowcols[j]->lppos < lp->ncols );
18240 assert( lp->cols[rowcols[j]->lppos] == rowcols[j] );
18241 assert( ! SCIPsetIsZero(set, rowvals[j]) );
18242 matinds[matidx] = rowcols[j]->lppos;
18243 matvals[matidx++] = rowvals[j];
18244 assert( matidx <= ntotnonz );
18245 }
18246
18247 /* add artificial variable */
18248 if ( ! SCIPsetIsZero(set, rhs) )
18249 {
18250 matinds[matidx] = lp->ncols;
18251 matvals[matidx++] = -rhs;
18252 assert( matidx <= ntotnonz );
18253 }
18254
18255 if( relaxrows )
18256 {
18257 /* add slack variable */
18258 matvals[matidx] = MAX(1.0, absrhs); /*lint !e679*/
18259 matinds[matidx++] = lp->ncols + 1 + cnt; /*lint !e679*/
18260 ++cnt;
18261 }
18262
18263 matlhs[matrowidx] = -SCIPlpiInfinity(lpi);
18264 matrhs[matrowidx++] = 0.0;
18265 assert( matrowidx <= ntotrows );
18266 }
18267 }
18268 }
18269
18270 /* create row arising from objective cutoff */
18271 if( inclobjcutoff )
18272 {
18273 SCIP_Real rhs;
18274
18275 /* get row data */
18276 assert(lp->looseobjvalinf == 0);
18277 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18278
18279 /* set up indices and coefficients */
18280 matbeg[matrowidx] = matidx;
18281 for( j = 0; j < lp->ncols; ++j )
18282 {
18283 assert( lp->cols[j] != NULL );
18284 assert( 0 <= lp->cols[j]->lppos && lp->cols[j]->lppos < lp->ncols );
18285 assert( lp->cols[lp->cols[j]->lppos] == lp->cols[j] );
18286
18287 if( ! SCIPsetIsZero(set, lp->cols[j]->obj) )
18288 {
18289 matinds[matidx] = lp->cols[j]->lppos;
18290 matvals[matidx++] = lp->cols[j]->obj;
18291 assert( matidx <= ntotnonz );
18292 }
18293 }
18294
18295 /* treat rhs */
18296
18297 /* add artificial variable */
18298 if ( ! SCIPsetIsZero(set, rhs) )
18299 {
18300 matinds[matidx] = lp->ncols;
18301 matvals[matidx++] = -rhs;
18302 assert( matidx <= ntotnonz );
18303 }
18304
18305 if( relaxrows )
18306 {
18307 SCIP_Real absrhs = REALABS(rhs);
18308
18309 /* add slack variable */
18310 matvals[matidx] = MAX(1.0, absrhs);
18311 matinds[matidx++] = lp->ncols + 1 + cnt;
18312 assert( matidx <= ntotnonz );
18313 ++cnt;
18314 }
18315 matlhs[matrowidx] = -SCIPsetInfinity(set);
18316 matrhs[matrowidx++] = 0.0;
18317 assert( matrowidx <= ntotrows );
18318 }
18319
18320 /* create rows arising from bounds */
18321 for( j = 0; j < lp->ncols; ++j )
18322 {
18323 SCIP_COL* col;
18324 SCIP_Real abscollb;
18325 SCIP_Real abscolub;
18326
18327 col = lp->cols[j];
18328 assert( col != NULL );
18329 assert( col->lppos == j );
18330
18331 /* fixed variable */
18332 if( SCIPsetIsEQ(set, col->lb, col->ub) )
18333 {
18334 /* set up index of column */
18335 matbeg[matrowidx] = matidx;
18336
18337 matinds[matidx] = j;
18338 matvals[matidx++] = 1.0;
18339 assert( matidx <= ntotnonz );
18340
18341 /* add artificial variable */
18342 if ( ! SCIPsetIsZero(set, col->ub) )
18343 {
18344 matinds[matidx] = lp->ncols;
18345 matvals[matidx++] = -col->ub;
18346 assert( matidx <= ntotnonz );
18347 }
18348
18349 matlhs[matrowidx] = 0.0;
18350 matrhs[matrowidx++] = 0.0;
18351 assert( matrowidx <= ntotrows );
18352
18353 continue;
18354 }
18355
18356 abscollb = REALABS(col->lb);
18357 abscolub = REALABS(col->ub);
18358
18359 /* lower bound */
18360 if ( ! SCIPsetIsInfinity(set, abscollb) )
18361 {
18362 /* set up index of column */
18363 matbeg[matrowidx] = matidx;
18364
18365 matinds[matidx] = j;
18366 matvals[matidx++] = 1.0;
18367 assert( matidx <= ntotnonz );
18368
18369 /* add artificial variable */
18370 if ( ! SCIPsetIsZero(set, col->lb) )
18371 {
18372 matinds[matidx] = lp->ncols;
18373 matvals[matidx++] = -col->lb;
18374 assert( matidx <= ntotnonz );
18375 }
18376
18377 /* add slack variable */
18378 matvals[matidx] = -MAX(1.0, abscollb);
18379 matinds[matidx++] = lp->ncols + 1 + cnt;
18380 assert( matidx <= ntotnonz );
18381 ++cnt;
18382
18383 matlhs[matrowidx] = 0.0;
18384 matrhs[matrowidx++] = SCIPsetInfinity(set);
18385 assert( matrowidx <= ntotrows );
18386 }
18387
18388 /* upper bound */
18389 if ( ! SCIPsetIsInfinity(set, abscolub) )
18390 {
18391 /* set up index of column */
18392 matbeg[matrowidx] = matidx;
18393
18394 matinds[matidx] = j;
18395 matvals[matidx++] = 1.0;
18396 assert( matidx <= ntotnonz );
18397
18398 /* add artificial variable */
18399 if ( ! SCIPsetIsZero(set, col->ub) )
18400 {
18401 matinds[matidx] = lp->ncols;
18402 matvals[matidx++] = -col->ub;
18403 assert( matidx <= ntotnonz );
18404 }
18405
18406 /* add slack variable */
18407 matvals[matidx] = MAX(1.0, abscolub);
18408 matinds[matidx++] = lp->ncols + 1 + cnt;
18409 assert( matidx <= ntotnonz );
18410 ++cnt;
18411
18412 matlhs[matrowidx] = -SCIPsetInfinity(set);
18413 matrhs[matrowidx++] = 0.0;
18414 assert( matrowidx <= ntotrows );
18415 }
18416 }
18417 assert( cnt == nslacks );
18418 assert( matrowidx == ntotrows );
18419
18420 /* add rows */
18421 SCIP_CALL( SCIPlpiAddRows(lpi, ntotrows, matlhs, matrhs, NULL, matidx, matbeg, matinds, matvals) );
18422
18423 SCIPsetFreeBufferArray(set, &matrhs);
18424 SCIPsetFreeBufferArray(set, &matlhs);
18425 SCIPsetFreeBufferArray(set, &matbeg);
18426 SCIPsetFreeBufferArray(set, &matvals);
18427 SCIPsetFreeBufferArray(set, &matinds);
18428
18429#ifdef SCIP_OUTPUT
18430 SCIP_CALL( SCIPlpiWriteLP(lpi, "relativeInterior.lp") );
18431#endif
18432
18433#ifndef NDEBUG
18434 {
18435 int ncols;
18436 SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
18437 assert( ncols == nnewcols );
18438 }
18439#endif
18440
18441 /* set time limit */
18442 if( SCIPsetIsInfinity(set, timelimit) )
18443 timelimit = SCIPlpiInfinity(lpi);
18444 retcode = SCIPlpiSetRealpar(lpi, SCIP_LPPAR_LPTILIM, timelimit);
18445
18446 /* check, if parameter is unknown */
18447 if( retcode == SCIP_PARAMETERUNKNOWN )
18448 SCIPmessagePrintWarning(messagehdlr, "Could not set time limit of LP solver for relative interior point computation.\n");
18449 else if ( retcode != SCIP_OKAY )
18450 return retcode;
18451
18452 /* set iteration limit */
18453 retcode = SCIPlpiSetIntpar(lpi, SCIP_LPPAR_LPITLIM, iterlimit);
18454
18455 /* check, if parameter is unknown */
18456 if( retcode == SCIP_PARAMETERUNKNOWN )
18457 SCIPmessagePrintWarning(messagehdlr, "Could not set iteration limit of LP solver for relative interior point computation.\n");
18458 else if ( retcode != SCIP_OKAY )
18459 return retcode;
18460
18461 /* solve and store point */
18462 /* SCIP_CALL( SCIPlpiSolvePrimal(lpi) ); */
18463 SCIP_CALL( SCIPlpiSolveDual(lpi) ); /* dual is usually faster */
18464
18465#ifndef NDEBUG
18466 if ( SCIPlpiIsIterlimExc(lpi) )
18467 SCIPmessagePrintWarning(messagehdlr, "Iteration limit exceeded in relative interior point computation.\n");
18468 if ( SCIPlpiIsTimelimExc(lpi) )
18469 SCIPmessagePrintWarning(messagehdlr, "Time limit exceeded in relative interior point computation.\n");
18470#endif
18471
18472 if( SCIPlpiIsOptimal(lpi) )
18473 {
18474 /* get primal solution */
18475 SCIP_CALL( SCIPsetAllocBufferArray(set, &primal, nnewcols) );
18476 SCIP_CALL( SCIPlpiGetSol(lpi, &objval, primal, NULL, NULL, NULL) );
18477 alpha = primal[lp->ncols];
18478 assert( SCIPsetIsFeasGE(set, alpha, 1.0) );
18479
18480 SCIPsetDebugMsg(set, "Solved relative interior lp with objective %g.\n", objval);
18481
18482 /* construct relative interior point */
18483 for( j = 0; j < lp->ncols; ++j )
18484 point[j] = primal[j]/alpha;
18485
18486#ifdef SCIP_DEBUG
18487 /* check whether the point is a relative interior point */
18488 cnt = 0;
18489 if( relaxrows )
18490 {
18491 for( i = 0; i < lp->nrows; ++i )
18492 {
18493 SCIP_ROW* row;
18494 SCIP_COL** rowcols;
18495 SCIP_Real* rowvals;
18496 SCIP_Real lhs;
18497 SCIP_Real rhs;
18498 SCIP_Real sum;
18499 int nnonz;
18500
18501 row = lp->rows[i];
18502 assert( row != NULL );
18503
18504 /* get row data */
18505 lhs = row->lhs - (SCIPsetIsInfinity(set, -row->lhs) ? 0.0 : row->constant);
18506 rhs = row->rhs - (SCIPsetIsInfinity(set, row->rhs) ? 0.0 : row->constant);
18507 nnonz = row->nlpcols;
18508 assert( nnonz <= lp->ncols );
18509 rowcols = row->cols;
18510 rowvals = row->vals;
18511
18512 sum = 0.0;
18513 for( j = 0; j < nnonz; ++j )
18514 sum += rowvals[j] * primal[rowcols[j]->lppos];
18515 sum /= alpha;
18516
18517 /* if we have an equation */
18518 if( SCIPsetIsEQ(set, lhs, rhs) )
18519 {
18520 assert( SCIPsetIsFeasEQ(set, sum, lhs) );
18521 }
18522 else
18523 {
18524 /* treat lhs */
18525 if( !SCIPsetIsInfinity(set, REALABS(lhs)) )
18526 {
18527 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, sum, lhs) );
18528 ++cnt;
18529 }
18530 /* treat rhs */
18531 if( !SCIPsetIsInfinity(set, REALABS(rhs)) )
18532 {
18533 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18534 ++cnt;
18535 }
18536 }
18537 }
18538 if( inclobjcutoff )
18539 {
18540 SCIP_Real sum;
18541#ifndef NDEBUG
18542 SCIP_Real rhs;
18543
18544 rhs = lp->cutoffbound - getFiniteLooseObjval(lp, set, prob);
18545#endif
18546 sum = 0.0;
18547 for( j = 0; j < lp->ncols; ++j )
18548 sum += lp->cols[j]->obj * primal[lp->cols[j]->lppos];
18549 sum /= alpha;
18550
18551 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, sum, rhs) );
18552 ++cnt;
18553 }
18554 }
18555 /* check bounds */
18556 for( j = 0; j < lp->ncols; ++j )
18557 {
18558 SCIP_COL* col;
18559#ifndef NDEBUG
18560 SCIP_Real val;
18561#endif
18562
18563 col = lp->cols[j];
18564 assert( col != NULL );
18565#ifndef NDEBUG
18566 val = primal[col->lppos] / alpha;
18567#endif
18568 /* if the variable is not fixed */
18569 if( !SCIPsetIsEQ(set, col->lb, col->ub) )
18570 {
18571 /* treat lb */
18572 if( !SCIPsetIsInfinity(set, REALABS(col->lb)) )
18573 {
18574 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasGT(set, val, col->lb) );
18575 ++cnt;
18576 }
18577 /* treat rhs */
18578 if( !SCIPsetIsInfinity(set, REALABS(col->ub)) )
18579 {
18580 assert( SCIPsetIsFeasZero(set, primal[lp->ncols+1+cnt]) || SCIPsetIsFeasLT(set, val, col->ub) );
18581 ++cnt;
18582 }
18583 }
18584 }
18585#endif
18586
18587 /* free */
18588 SCIPsetFreeBufferArray(set, &primal);
18589
18590 *success = TRUE;
18591 }
18592
18593 return SCIP_OKAY;
18594}
18595
18596/** compute relative interior point
18597 *
18598 * We use the approach of@par
18599 * R. Freund, R. Roundy, M. J. Todd@par
18600 * "Identifying the Set of Always-Active Constraints in a System of Linear Inequalities by a Single Linear Program"@par
18601 * Tech. Rep, No. 1674-85, Sloan School, M.I.T., 1985
18602 *
18603 * to compute a relative interior point for the current LP.
18604 *
18605 * Assume the original LP looks as follows:
18606 * \f[
18607 * \begin{array}{rrl}
18608 * \min & c^T x &\\
18609 * & A x & \geq a\\
18610 * & B x & \leq b\\
18611 * & D x & = d.
18612 * \end{array}
18613 * \f]
18614 * Note that bounds should be included in the system.
18615 *
18616 * To find an interior point the following LP does the job:
18617 * \f[
18618 * \begin{array}{rrl}
18619 * \max & 1^T y &\\
18620 * & A x - y - \alpha a & \geq 0\\
18621 * & B x + y - \alpha b & \leq 0\\
18622 * & D x - \alpha d & = 0\\
18623 * & 0 \leq y & \leq 1\\
18624 * & \alpha & \geq 1.
18625 * \end{array}
18626 * \f]
18627 * If the original LP is feasible, this LP is feasible as well. Any optimal solution yields the relative interior point
18628 * \f$x^*_j/\alpha^*\f$. Note that this will just produce some relative interior point. It does not produce a
18629 * particular relative interior point, e.g., one that maximizes the distance to the boundary in some norm.
18630 */
18632 SCIP_SET* set, /**< global SCIP settings */
18633 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
18634 SCIP_LP* lp, /**< LP data */
18635 SCIP_PROB* prob, /**< problem data */
18636 SCIP_Bool relaxrows, /**< should the rows be relaxed */
18637 SCIP_Bool inclobjcutoff, /**< should a row for the objective cutoff be included */
18638 SCIP_Real timelimit, /**< time limit for LP solver */
18639 int iterlimit, /**< iteration limit for LP solver */
18640 SCIP_Real* point, /**< array to store relative interior point on exit */
18641 SCIP_Bool* success /**< buffer to indicate whether interior point was successfully computed */
18642 )
18643{
18644 SCIP_LPI* lpi;
18645 SCIP_RETCODE retcode;
18646
18647 assert(set != NULL);
18648 assert(lp != NULL);
18649 assert(point != NULL);
18650 assert(success != NULL);
18651
18652 *success = FALSE;
18653
18654 /* check time and iteration limits */
18655 if ( timelimit <= 0.0 || iterlimit <= 0 )
18656 return SCIP_OKAY;
18657
18658 /* exit if there are no columns */
18659 assert(lp->nrows >= 0);
18660 assert(lp->ncols >= 0);
18661 if( lp->ncols == 0 )
18662 return SCIP_OKAY;
18663
18664 /* disable objective cutoff if we have none */
18665 if( inclobjcutoff && (SCIPsetIsInfinity(set, lp->cutoffbound) || lp->looseobjvalinf > 0 || lp->looseobjval == SCIP_INVALID) ) /*lint !e777 */
18666 inclobjcutoff = FALSE;
18667
18668 SCIPsetDebugMsg(set, "Computing relative interior point to current LP.\n");
18669
18670 /* if there are no rows, we return the zero point */
18671 if( lp->nrows == 0 && !inclobjcutoff )
18672 {
18673 /* create zero point */
18674 BMSclearMemoryArray(point, lp->ncols);
18675 *success = TRUE;
18676
18677 return SCIP_OKAY;
18678 }
18679
18680 /* create auxiliary LP */
18681 SCIP_CALL( SCIPlpiCreate(&lpi, messagehdlr, "relativeInterior", SCIP_OBJSEN_MAXIMIZE) );
18682
18683 /* catch return code and ensure that lpi is freed, anyway */
18684 retcode = computeRelIntPoint(lpi, set, messagehdlr, lp, prob, relaxrows, inclobjcutoff, timelimit, iterlimit, point, success);
18685
18686 SCIP_CALL( SCIPlpiFree(&lpi) );
18687
18688 /* return error, unless we obtained an LP error */
18689 if ( retcode != SCIP_OKAY && retcode != SCIP_LPERROR )
18690 {
18691 SCIP_CALL( retcode );
18692 }
18693
18694 return SCIP_OKAY;
18695}
18696
18697/** computes two measures for dual degeneracy (dual degeneracy rate and variable-constraint ratio)
18698 * based on the changes applied when reducing the problem to the optimal face
18699 *
18700 * returns the dual degeneracy rate, i.e., the share of nonbasic variables with reduced cost 0
18701 * and the variable-constraint ratio, i.e., the number of unfixed variables in relation to the basis size
18702 */
18704 SCIP_LP* lp, /**< LP data */
18705 SCIP_SET* set, /**< global SCIP settings */
18706 SCIP_STAT* stat, /**< problem statistics */
18707 SCIP_Real* degeneracy, /**< pointer to store the dual degeneracy rate */
18708 SCIP_Real* varconsratio /**< pointer to store the variable-constraint ratio */
18709 )
18710{
18711 assert(lp != NULL);
18712 assert(lp->solved);
18713 assert(lp->flushed);
18714
18715 if( lp->validdegeneracylp != stat->nlps )
18716 {
18717 lp->validdegeneracylp = stat->nlps;
18718
18719 /* if the LP was solved to optimality, we determine the dual degeneracy */
18721 {
18722 SCIP_COL** cols;
18723 SCIP_ROW** rows;
18724 SCIP_COL* col;
18725 int ncols;
18726 int nrows;
18727 int nfixedcols = 0;
18728 int nalreadyfixedcols = 0;
18729 int nfixedrows = 0;
18730#ifndef NDEBUG
18731 int nimplicitfixedrows = 0;
18732#endif
18733 int nineq = 0;
18734 int c;
18735 int r;
18736 int nbasicequalities = 0;
18737
18738 cols = lp->cols;
18739 rows = lp->rows;
18740 ncols = lp->ncols;
18741 nrows = lp->nrows;
18742
18743 /* count number of columns that will be fixed when reducing the LP to the optimal face */
18744 for( c = ncols - 1 ; c >= 0; --c )
18745 {
18746 col = cols[c];
18747 assert(SCIPcolIsInLP(col));
18748
18749 /* column is not basic and not fixed already */
18751 {
18752 /* variable with nonzero reduced costs are fixed */
18753 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18754 if( !SCIPsetIsZero(set, SCIPcolGetRedcost(col, stat, lp)) )
18755 ++nfixedcols;
18756 else if( SCIPsetIsEQ(set, SCIPcolGetLb(col), SCIPcolGetUb(col)) )
18757 ++nalreadyfixedcols;
18758 }
18759 }
18760
18761 /* count number of rows that will be turned into equations when reducing the LP to the optimal face */
18762 for( r = nrows - 1; r >= 0; --r )
18763 {
18764 SCIP_ROW* row = rows[r];
18765
18766 assert(SCIProwIsInLP(row));
18767
18768 if( !SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetRhs(row)) )
18769 {
18770 SCIP_Real dualsol = SCIProwGetDualsol(row);
18771
18772 ++nineq;
18773
18775 {
18776 /* rows with nonzero dual solution are turned into equations */
18777 /* @todo which tolerance should be used here? epsilon or dualfeastol? */
18778 if( !SCIPsetIsZero(set, dualsol) )
18779 {
18780 if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18781 {
18782 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasNegative(set, dualsol));
18783 ++nfixedrows;
18784 }
18785 else if( SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetLPActivity(row, set, stat, lp)) )
18786 {
18787 assert(!SCIPlpIsDualReliable(lp) || !SCIPsetIsDualfeasPositive(set, dualsol));
18788 ++nfixedrows;
18789 }
18790 }
18791#ifndef NDEBUG
18792 else if( SCIPsetIsEQ(set, SCIProwGetLhs(row), SCIProwGetMaxActivity(row, set, stat))
18793 || SCIPsetIsEQ(set, SCIProwGetRhs(row), SCIProwGetMinActivity(row, set, stat)) )
18794 {
18795 ++nimplicitfixedrows;
18796 }
18797#endif
18798 }
18799 }
18801 ++nbasicequalities;
18802 }
18803 assert(nfixedcols + nfixedrows <= ncols + nineq + nbasicequalities - nrows - nalreadyfixedcols - nimplicitfixedrows);
18804
18805 if( ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols > 0 )
18806 lp->degeneracy = 1.0 - 1.0 * (nfixedcols + nfixedrows) / (ncols + nineq - nrows + nbasicequalities - nalreadyfixedcols);
18807 else
18808 lp->degeneracy = 0.0;
18809
18810 if( nrows > 0 )
18811 lp->varconsratio = 1.0 * (ncols + nineq + nbasicequalities - nfixedcols - nfixedrows - nalreadyfixedcols) / nrows;
18812 else
18813 lp->varconsratio = 1.0; /* @todo should this rather be set to a large value? */
18814 assert(lp->degeneracy >= 0);
18815 assert(SCIPsetIsLE(set, lp->degeneracy, 1.0));
18816 assert(SCIPsetIsGE(set, lp->varconsratio, 1.0));
18817 }
18818 else
18819 {
18820 lp->degeneracy = 0.0;
18821 lp->varconsratio = 0.0;
18822 }
18823 }
18824
18825 *degeneracy = lp->degeneracy;
18826 *varconsratio = lp->varconsratio;
18827
18828 return SCIP_OKAY;
18829}
18830
18831/** checks, if absolute difference of values is in range of LP primal feastol */
18833 SCIP_SET* set, /**< global SCIP settings */
18834 SCIP_LP* lp, /**< current LP data */
18835 SCIP_Real val1, /**< first value to be compared */
18836 SCIP_Real val2 /**< second value to be compared */
18837 )
18838{
18839 assert(set != NULL);
18840 assert(lp != NULL);
18841
18842 /* avoid to compare two different infinities; the reason for that is
18843 * that such a comparison can lead to unexpected results */
18844 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18845 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18846 || val1 == val2 ); /*lint !e777*/
18847
18848 return EPSEQ(val1, val2, lp->feastol);
18849}
18850
18851/** checks, if absolute difference of val1 and val2 is lower than LP primal feastol */
18853 SCIP_SET* set, /**< global SCIP settings */
18854 SCIP_LP* lp, /**< current LP data */
18855 SCIP_Real val1, /**< first value to be compared */
18856 SCIP_Real val2 /**< second value to be compared */
18857 )
18858{
18859 assert(set != NULL);
18860 assert(lp != NULL);
18861
18862 /* avoid to compare two different infinities; the reason for that is
18863 * that such a comparison can lead to unexpected results */
18864 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18865 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18866 || val1 == val2 ); /*lint !e777*/
18867
18868 return EPSLT(val1, val2, lp->feastol);
18869}
18870
18871/** checks, if absolute difference of val1 and val2 is not greater than LP primal feastol */
18873 SCIP_SET* set, /**< global SCIP settings */
18874 SCIP_LP* lp, /**< current LP data */
18875 SCIP_Real val1, /**< first value to be compared */
18876 SCIP_Real val2 /**< second value to be compared */
18877 )
18878{
18879 assert(set != NULL);
18880 assert(lp != NULL);
18881
18882 /* avoid to compare two different infinities; the reason for that is
18883 * that such a comparison can lead to unexpected results */
18884 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18885 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18886 || val1 == val2 ); /*lint !e777*/
18887
18888 return EPSLE(val1, val2, lp->feastol);
18889}
18890
18891/** checks, if absolute difference of val1 and val2 is greater than LP primal feastol */
18893 SCIP_SET* set, /**< global SCIP settings */
18894 SCIP_LP* lp, /**< current LP data */
18895 SCIP_Real val1, /**< first value to be compared */
18896 SCIP_Real val2 /**< second value to be compared */
18897 )
18898{
18899 assert(set != NULL);
18900 assert(lp != NULL);
18901
18902 /* avoid to compare two different infinities; the reason for that is
18903 * that such a comparison can lead to unexpected results */
18904 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18905 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18906 || val1 == val2 ); /*lint !e777*/
18907
18908 return EPSGT(val1, val2, lp->feastol);
18909}
18910
18911/** checks, if absolute difference of val1 and val2 is not lower than -LP primal feastol */
18913 SCIP_SET* set, /**< global SCIP settings */
18914 SCIP_LP* lp, /**< current LP data */
18915 SCIP_Real val1, /**< first value to be compared */
18916 SCIP_Real val2 /**< second value to be compared */
18917 )
18918{
18919 assert(set != NULL);
18920 assert(lp != NULL);
18921
18922 /* avoid to compare two different infinities; the reason for that is
18923 * that such a comparison can lead to unexpected results */
18924 assert( ((!SCIPsetIsInfinity(set, val1) || !SCIPsetIsInfinity(set, val2))
18925 && (!SCIPsetIsInfinity(set, -val1) || !SCIPsetIsInfinity(set, -val2)))
18926 || val1 == val2 ); /*lint !e777*/
18927
18928 return EPSGE(val1, val2, lp->feastol);
18929}
18930
18931/** checks, if value is in range LP primal feasibility tolerance of 0.0 */
18933 SCIP_LP* lp, /**< current LP data */
18934 SCIP_Real val /**< value to process */
18935 )
18936{
18937 assert(lp != NULL);
18938
18939 return EPSZ(val, lp->feastol);
18940}
18941
18942/** checks, if value is greater than LP primal feasibility tolerance */
18944 SCIP_LP* lp, /**< current LP data */
18945 SCIP_Real val /**< value to process */
18946 )
18947{
18948 assert(lp != NULL);
18949
18950 return EPSP(val, lp->feastol);
18951}
18952
18953/** checks, if value is lower than -LP primal feasibility tolerance */
18955 SCIP_LP* lp, /**< current LP data */
18956 SCIP_Real val /**< value to process */
18957 )
18958{
18959 assert(lp != NULL);
18960
18961 return EPSN(val, lp->feastol);
18962}
static long bound
SCIP_VAR * a
Definition: circlepacking.c:66
SCIP_VAR ** b
Definition: circlepacking.c:65
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_Real * r
Definition: circlepacking.c:59
SCIP_VAR ** x
Definition: circlepacking.c:63
void SCIPclockStop(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:360
void SCIPclockStart(SCIP_CLOCK *clck, SCIP_SET *set)
Definition: clock.c:290
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:438
internal methods for clocks and timing issues
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6254
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6266
internal methods for constraints and constraint handlers
#define NULL
Definition: def.h:266
#define SCIP_MAXSTRLEN
Definition: def.h:287
#define EPSGE(x, y, eps)
Definition: def.h:201
#define SCIP_Longint
Definition: def.h:157
#define SCIP_UNUSED(x)
Definition: def.h:427
#define EPSISINT(x, eps)
Definition: def.h:209
#define SCIP_DEFAULT_SUMEPSILON
Definition: def.h:179
#define EPSP(x, eps)
Definition: def.h:203
#define SCIP_REAL_MAX
Definition: def.h:173
#define SCIP_INVALID
Definition: def.h:192
#define SCIP_Bool
Definition: def.h:91
#define SCIP_DEFAULT_EPSILON
Definition: def.h:178
#define EPSLE(x, y, eps)
Definition: def.h:199
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define SCIP_Real
Definition: def.h:172
#define SCIP_UNKNOWN
Definition: def.h:193
#define EPSLT(x, y, eps)
Definition: def.h:198
#define ABS(x)
Definition: def.h:234
#define SQR(x)
Definition: def.h:213
#define EPSEQ(x, y, eps)
Definition: def.h:197
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:238
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define EPSN(x, eps)
Definition: def.h:204
#define SCIP_LONGINT_FORMAT
Definition: def.h:164
#define SCIPABORT()
Definition: def.h:345
#define REALABS(x)
Definition: def.h:196
#define EPSGT(x, y, eps)
Definition: def.h:200
#define SCIP_LONGINT_MAX
Definition: def.h:158
#define EPSZ(x, eps)
Definition: def.h:202
#define SCIP_CALL(x)
Definition: def.h:373
SCIP_RETCODE SCIPeventCreateRowDeletedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:913
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2240
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1846
SCIP_RETCODE SCIPeventCreateRowSideChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_SIDETYPE side, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:980
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1979
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1821
SCIP_RETCODE SCIPeventCreateRowConstChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:957
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1886
SCIP_RETCODE SCIPeventCreateRowCoefChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row, SCIP_COL *col, SCIP_Real oldval, SCIP_Real newval)
Definition: event.c:932
SCIP_RETCODE SCIPeventCreateRowAddedLP(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:894
internal methods for managing events
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_clp.cpp:1167
SCIP_RETCODE SCIPlpiSetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3429
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3349
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real *dval)
Definition: lpi_clp.cpp:3796
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:3919
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2690
SCIP_Bool SCIPlpiExistsPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2450
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_clp.cpp:2967
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:914
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI *lpi, SCIP_Real *ray)
Definition: lpi_clp.cpp:2832
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_clp.cpp:3648
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_clp.cpp:4001
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_clp.cpp:480
SCIP_RETCODE SCIPlpiSetRealpar(SCIP_LPI *lpi, SCIP_LPPARAM type, SCIP_Real dval)
Definition: lpi_clp.cpp:3833
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2283
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_clp.cpp:3610
SCIP_RETCODE SCIPlpiStrongbranchInt(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2329
SCIP_RETCODE SCIPlpiGetBounds(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *lbs, SCIP_Real *ubs)
Definition: lpi_clp.cpp:1709
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_clp.cpp:2857
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_clp.cpp:2766
int SCIPlpiGetInternalStatus(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2752
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2006
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_clp.cpp:2405
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3623
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2720
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_clp.cpp:1084
SCIP_Bool SCIPlpiIsPrimalUnbounded(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2488
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_clp.cpp:1647
SCIP_RETCODE SCIPlpiFree(SCIP_LPI **lpi)
Definition: lpi_clp.cpp:643
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2304
SCIP_Bool SCIPlpiIsPrimalFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2521
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2609
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_clp.cpp:3592
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2736
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_clp.cpp:3522
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_clp.cpp:3692
const char * SCIPlpiGetSolverName(void)
Definition: lpi_clp.cpp:454
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2468
SCIP_RETCODE SCIPlpiGetBInvRow(SCIP_LPI *lpi, int r, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3241
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_clp.cpp:986
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3276
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int r, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_clp.cpp:3314
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_clp.cpp:1957
SCIP_Bool SCIPlpiIsOptimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2623
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2018
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_clp.cpp:1740
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_clp.cpp:2350
SCIP_RETCODE SCIPlpiGetSol(SCIP_LPI *lpi, SCIP_Real *objval, SCIP_Real *primsol, SCIP_Real *dualsol, SCIP_Real *activity, SCIP_Real *redcost)
Definition: lpi_clp.cpp:2788
SCIP_Bool SCIPlpiHasDualRay(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2556
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:868
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_clp.cpp:1686
SCIP_RETCODE SCIPlpiFreeState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3503
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2502
SCIP_RETCODE SCIPlpiSolveDual(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1880
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_clp.cpp:758
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:1805
SCIP_RETCODE SCIPlpiGetIterations(SCIP_LPI *lpi, int *iterations)
Definition: lpi_clp.cpp:2921
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI *lpi, int *bind)
Definition: lpi_clp.cpp:3189
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_clp.cpp:531
SCIP_RETCODE SCIPlpiChgObj(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *obj)
Definition: lpi_clp.cpp:1240
SCIP_Bool SCIPlpiIsStable(SCIP_LPI *lpi)
Definition: lpi_clp.cpp:2647
SCIP_RETCODE SCIPlpiGetNCols(SCIP_LPI *lpi, int *ncols)
Definition: lpi_clp.cpp:1435
SCIP_RETCODE SCIPlpiInterrupt(SCIP_LPI *lpi, SCIP_Bool interrupt)
Definition: lpi_clp.cpp:3895
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_clp.cpp:837
SCIP_RETCODE SCIPlpiDelRowset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_clp.cpp:1018
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_clp.cpp:1417
SCIP_RETCODE SCIPlpiGetState(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPISTATE **lpistate)
Definition: lpi_clp.cpp:3389
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9124
#define SCIPisFinite(x)
Definition: pub_misc.h:1933
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9397
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11215
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10399
SCIP_Real SCIPcolGetMinPrimsol(SCIP_COL *col)
Definition: lp.c:17037
int SCIPcolGetLPPos(SCIP_COL *col)
Definition: lp.c:17121
int SCIPcolGetVarProbindex(SCIP_COL *col)
Definition: lp.c:17090
SCIP_Bool SCIPcolIsRemovable(SCIP_COL *col)
Definition: lp.c:17111
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17070
SCIP_Bool SCIPcolIsIntegral(SCIP_COL *col)
Definition: lp.c:17100
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16981
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:17154
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
Definition: lp.c:17189
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
Definition: lp.c:17179
void SCIPcolSort(SCIP_COL *col)
Definition: lp.c:3433
int SCIPcolGetIndex(SCIP_COL *col)
Definition: lp.c:17080
SCIP_Real SCIPcolGetBestBound(SCIP_COL *col)
Definition: lp.c:17011
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16991
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:17024
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:17001
SCIP_Longint SCIPcolGetStrongbranchNode(SCIP_COL *col)
Definition: lp.c:17201
int SCIPcolGetNLPNonz(SCIP_COL *col)
Definition: lp.c:17168
int SCIPcolGetNStrongbranchs(SCIP_COL *col)
Definition: lp.c:17211
int SCIPcolGetAge(SCIP_COL *col)
Definition: lp.c:17221
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:17143
int SCIPcolGetLPDepth(SCIP_COL *col)
Definition: lp.c:17132
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:17059
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17231
SCIP_Real SCIPcolGetMaxPrimsol(SCIP_COL *col)
Definition: lp.c:17047
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8234
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
void SCIPintervalSub(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Bool SCIProwIsIntegral(SCIP_ROW *row)
Definition: lp.c:17419
void SCIProwSort(SCIP_ROW *row)
Definition: lp.c:6014
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:17320
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:17439
SCIP_Longint SCIProwGetActiveLPCount(SCIP_ROW *row)
Definition: lp.c:17573
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:17540
SCIP_Real SCIProwGetParallelism(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7722
SCIP_CONS * SCIProwGetOriginCons(SCIP_ROW *row)
Definition: lp.c:17469
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17241
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:17266
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:17519
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:17330
int SCIProwGetAge(SCIP_ROW *row)
Definition: lp.c:17399
int SCIProwGetNLPNonz(SCIP_ROW *row)
Definition: lp.c:17255
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition: lp.c:17296
int SCIProwGetLPPos(SCIP_ROW *row)
Definition: lp.c:17529
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:17429
SCIP_CONSHDLR * SCIProwGetOriginConshdlr(SCIP_ROW *row)
Definition: lp.c:17484
SCIP_Longint SCIProwGetNLPsAfterCreation(SCIP_ROW *row)
Definition: lp.c:17583
void SCIProwLock(SCIP_ROW *row)
Definition: lp.c:5376
SCIP_Bool SCIProwIsRemovable(SCIP_ROW *row)
Definition: lp.c:17449
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:17379
SCIP_SEPA * SCIProwGetOriginSepa(SCIP_ROW *row)
Definition: lp.c:17504
void SCIProwUnlock(SCIP_ROW *row)
Definition: lp.c:5391
SCIP_Real SCIProwGetSumNorm(SCIP_ROW *row)
Definition: lp.c:17308
SCIP_DECL_SORTPTRCOMP(SCIProwComp)
Definition: lp.c:951
int SCIProwGetRank(SCIP_ROW *row)
Definition: lp.c:17409
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:17353
int SCIProwGetIndex(SCIP_ROW *row)
Definition: lp.c:17389
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition: lp.c:17562
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:17286
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:17551
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:17340
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:17276
SCIP_ROWORIGINTYPE SCIProwGetOrigintype(SCIP_ROW *row)
Definition: lp.c:17459
SCIP_BASESTAT SCIProwGetBasisStatus(SCIP_ROW *row)
Definition: lp.c:17368
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17816
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:18217
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17626
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17565
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:18171
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3416
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17953
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18115
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17795
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17446
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17637
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:18253
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:18161
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:18105
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3429
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18492
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17963
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:18243
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:15879
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17865
#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:13432
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:11578
SCIP_Real SCIPlpGetModifiedProvedPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: lp.c:13374
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:15270
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:16316
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:17704
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:15603
int SCIPlpGetNNewcols(SCIP_LP *lp)
Definition: lp.c:17671
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:18943
SCIP_Bool SCIPlpIsFeasGT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18892
SCIP_RETCODE SCIPlpIsInfeasibilityProved(SCIP_LP *lp, SCIP_SET *set, SCIP_Bool *proved)
Definition: lp.c:16533
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:11487
SCIP_Real SCIPlpGetLooseObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13160
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:13727
SCIP_Real SCIPlpGetObjNorm(SCIP_LP *lp)
Definition: lp.c:17735
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:15679
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:17885
#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:13921
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14332
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:16555
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:11994
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:13334
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:13894
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:13105
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:13180
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:17682
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:13204
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:13149
SCIP_RETCODE SCIPlpUpdateAddVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14030
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:17845
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:17812
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:17825
#define FEASTOLTIGHTFAC
Definition: lp.c:11575
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:12025
static int lpGetResolveItlim(SCIP_SET *set, SCIP_STAT *stat, int itlim)
Definition: lp.c:12393
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:12413
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:13121
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:15918
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:16409
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:15330
static SCIP_RETCODE lpRemoveObsoleteCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15527
SCIP_Real SCIPlpGetRootObjval(SCIP_LP *lp)
Definition: lp.c:17768
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:18912
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:11549
SCIP_RETCODE SCIPlpGetProvedLowerbound(SCIP_LP *lp, SCIP_SET *set, SCIP_Real *bound)
Definition: lp.c:16519
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:17895
SCIP_COL ** SCIPlpGetNewcols(SCIP_LP *lp)
Definition: lp.c:17660
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:11267
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:17802
SCIP_Bool SCIPlpIsFeasLT(SCIP_SET *set, SCIP_LP *lp, SCIP_Real val1, SCIP_Real val2)
Definition: lp.c:18852
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:14122
#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:15957
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17875
static void rowUpdateDelLP(SCIP_ROW *row)
Definition: lp.c:8975
void SCIPlpUnmarkDivingObjChanged(SCIP_LP *lp)
Definition: lp.c:17906
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:18631
#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:18703
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:14350
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:13645
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:17929
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:17792
SCIP_RETCODE SCIPlpGetDualfarkas(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool forcedlpsolve, SCIP_Bool *valid)
Definition: lp.c:15054
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:16319
static SCIP_RETCODE lpCleanupCols(SCIP_LP *lp, SCIP_SET *set, SCIP_STAT *stat, int firstcol)
Definition: lp.c:15741
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:11404
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:16373
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:15255
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:16343
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:14075
SCIP_RETCODE SCIPlpUpdateDelVar(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14051
void SCIPlpEndStrongbranchProbing(SCIP_LP *lp)
Definition: lp.c:16386
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:18932
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:15710
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:14254
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:14209
static void getObjvalDeltaUb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldub, SCIP_Real newub, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13604
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:17917
SCIP_RETCODE SCIPlpUpdateVarUbGlobal(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13962
static SCIP_RETCODE lpFlushAndSolve(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_EVENTQUEUE *eventqueue, int resolveitlim, int harditlim, SCIP_Bool needprimalray, SCIP_Bool needdualray, int fastmip, SCIP_Bool tightprimfeastol, SCIP_Bool tightdualfeastol, SCIP_Bool fromscratch, int scaling, SCIP_Bool keepsol, SCIP_Bool *lperror)
Definition: lp.c:12214
SCIP_RETCODE SCIPlpReset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter)
Definition: lp.c: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:16358
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:17758
SCIP_Bool SCIPlpIsSolved(SCIP_LP *lp)
Definition: lp.c:17835
SCIP_RETCODE SCIPlpUpdateVarUb(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub)
Definition: lp.c:13989
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:13840
static void lpNumericalTroubleMessage(SCIP_MESSAGEHDLR *messagehdlr, SCIP_SET *set, SCIP_STAT *stat, SCIP_VERBLEVEL verblevel, const char *formatstr,...)
Definition: lp.c:11496
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:14311
SCIP_Real SCIPlpGetGlobalPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13272
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:17855
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:16570
static void getObjvalDeltaLb(SCIP_SET *set, SCIP_Real obj, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real *deltaval, int *deltainf)
Definition: lp.c:13563
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:16031
SCIP_Bool SCIPlpIsFeasNegative(SCIP_LP *lp, SCIP_Real val)
Definition: lp.c:18954
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:16137
SCIP_COL ** SCIPlpGetCols(SCIP_LP *lp)
Definition: lp.c:17593
int SCIPlpGetNCols(SCIP_LP *lp)
Definition: lp.c:17603
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:17780
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:14667
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:18832
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:12304
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:17640
void SCIPlpSetRootLPIsRelax(SCIP_LP *lp, SCIP_Bool isrelax)
Definition: lp.c:17747
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:12331
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:17613
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:18872
int SCIPlpGetNNewrows(SCIP_LP *lp)
Definition: lp.c:17693
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:14993
#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:13193
int SCIPlpGetNRows(SCIP_LP *lp)
Definition: lp.c:17650
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:15808
SCIP_Real SCIPlpGetPseudoObjval(SCIP_LP *lp, SCIP_SET *set, SCIP_PROB *prob)
Definition: lp.c:13304
static SCIP_RETCODE lpDelRowset(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, int *rowdstat)
Definition: lp.c:15429
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:14187
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:13950
internal methods for problem variables